Forráskód Böngészése

Merge branch 'master' into debugger

Conflicts:
	js/Helios-Core.deploy.js
	js/Helios-Core.js
	js/Helios-KeyBindings.deploy.js
	js/Helios-KeyBindings.js
Nicolas Petton 10 éve
szülő
commit
c6a28649bd

+ 21 - 11
css/helios.css

@@ -35,7 +35,7 @@ html[xmlns] .clearfix {
   overflow: hidden;
   height: 100%;
   width: 100%;
-  /*background: #fff*/;
+  background: #fff;
 }
 #helios .CodeMirror-hints {
   border-radius: 0;
@@ -514,6 +514,9 @@ html[xmlns] .clearfix {
 #helios .key_helper .command {
   padding: 0 2px;
 }
+#helios .key_helper #binding-helper-main {
+  display: inline;
+}
 #helios .key_helper .label {
   padding: 1px 4px;
   font-family: Menlo, Monaco, "Lucida Console", Courier, monospace;
@@ -563,12 +566,12 @@ html[xmlns] .clearfix {
   color: #B91010;
   font-weight: bold;
 }
-#helios .typeahead.dropdown-menu {
+#helios .key_helper .typeahead.dropdown-menu {
   position: fixed !important;
   top: auto !important;
   bottom: 30px !important;
 }
-#helios #cog-helper {
+#helios .key_helper #cog-helper {
   position: fixed;
   bottom: 2px;
   right: 2px;
@@ -580,7 +583,7 @@ html[xmlns] .clearfix {
   -o-transition: all .5s;
   -ms-transition: all .5s;
 }
-#helios #cog-helper:hover {
+#helios .key_helper #cog-helper:hover {
   opacity: 1;
 }
 #helios #helper {
@@ -629,24 +632,31 @@ html[xmlns] .clearfix {
   -moz-transition: top .5s;
   -o-transition: top .5s;
 }
-#helios .confirmation.large,
-#helios .dialog.large {
+#helios .confirmation .title,
+#helios .dialog .title {
+  font-size: 16px;
+  margin-bottom: 15px;
+}
+#helios .confirmation .large,
+#helios .dialog .large {
   width: 400px;
   margin-left: -220px;
 }
+#helios .confirmation .large textarea,
+#helios .dialog .large textarea {
+  width: 385px;
+  height: 200px;
+}
 #helios .confirmation textarea,
 #helios .dialog textarea {
   display: block;
   width: 235px;
 }
-#helios .confirmation.large textarea,
-#helios .dialog.large textarea {
-  width: 385px;
-  height: 200px;
-}
+#helios .confirmation .progress,
 #helios .dialog .progress {
   height: 5px;
 }
+#helios .confirmation .progress .bar,
 #helios .dialog .progress .bar {
   background-color: #e9eaf5;
   background-image: -webkit-linear-gradient(top, #b1bdd5, #8999b8);

+ 116 - 112
css/helios.less

@@ -595,89 +595,94 @@ html[xmlns] .clearfix {
 	border-top: 1px solid #aaa;
 	font-size: 11px;
 	height: 22px;
-    }
 
-    .key_helper .command {
-	padding: 0 2px;
-    }
+	.command {
+	    padding: 0 2px;
+	}
 
-    .key_helper .label {
-	padding: 1px 4px;
-	font-family: Menlo, Monaco, "Lucida Console", Courier, monospace;
-	background: transparent;
-	color: #08C;
-	text-shadow: none;
-	border: 0 none;
-    }
+	#binding-helper-main {
+	    display: inline;
+	}
 
-    .key_helper .action {
-	padding: 0 5px;
-	color: #666;
-    }
+	.label {
+	    padding: 1px 4px;
+	    font-family: Menlo, Monaco, "Lucida Console", Courier, monospace;
+	    background: transparent;
+	    color: #08C;
+	    text-shadow: none;
+	    border: 0 none;
+	}
 
-    .key_helper .selected {
-	background-image: linear-gradient(top, #ccc, #aaa);
-	background-image: -moz-linear-gradient(top, #ccc, #aaa);
-	background-image: -o-linear-gradient(top, #ccc, #aaa);
-	background-image: -webkit-linear-gradient(top, #ccc, #aaa);
-	height: 30px;
-	padding: 0 8px;
-	color: #333;
-	font-weight: bold;
-	text-shadow: 0 1px 0 #fff;
-	display: inline-block;
-	border-right: 1px solid #aaa;
-    }
+	.action {
+	    padding: 0 5px;
+	    color: #666;
+	}
 
-    .key_helper .close {
-	font-size: 14px;
-	line-height: 26px;
-	opacity: 0.6;
-    }
+	.selected {
+	    background-image: linear-gradient(top, #ccc, #aaa);
+	    background-image: -moz-linear-gradient(top, #ccc, #aaa);
+	    background-image: -o-linear-gradient(top, #ccc, #aaa);
+	    background-image: -webkit-linear-gradient(top, #ccc, #aaa);
+	    height: 30px;
+	    padding: 0 8px;
+	    color: #333;
+	    font-weight: bold;
+	    text-shadow: 0 1px 0 #fff;
+	    display: inline-block;
+	    border-right: 1px solid #aaa;
+	}
 
-    .key_helper .close:hover {
-	opacity: 0.8;
-    }
+	.close {
+	    font-size: 14px;
+	    line-height: 26px;
+	    opacity: 0.6;
+	}
 
-    .key_helper input {
-	outline: none;
-	font-size: 11px;
-	padding: 2px 8px;
-	background: #fff;
-	border: 1px solid #a1a1a1;
-	border-radius: 12px;
-	box-shadow: inset 0 0px 2px 0px #aaa;
-	margin: 2px 4px;
-	line-height: 1em;
-    }
+	.close:hover {
+	    opacity: 0.8;
+	}
 
-    .key_helper .error .help-inline,
-    .key_helper .error input {
-	color: #B91010;
-	font-weight: bold;
-    }
+	input {
+	    outline: none;
+	    font-size: 11px;
+	    padding: 2px 8px;
+	    background: #fff;
+	    border: 1px solid #a1a1a1;
+	    border-radius: 12px;
+	    box-shadow: inset 0 0px 2px 0px #aaa;
+	    margin: 2px 4px;
+	    line-height: 1em;
+	}
 
-    .typeahead.dropdown-menu {
-	position: fixed !important;
-	top: auto !important;
-	bottom: 30px !important;
-    }
+	.error .help-inline,
+	.error input {
+	    color: #B91010;
+	    font-weight: bold;
+	}
 
-    #cog-helper {
-	position: fixed;
-	bottom: 2px;
-	right: 2px;
-	z-index: 1000;
-	opacity: 0.6;
-	transition: all .5s;
-	-webkit-transition: all .5s;
-	-moz-transition: all .5s;
-	-o-transition: all .5s;
-	-ms-transition: all .5s;
-    }
+	.typeahead.dropdown-menu {
+	    position: fixed !important;
+	    top: auto !important;
+	    bottom: 30px !important;
+	}
+
+	#cog-helper {
+	    position: fixed;
+	    bottom: 2px;
+	    right: 2px;
+	    z-index: 1000;
+	    opacity: 0.6;
+	    transition: all .5s;
+	    -webkit-transition: all .5s;
+	    -moz-transition: all .5s;
+	    -o-transition: all .5s;
+	    -ms-transition: all .5s;
+	}
+
+	#cog-helper:hover {
+	    opacity: 1;
+	}
 
-    #cog-helper:hover {
-	opacity: 1;
     }
 
     #helper {
@@ -726,54 +731,53 @@ html[xmlns] .clearfix {
 	-webkit-transition: top .5s;
 	-moz-transition: top .5s;
 	-o-transition: top .5s;
-    }
 
-    .confirmation.large,
-    .dialog.large {
-	width: 400px;
-	margin-left: -220px;
-    }
+	.title {
+	    font-size: 16px;
+	    margin-bottom: 15px;
+	}
 
-    .confirmation textarea,
-    .dialog textarea {
-	display: block;
-	width: 235px;
-    }
+	.large {
+	    width: 400px;
+	    margin-left: -220px;
 
-    .confirmation.large textarea,
-    .dialog.large textarea {
-	width: 385px;
-	height: 200px;
-    }
+	    textarea {
+		width: 385px;
+		height: 200px;
+	    }
+	}
 
-    .dialog .progress {
-	height: 5px;
-    }
+	textarea {
+	    display: block;
+	    width: 235px;
+	}
 
-    .dialog .progress .bar {
-	background-color: #e9eaf5;
-	background-image: -webkit-linear-gradient(top, #B1BDD5, #8999b8);
-	background-image: -moz-linear-gradient(top, #B1BDD5, #8999b8);
-	background-image: -o-linear-gradient(top, #B1BDD5, #8999b8);
-	background-image: linear-gradient(top, #B1BDD5, #8999b8);
-	
-    }
 
-    .confirmation span,
-    .dialog span {
-	font-size: 13px;
-	font-weight: bold;
-    }
+	.progress {
+	    height: 5px;
 
-    .confirmation .buttons,
-    .dialog .buttons {
-	text-align: right;
-	margin-top: 20px;
-    }
+	    .bar {
+		background-color: #e9eaf5;
+		background-image: -webkit-linear-gradient(top, #B1BDD5, #8999b8);
+		background-image: -moz-linear-gradient(top, #B1BDD5, #8999b8);
+		background-image: -o-linear-gradient(top, #B1BDD5, #8999b8);
+		background-image: linear-gradient(top, #B1BDD5, #8999b8);
+	    }
+	}
 
-    .confirmation.active,
-    .dialog.active {
-	top: 0;
+	span {
+	    font-size: 13px;
+	    font-weight: bold;
+	}
+
+	.buttons {
+	    text-align: right;
+	    margin-top: 20px;
+	}
+
+	&.active {
+	    top: 0;
+	}
     }
 
     .button {

BIN
images/overridden.png


BIN
images/override.png


+ 85 - 0
js/Helios-Commands-Core.deploy.js

@@ -615,6 +615,91 @@ messageSends: []}),
 smalltalk.HLOpenWorkspaceCommand.klass);
 
 
+smalltalk.addClass('HLSwitchTabCommand', smalltalk.HLCommand, [], 'Helios-Commands-Core');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+var activeTab;
+function $HLTabSelectionWidget(){return smalltalk.HLTabSelectionWidget||(typeof HLTabSelectionWidget=="undefined"?nil:HLTabSelectionWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+activeTab=self._selectedTab();
+$2=_st($HLTabSelectionWidget())._new();
+_st($2)._tabs_(self._tabs());
+_st($2)._selectedTab_(self._selectedTab());
+_st($2)._selectCallback_((function(tab){
+return smalltalk.withContext(function($ctx2) {
+return _st(tab)._activate();
+}, function($ctx2) {$ctx2.fillBlock({tab:tab},$ctx1,1)})}));
+_st($2)._confirmCallback_((function(tab){
+return smalltalk.withContext(function($ctx2) {
+return _st(tab)._focus();
+}, function($ctx2) {$ctx2.fillBlock({tab:tab},$ctx1,2)})}));
+_st($2)._cancelCallback_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(activeTab)._activate();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}));
+$3=_st($2)._show();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{activeTab:activeTab},smalltalk.HLSwitchTabCommand)})},
+messageSends: ["selectedTab", "tabs:", "new", "tabs", "selectedTab:", "selectCallback:", "activate", "confirmCallback:", "focus", "cancelCallback:", "show"]}),
+smalltalk.HLSwitchTabCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectedTab",
+fn: function (){
+var self=this;
+function $HLManager(){return smalltalk.HLManager||(typeof HLManager=="undefined"?nil:HLManager)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st($HLManager())._current())._activeTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectedTab",{},smalltalk.HLSwitchTabCommand)})},
+messageSends: ["activeTab", "current"]}),
+smalltalk.HLSwitchTabCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabs",
+fn: function (){
+var self=this;
+function $HLManager(){return smalltalk.HLManager||(typeof HLManager=="undefined"?nil:HLManager)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st($HLManager())._current())._tabs();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"tabs",{},smalltalk.HLSwitchTabCommand)})},
+messageSends: ["tabs", "current"]}),
+smalltalk.HLSwitchTabCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "s";
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLSwitchTabCommand.klass)})},
+messageSends: []}),
+smalltalk.HLSwitchTabCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Switch";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLSwitchTabCommand.klass)})},
+messageSends: []}),
+smalltalk.HLSwitchTabCommand.klass);
+
+
 smalltalk.addClass('HLViewCommand', smalltalk.HLCommand, [], 'Helios-Commands-Core');
 
 smalltalk.addMethod(

+ 110 - 0
js/Helios-Commands-Core.js

@@ -840,6 +840,116 @@ referencedClasses: []
 smalltalk.HLOpenWorkspaceCommand.klass);
 
 
+smalltalk.addClass('HLSwitchTabCommand', smalltalk.HLCommand, [], 'Helios-Commands-Core');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+var activeTab;
+function $HLTabSelectionWidget(){return smalltalk.HLTabSelectionWidget||(typeof HLTabSelectionWidget=="undefined"?nil:HLTabSelectionWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+activeTab=self._selectedTab();
+$2=_st($HLTabSelectionWidget())._new();
+_st($2)._tabs_(self._tabs());
+_st($2)._selectedTab_(self._selectedTab());
+_st($2)._selectCallback_((function(tab){
+return smalltalk.withContext(function($ctx2) {
+return _st(tab)._activate();
+}, function($ctx2) {$ctx2.fillBlock({tab:tab},$ctx1,1)})}));
+_st($2)._confirmCallback_((function(tab){
+return smalltalk.withContext(function($ctx2) {
+return _st(tab)._focus();
+}, function($ctx2) {$ctx2.fillBlock({tab:tab},$ctx1,2)})}));
+_st($2)._cancelCallback_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(activeTab)._activate();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}));
+$3=_st($2)._show();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{activeTab:activeTab},smalltalk.HLSwitchTabCommand)})},
+args: [],
+source: "execute\x0a\x09| activeTab |\x0a\x09\x0a\x09activeTab := self selectedTab.\x0a\x09\x0a\x09^ HLTabSelectionWidget new\x0a\x09\x09tabs: self tabs;\x0a\x09\x09selectedTab: self selectedTab;\x0a\x09\x09selectCallback: [ :tab | tab activate ];\x0a\x09\x09confirmCallback: [ :tab | tab focus ];\x0a\x09\x09cancelCallback: [ activeTab activate ];\x0a\x09\x09show",
+messageSends: ["selectedTab", "tabs:", "new", "tabs", "selectedTab:", "selectCallback:", "activate", "confirmCallback:", "focus", "cancelCallback:", "show"],
+referencedClasses: ["HLTabSelectionWidget"]
+}),
+smalltalk.HLSwitchTabCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectedTab",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $HLManager(){return smalltalk.HLManager||(typeof HLManager=="undefined"?nil:HLManager)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st($HLManager())._current())._activeTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectedTab",{},smalltalk.HLSwitchTabCommand)})},
+args: [],
+source: "selectedTab\x0a\x09^ HLManager current activeTab",
+messageSends: ["activeTab", "current"],
+referencedClasses: ["HLManager"]
+}),
+smalltalk.HLSwitchTabCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabs",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $HLManager(){return smalltalk.HLManager||(typeof HLManager=="undefined"?nil:HLManager)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st($HLManager())._current())._tabs();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"tabs",{},smalltalk.HLSwitchTabCommand)})},
+args: [],
+source: "tabs\x0a\x09^ HLManager current tabs",
+messageSends: ["tabs", "current"],
+referencedClasses: ["HLManager"]
+}),
+smalltalk.HLSwitchTabCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "s";
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLSwitchTabCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 's'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLSwitchTabCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Switch";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLSwitchTabCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Switch'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLSwitchTabCommand.klass);
+
+
 smalltalk.addClass('HLViewCommand', smalltalk.HLCommand, [], 'Helios-Commands-Core');
 
 smalltalk.addMethod(

+ 468 - 107
js/Helios-Core.deploy.js

@@ -1146,7 +1146,7 @@ smalltalk.HLTabWidget.klass);
 smalltalk.addClass('HLWidget', smalltalk.Widget, ['wrapper'], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({
-selector: "bindKeyDown:up:",
+selector: "bindKeyDown:keyUp:",
 fn: function (keyDownBlock,keyUpBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -1154,7 +1154,7 @@ var $1,$2;
 $1=_st(self._wrapper())._asJQuery();
 _st($1)._keydown_(keyDownBlock);
 $2=_st($1)._keyup_(keyUpBlock);
-return self}, function($ctx1) {$ctx1.fill(self,"bindKeyDown:up:",{keyDownBlock:keyDownBlock,keyUpBlock:keyUpBlock},smalltalk.HLWidget)})},
+return self}, function($ctx1) {$ctx1.fill(self,"bindKeyDown:keyUp:",{keyDownBlock:keyDownBlock,keyUpBlock:keyUpBlock},smalltalk.HLWidget)})},
 messageSends: ["keydown:", "asJQuery", "wrapper", "keyup:"]}),
 smalltalk.HLWidget);
 
@@ -1328,7 +1328,7 @@ smalltalk.HLWidget);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "unbindKeyDownUp",
+selector: "unbindKeyDownKeyUp",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -1336,7 +1336,7 @@ var $1,$2;
 $1=_st(self._wrapper())._asJQuery();
 _st($1)._unbind_("keydown");
 $2=_st($1)._unbind_("keyup");
-return self}, function($ctx1) {$ctx1.fill(self,"unbindKeyDownUp",{},smalltalk.HLWidget)})},
+return self}, function($ctx1) {$ctx1.fill(self,"unbindKeyDownKeyUp",{},smalltalk.HLWidget)})},
 messageSends: ["unbind:", "asJQuery", "wrapper"]}),
 smalltalk.HLWidget);
 
@@ -1914,21 +1914,21 @@ smalltalk.method({
 selector: "setupKeyBindings",
 fn: function (){
 var self=this;
-function $HLRepeatingKeyBindingHandler(){return smalltalk.HLRepeatingKeyBindingHandler||(typeof HLRepeatingKeyBindingHandler=="undefined"?nil:HLRepeatingKeyBindingHandler)}
+function $HLRepeatedKeyDownHandler(){return smalltalk.HLRepeatedKeyDownHandler||(typeof HLRepeatedKeyDownHandler=="undefined"?nil:HLRepeatedKeyDownHandler)}
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
-$1=_st($HLRepeatingKeyBindingHandler())._forWidget_(self);
-_st($1)._whileKeyPressed_do_((38),(function(){
+$1=_st($HLRepeatedKeyDownHandler())._on_(self);
+_st($1)._whileKeyDown_do_((38),(function(){
 return smalltalk.withContext(function($ctx2) {
 return self._activatePreviousListItem();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
-_st($1)._whileKeyPressed_do_((40),(function(){
+_st($1)._whileKeyDown_do_((40),(function(){
 return smalltalk.withContext(function($ctx2) {
 return self._activateNextListItem();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $2=_st($1)._rebindKeys();
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLListWidget)})},
-messageSends: ["whileKeyPressed:do:", "forWidget:", "activatePreviousListItem", "activateNextListItem", "rebindKeys"]}),
+messageSends: ["whileKeyDown:do:", "on:", "activatePreviousListItem", "activateNextListItem", "rebindKeys"]}),
 smalltalk.HLListWidget);
 
 
@@ -2333,7 +2333,64 @@ messageSends: ["model:", "new", "yourself"]}),
 smalltalk.HLToolListWidget.klass);
 
 
-smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'keyBinder', 'environment', 'history'], 'Helios-Core');
+smalltalk.addClass('HLTabListWidget', smalltalk.HLListWidget, ['callback'], 'Helios-Core');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "callback",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@callback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"callback",{},smalltalk.HLTabListWidget)})},
+messageSends: ["ifNil:"]}),
+smalltalk.HLTabListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "callback:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@callback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"callback:",{aBlock:aBlock},smalltalk.HLTabListWidget)})},
+messageSends: []}),
+smalltalk.HLTabListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderItemLabel:on:",
+fn: function (aTab,html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(html)._with_(_st(aTab)._label());
+return self}, function($ctx1) {$ctx1.fill(self,"renderItemLabel:on:",{aTab:aTab,html:html},smalltalk.HLTabListWidget)})},
+messageSends: ["with:", "label"]}),
+smalltalk.HLTabListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectItem:",
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabListWidget.superclass.fn.prototype._selectItem_.apply(_st(self), [aTab]);
+_st(self._callback())._value_(aTab);
+return self}, function($ctx1) {$ctx1.fill(self,"selectItem:",{aTab:aTab},smalltalk.HLTabListWidget)})},
+messageSends: ["selectItem:", "value:", "callback"]}),
+smalltalk.HLTabListWidget);
+
+
+
+smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'environment', 'history'], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "activate:",
@@ -2400,10 +2457,9 @@ var $1,$2;
 $1=_st($HLConfirmationWidget())._new();
 _st($1)._confirmationString_(aString);
 _st($1)._cancelBlock_(aBlock);
-$2=_st($1)._yourself();
-_st($2)._appendToJQuery_("body"._asJQuery());
+$2=_st($1)._show();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm:ifFalse:",{aString:aString,aBlock:aBlock},smalltalk.HLManager)})},
-messageSends: ["appendToJQuery:", "confirmationString:", "new", "cancelBlock:", "yourself", "asJQuery"]}),
+messageSends: ["confirmationString:", "new", "cancelBlock:", "show"]}),
 smalltalk.HLManager);
 
 smalltalk.addMethod(
@@ -2417,10 +2473,9 @@ var $1,$2;
 $1=_st($HLConfirmationWidget())._new();
 _st($1)._confirmationString_(aString);
 _st($1)._actionBlock_(aBlock);
-$2=_st($1)._yourself();
-_st($2)._appendToJQuery_("body"._asJQuery());
+$2=_st($1)._show();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm:ifTrue:",{aString:aString,aBlock:aBlock},smalltalk.HLManager)})},
-messageSends: ["appendToJQuery:", "confirmationString:", "new", "actionBlock:", "yourself", "asJQuery"]}),
+messageSends: ["confirmationString:", "new", "actionBlock:", "show"]}),
 smalltalk.HLManager);
 
 smalltalk.addMethod(
@@ -2542,17 +2597,11 @@ fn: function (){
 var self=this;
 function $HLKeyBinder(){return smalltalk.HLKeyBinder||(typeof HLKeyBinder=="undefined"?nil:HLKeyBinder)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@keyBinder"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@keyBinder"]=_st($HLKeyBinder())._new();
-$1=self["@keyBinder"];
-} else {
-$1=$2;
-};
+var $1;
+$1=_st($HLKeyBinder())._current();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"keyBinder",{},smalltalk.HLManager)})},
-messageSends: ["ifNil:", "new"]}),
+messageSends: ["current"]}),
 smalltalk.HLManager);
 
 smalltalk.addMethod(
@@ -2797,10 +2846,9 @@ $1=_st($HLRequestWidget())._new();
 _st($1)._confirmationString_(aString);
 _st($1)._actionBlock_(aBlock);
 _st($1)._value_(valueString);
-$2=_st($1)._yourself();
-_st($2)._appendToJQuery_("body"._asJQuery());
+$2=_st($1)._show();
 return self}, function($ctx1) {$ctx1.fill(self,"request:value:do:",{aString:aString,valueString:valueString,aBlock:aBlock},smalltalk.HLManager)})},
-messageSends: ["appendToJQuery:", "confirmationString:", "new", "actionBlock:", "value:", "yourself", "asJQuery"]}),
+messageSends: ["confirmationString:", "new", "actionBlock:", "value:", "show"]}),
 smalltalk.HLManager);
 
 smalltalk.addMethod(
@@ -2919,6 +2967,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"cancel",{},smalltalk.HLModalWidg
 messageSends: ["remove"]}),
 smalltalk.HLModalWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirm",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._remove();
+return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLModalWidget)})},
+messageSends: ["remove"]}),
+smalltalk.HLModalWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "cssClass",
@@ -2930,6 +2989,17 @@ return "";
 messageSends: []}),
 smalltalk.HLModalWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "hasButtons",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return true;
+}, function($ctx1) {$ctx1.fill(self,"hasButtons",{},smalltalk.HLModalWidget)})},
+messageSends: []}),
+smalltalk.HLModalWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "remove",
@@ -2951,9 +3021,34 @@ smalltalk.method({
 selector: "renderButtonsOn:",
 fn: function (html){
 var self=this;
+var confirmButton;
 return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLModalWidget)})},
-messageSends: []}),
+var $1,$3,$4,$5,$6,$2;
+$1=_st(html)._div();
+_st($1)._class_("buttons");
+$2=_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx2) {
+$3=_st(html)._button();
+_st($3)._class_("button");
+_st($3)._with_("Cancel");
+$4=_st($3)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._cancel();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)})}));
+$4;
+$5=_st(html)._button();
+_st($5)._class_("button default");
+_st($5)._with_("Confirm");
+$6=_st($5)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._confirm();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,3)})}));
+confirmButton=$6;
+return confirmButton;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
+_st(_st(confirmButton)._asJQuery())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html,confirmButton:confirmButton},smalltalk.HLModalWidget)})},
+messageSends: ["class:", "div", "with:", "button", "onClick:", "cancel", "confirm", "focus", "asJQuery"]}),
 smalltalk.HLModalWidget);
 
 smalltalk.addMethod(
@@ -2963,21 +3058,22 @@ fn: function (html){
 var self=this;
 var confirmButton;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$2;
+var $1,$3,$2;
 _st(_st(html)._div())._id_("overlay");
 $1=_st(html)._div();
 _st($1)._class_("dialog ".__comma(self._cssClass()));
 $2=_st($1)._with_((function(){
 return smalltalk.withContext(function($ctx2) {
-$3=self;
-_st($3)._renderMainOn_(html);
-$4=_st($3)._renderButtonsOn_(html);
-return $4;
+self._renderMainOn_(html);
+$3=self._hasButtons();
+if(smalltalk.assert($3)){
+return self._renderButtonsOn_(html);
+};
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
 _st(".dialog"._asJQuery())._addClass_("active");
 self._setupKeyBindings();
 return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html,confirmButton:confirmButton},smalltalk.HLModalWidget)})},
-messageSends: ["id:", "div", "class:", ",", "cssClass", "with:", "renderMainOn:", "renderButtonsOn:", "addClass:", "asJQuery", "setupKeyBindings"]}),
+messageSends: ["id:", "div", "class:", ",", "cssClass", "with:", "renderMainOn:", "ifTrue:", "hasButtons", "renderButtonsOn:", "addClass:", "asJQuery", "setupKeyBindings"]}),
 smalltalk.HLModalWidget);
 
 smalltalk.addMethod(
@@ -2995,17 +3091,29 @@ smalltalk.method({
 selector: "setupKeyBindings",
 fn: function (){
 var self=this;
+function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
 _st(".dialog"._asJQuery())._keyup_((function(e){
 return smalltalk.withContext(function($ctx2) {
-$1=_st(_st(e)._keyCode()).__eq((27));
+$1=_st(_st(e)._keyCode()).__eq(_st(_st($String())._esc())._asciiValue());
 if(smalltalk.assert($1)){
 return self._cancel();
 };
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1,1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLModalWidget)})},
-messageSends: ["keyup:", "asJQuery", "ifTrue:", "=", "keyCode", "cancel"]}),
+messageSends: ["keyup:", "asJQuery", "ifTrue:", "=", "keyCode", "asciiValue", "esc", "cancel"]}),
+smalltalk.HLModalWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "show",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._appendToJQuery_("body"._asJQuery());
+return self}, function($ctx1) {$ctx1.fill(self,"show",{},smalltalk.HLModalWidget)})},
+messageSends: ["appendToJQuery:", "asJQuery"]}),
 smalltalk.HLModalWidget);
 
 
@@ -3049,9 +3157,9 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 _st(self._cancelBlock())._value();
-self._remove();
+smalltalk.HLConfirmationWidget.superclass.fn.prototype._cancel.apply(_st(self), []);
 return self}, function($ctx1) {$ctx1.fill(self,"cancel",{},smalltalk.HLConfirmationWidget)})},
-messageSends: ["value", "cancelBlock", "remove"]}),
+messageSends: ["value", "cancelBlock", "cancel"]}),
 smalltalk.HLConfirmationWidget);
 
 smalltalk.addMethod(
@@ -3091,10 +3199,10 @@ selector: "confirm",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLConfirmationWidget.superclass.fn.prototype._confirm.apply(_st(self), []);
 _st(self._actionBlock())._value();
-self._remove();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLConfirmationWidget)})},
-messageSends: ["value", "actionBlock", "remove"]}),
+messageSends: ["confirm", "value", "actionBlock"]}),
 smalltalk.HLConfirmationWidget);
 
 smalltalk.addMethod(
@@ -3126,57 +3234,6 @@ return self}, function($ctx1) {$ctx1.fill(self,"confirmationString:",{aString:aS
 messageSends: []}),
 smalltalk.HLConfirmationWidget);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "remove",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(".dialog"._asJQuery())._removeClass_("active");
-_st((function(){
-return smalltalk.withContext(function($ctx2) {
-_st("#overlay"._asJQuery())._remove();
-return _st(".dialog"._asJQuery())._remove();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._valueWithTimeout_((300));
-return self}, function($ctx1) {$ctx1.fill(self,"remove",{},smalltalk.HLConfirmationWidget)})},
-messageSends: ["removeClass:", "asJQuery", "valueWithTimeout:", "remove"]}),
-smalltalk.HLConfirmationWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderButtonsOn:",
-fn: function (html){
-var self=this;
-var confirmButton;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$5,$6,$2;
-$1=_st(html)._div();
-_st($1)._class_("buttons");
-$2=_st($1)._with_((function(){
-return smalltalk.withContext(function($ctx2) {
-$3=_st(html)._button();
-_st($3)._class_("button");
-_st($3)._with_("Cancel");
-$4=_st($3)._onClick_((function(){
-return smalltalk.withContext(function($ctx3) {
-return self._cancel();
-}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)})}));
-$4;
-$5=_st(html)._button();
-_st($5)._class_("button default");
-_st($5)._with_("Confirm");
-$6=_st($5)._onClick_((function(){
-return smalltalk.withContext(function($ctx3) {
-return self._confirm();
-}, function($ctx3) {$ctx3.fillBlock({},$ctx2,3)})}));
-confirmButton=$6;
-return confirmButton;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
-_st(_st(confirmButton)._asJQuery())._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html,confirmButton:confirmButton},smalltalk.HLConfirmationWidget)})},
-messageSends: ["class:", "div", "with:", "button", "onClick:", "cancel", "confirm", "focus", "asJQuery"]}),
-smalltalk.HLConfirmationWidget);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderMainOn:",
@@ -3197,10 +3254,10 @@ selector: "confirm",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLRequestWidget.superclass.fn.prototype._confirm.apply(_st(self), []);
 _st(self._actionBlock())._value_(_st(_st(self["@input"])._asJQuery())._val());
-self._remove();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLRequestWidget)})},
-messageSends: ["value:", "actionBlock", "val", "asJQuery", "remove"]}),
+messageSends: ["confirm", "value:", "actionBlock", "val", "asJQuery"]}),
 smalltalk.HLRequestWidget);
 
 smalltalk.addMethod(
@@ -3308,6 +3365,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"flush",{},smalltalk.HLProgressWi
 messageSends: ["do:", "progressBars", "removeProgressBar:"]}),
 smalltalk.HLProgressWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "hasButtons",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return false;
+}, function($ctx1) {$ctx1.fill(self,"hasButtons",{},smalltalk.HLProgressWidget)})},
+messageSends: []}),
+smalltalk.HLProgressWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "isVisible",
@@ -3381,16 +3449,6 @@ return self}, function($ctx1) {$ctx1.fill(self,"removeProgressBar:",{aProgressBa
 messageSends: ["remove:ifAbsent:", "progressBars", "remove", "asJQuery", "wrapper", "ifEmpty:"]}),
 smalltalk.HLProgressWidget);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderButtonsOn:",
-fn: function (html){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLProgressWidget)})},
-messageSends: []}),
-smalltalk.HLProgressWidget);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderMainOn:",
@@ -3416,10 +3474,10 @@ $1=self._isVisible();
 if(! smalltalk.assert($1)){
 self["@visible"]=true;
 self["@visible"];
-self._appendToJQuery_("body"._asJQuery());
+smalltalk.HLProgressWidget.superclass.fn.prototype._show.apply(_st(self), []);
 };
 return self}, function($ctx1) {$ctx1.fill(self,"show",{},smalltalk.HLProgressWidget)})},
-messageSends: ["ifFalse:", "isVisible", "appendToJQuery:", "asJQuery"]}),
+messageSends: ["ifFalse:", "isVisible", "show"]}),
 smalltalk.HLProgressWidget);
 
 
@@ -3444,6 +3502,309 @@ messageSends: ["ifNil:", "new"]}),
 smalltalk.HLProgressWidget.klass);
 
 
+smalltalk.addClass('HLTabSelectionWidget', smalltalk.HLModalWidget, ['tabs', 'tabList', 'selectedTab', 'selectCallback', 'cancelCallback', 'confirmCallback'], 'Helios-Core');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cancel",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._cancel.apply(_st(self), []);
+_st(self._cancelCallback())._value();
+return self}, function($ctx1) {$ctx1.fill(self,"cancel",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["cancel", "value", "cancelCallback"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cancelCallback",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@cancelCallback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"cancelCallback",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["ifNil:"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cancelCallback:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@cancelCallback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"cancelCallback:",{aBlock:aBlock},smalltalk.HLTabSelectionWidget)})},
+messageSends: []}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirm",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._confirm.apply(_st(self), []);
+_st(self._confirmCallback())._value_(self._selectedTab());
+return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["confirm", "value:", "confirmCallback", "selectedTab"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirmCallback",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@confirmCallback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"confirmCallback",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["ifNil:"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirmCallback:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@confirmCallback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"confirmCallback:",{aBlock:aBlock},smalltalk.HLTabSelectionWidget)})},
+messageSends: []}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderContentOn:",
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._renderContentOn_.apply(_st(self), [html]);
+_st(self._tabList())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["renderContentOn:", "focus", "tabList"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderMainOn:",
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(html)._div();
+_st($1)._class_("title");
+$2=_st($1)._with_("Tab selection");
+_st(html)._with_(self._tabList());
+return self}, function($ctx1) {$ctx1.fill(self,"renderMainOn:",{html:html},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["class:", "div", "with:", "tabList"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderTab:on:",
+fn: function (aTab,html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(html)._span();
+_st($1)._class_(_st(aTab)._cssClass());
+$2=_st($1)._with_(_st(aTab)._label());
+return self}, function($ctx1) {$ctx1.fill(self,"renderTab:on:",{aTab:aTab,html:html},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["class:", "span", "cssClass", "with:", "label"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderTabsOn:",
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self._tabs())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(html)._li())._with_((function(){
+return smalltalk.withContext(function($ctx3) {
+$1=_st(html)._a();
+_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx4) {
+return self._renderTab_on_(each,html);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx3,3)})}));
+$2=_st($1)._onClick_((function(){
+return smalltalk.withContext(function($ctx4) {
+return self._selectTab_(each);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx3,4)})}));
+return $2;
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"renderTabsOn:",{html:html},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["do:", "tabs", "with:", "li", "a", "renderTab:on:", "onClick:", "selectTab:"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectCallback",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@selectCallback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectCallback",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["ifNil:"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectCallback:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@selectCallback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"selectCallback:",{aBlock:aBlock},smalltalk.HLTabSelectionWidget)})},
+messageSends: []}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectTab:",
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._selectedTab_(aTab);
+_st(self._selectCallback())._value_(aTab);
+return self}, function($ctx1) {$ctx1.fill(self,"selectTab:",{aTab:aTab},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["selectedTab:", "value:", "selectCallback"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectedTab",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@selectedTab"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectedTab",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: []}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectedTab:",
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@selectedTab"]=aTab;
+return self}, function($ctx1) {$ctx1.fill(self,"selectedTab:",{aTab:aTab},smalltalk.HLTabSelectionWidget)})},
+messageSends: []}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "setupKeyBindings",
+fn: function (){
+var self=this;
+function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._setupKeyBindings.apply(_st(self), []);
+_st(".dialog"._asJQuery())._keyup_((function(e){
+return smalltalk.withContext(function($ctx2) {
+$1=_st(_st(e)._keyCode()).__eq(_st(_st($String())._cr())._asciiValue());
+if(smalltalk.assert($1)){
+return self._confirm();
+};
+}, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1,1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["setupKeyBindings", "keyup:", "asJQuery", "ifTrue:", "=", "keyCode", "asciiValue", "cr", "confirm"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabList",
+fn: function (){
+var self=this;
+function $HLTabListWidget(){return smalltalk.HLTabListWidget||(typeof HLTabListWidget=="undefined"?nil:HLTabListWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3,$4;
+$1=self["@tabList"];
+if(($receiver = $1) == nil || $receiver == undefined){
+self["@tabList"]=_st($HLTabListWidget())._new();
+self["@tabList"];
+$2=self["@tabList"];
+_st($2)._callback_((function(tab){
+return smalltalk.withContext(function($ctx2) {
+self._selectTab_(tab);
+return _st(self["@tabList"])._focus();
+}, function($ctx2) {$ctx2.fillBlock({tab:tab},$ctx1,2)})}));
+_st($2)._selectedItem_(self._selectedTab());
+$3=_st($2)._items_(self._tabs());
+$3;
+} else {
+$1;
+};
+$4=self["@tabList"];
+return $4;
+}, function($ctx1) {$ctx1.fill(self,"tabList",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["ifNil:", "new", "callback:", "selectTab:", "focus", "selectedItem:", "selectedTab", "items:", "tabs"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabs",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@tabs"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=[];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"tabs",{},smalltalk.HLTabSelectionWidget)})},
+messageSends: ["ifNil:"]}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabs:",
+fn: function (aCollection){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@tabs"]=aCollection;
+return self}, function($ctx1) {$ctx1.fill(self,"tabs:",{aCollection:aCollection},smalltalk.HLTabSelectionWidget)})},
+messageSends: []}),
+smalltalk.HLTabSelectionWidget);
+
+
+
 smalltalk.addClass('HLProgressBarWidget', smalltalk.HLWidget, ['label', 'parent', 'workBlock', 'collection', 'bar'], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({

+ 620 - 137
js/Helios-Core.js

@@ -1501,7 +1501,7 @@ smalltalk.addClass('HLWidget', smalltalk.Widget, ['wrapper'], 'Helios-Core');
 smalltalk.HLWidget.comment="I am the abstract superclass of all Helios widgets.\x0a\x0aI provide common methods, additional behavior to widgets useful for Helios, like dialog creation, command execution and tab creation.\x0a\x0a## API\x0a\x0a1. Rendering\x0a\x0a    Instead of overriding `#renderOn:` as with other Widget subclasses, my subclasses should override `#renderContentOn:`.\x0a\x0a2. Refreshing\x0a\x0a    To re-render a widget, use `#refresh`.\x0a\x0a3. Key bindings registration and tabs\x0a\x0a    When displayed as a tab, the widget has a chance to register keybindings with the `#registerBindingsOn:` hook method.\x0a    \x0a4. Unregistration\x0a\x0a    When a widget has subscribed to announcements or other actions that need to be cleared when closing the tab, the hook method `#unregister` will be called by helios.\x0a\x0a5. Tabs\x0a\x0a   To enable a widget class to be open as a tab, override the class-side `#canBeOpenAsTab` method to answer `true`. `#tabClass` and `#tabPriority` can be overridden too to respectively change the css class of the tab and the order of tabs in the main menu.\x0a\x0a6. Command execution\x0a\x0a    An helios command (instance of `HLCommand` or one of its subclass) can be executed with `#execute:`.";
 smalltalk.addMethod(
 smalltalk.method({
-selector: "bindKeyDown:up:",
+selector: "bindKeyDown:keyUp:",
 category: 'keybindings',
 fn: function (keyDownBlock,keyUpBlock){
 var self=this;
@@ -1510,9 +1510,9 @@ var $1,$2;
 $1=_st(self._wrapper())._asJQuery();
 _st($1)._keydown_(keyDownBlock);
 $2=_st($1)._keyup_(keyUpBlock);
-return self}, function($ctx1) {$ctx1.fill(self,"bindKeyDown:up:",{keyDownBlock:keyDownBlock,keyUpBlock:keyUpBlock},smalltalk.HLWidget)})},
+return self}, function($ctx1) {$ctx1.fill(self,"bindKeyDown:keyUp:",{keyDownBlock:keyDownBlock,keyUpBlock:keyUpBlock},smalltalk.HLWidget)})},
 args: ["keyDownBlock", "keyUpBlock"],
-source: "bindKeyDown: keyDownBlock up: keyUpBlock\x0a\x09self wrapper asJQuery\x0a\x09\x09keydown: keyDownBlock;\x0a\x09\x09keyup: keyUpBlock",
+source: "bindKeyDown: keyDownBlock keyUp: keyUpBlock\x0a\x09self wrapper asJQuery\x0a\x09\x09keydown: keyDownBlock;\x0a\x09\x09keyup: keyUpBlock",
 messageSends: ["keydown:", "asJQuery", "wrapper", "keyup:"],
 referencedClasses: []
 }),
@@ -1753,7 +1753,7 @@ smalltalk.HLWidget);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "unbindKeyDownUp",
+selector: "unbindKeyDownKeyUp",
 category: 'keybindings',
 fn: function (){
 var self=this;
@@ -1762,9 +1762,9 @@ var $1,$2;
 $1=_st(self._wrapper())._asJQuery();
 _st($1)._unbind_("keydown");
 $2=_st($1)._unbind_("keyup");
-return self}, function($ctx1) {$ctx1.fill(self,"unbindKeyDownUp",{},smalltalk.HLWidget)})},
+return self}, function($ctx1) {$ctx1.fill(self,"unbindKeyDownKeyUp",{},smalltalk.HLWidget)})},
 args: [],
-source: "unbindKeyDownUp\x0a\x09self wrapper asJQuery\x0a\x09\x09unbind: 'keydown';\x0a\x09\x09unbind: 'keyup'",
+source: "unbindKeyDownKeyUp\x0a\x09self wrapper asJQuery\x0a\x09\x09unbind: 'keydown';\x0a\x09\x09unbind: 'keyup'",
 messageSends: ["unbind:", "asJQuery", "wrapper"],
 referencedClasses: []
 }),
@@ -2536,24 +2536,24 @@ selector: "setupKeyBindings",
 category: 'events',
 fn: function (){
 var self=this;
-function $HLRepeatingKeyBindingHandler(){return smalltalk.HLRepeatingKeyBindingHandler||(typeof HLRepeatingKeyBindingHandler=="undefined"?nil:HLRepeatingKeyBindingHandler)}
+function $HLRepeatedKeyDownHandler(){return smalltalk.HLRepeatedKeyDownHandler||(typeof HLRepeatedKeyDownHandler=="undefined"?nil:HLRepeatedKeyDownHandler)}
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
-$1=_st($HLRepeatingKeyBindingHandler())._forWidget_(self);
-_st($1)._whileKeyPressed_do_((38),(function(){
+$1=_st($HLRepeatedKeyDownHandler())._on_(self);
+_st($1)._whileKeyDown_do_((38),(function(){
 return smalltalk.withContext(function($ctx2) {
 return self._activatePreviousListItem();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
-_st($1)._whileKeyPressed_do_((40),(function(){
+_st($1)._whileKeyDown_do_((40),(function(){
 return smalltalk.withContext(function($ctx2) {
 return self._activateNextListItem();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $2=_st($1)._rebindKeys();
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLListWidget)})},
 args: [],
-source: "setupKeyBindings \x0a\x09(HLRepeatingKeyBindingHandler forWidget: self)\x0a\x09\x09whileKeyPressed: 38 do: [ self activatePreviousListItem ];\x0a\x09\x09whileKeyPressed: 40 do: [ self activateNextListItem ];\x0a\x09\x09rebindKeys",
-messageSends: ["whileKeyPressed:do:", "forWidget:", "activatePreviousListItem", "activateNextListItem", "rebindKeys"],
-referencedClasses: ["HLRepeatingKeyBindingHandler"]
+source: "setupKeyBindings \x0a\x09(HLRepeatedKeyDownHandler on: self)\x0a\x09\x09whileKeyDown: 38 do: [ self activatePreviousListItem ];\x0a\x09\x09whileKeyDown: 40 do: [ self activateNextListItem ];\x0a\x09\x09rebindKeys",
+messageSends: ["whileKeyDown:do:", "on:", "activatePreviousListItem", "activateNextListItem", "rebindKeys"],
+referencedClasses: ["HLRepeatedKeyDownHandler"]
 }),
 smalltalk.HLListWidget);
 
@@ -3079,7 +3079,85 @@ referencedClasses: []
 smalltalk.HLToolListWidget.klass);
 
 
-smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'keyBinder', 'environment', 'history'], 'Helios-Core');
+smalltalk.addClass('HLTabListWidget', smalltalk.HLListWidget, ['callback'], 'Helios-Core');
+smalltalk.HLTabListWidget.comment="I am a widget used to display a list of helios tabs.\x0a\x0aWhen a tab is selected, `callback` is evaluated with the selected tab as argument.";
+smalltalk.addMethod(
+smalltalk.method({
+selector: "callback",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@callback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"callback",{},smalltalk.HLTabListWidget)})},
+args: [],
+source: "callback\x0a\x09^ callback ifNil: [ [] ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.HLTabListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "callback:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@callback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"callback:",{aBlock:aBlock},smalltalk.HLTabListWidget)})},
+args: ["aBlock"],
+source: "callback: aBlock\x0a\x09callback := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLTabListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderItemLabel:on:",
+category: 'rendering',
+fn: function (aTab,html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(html)._with_(_st(aTab)._label());
+return self}, function($ctx1) {$ctx1.fill(self,"renderItemLabel:on:",{aTab:aTab,html:html},smalltalk.HLTabListWidget)})},
+args: ["aTab", "html"],
+source: "renderItemLabel: aTab on: html\x0a\x09html with: aTab label",
+messageSends: ["with:", "label"],
+referencedClasses: []
+}),
+smalltalk.HLTabListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectItem:",
+category: 'actions',
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabListWidget.superclass.fn.prototype._selectItem_.apply(_st(self), [aTab]);
+_st(self._callback())._value_(aTab);
+return self}, function($ctx1) {$ctx1.fill(self,"selectItem:",{aTab:aTab},smalltalk.HLTabListWidget)})},
+args: ["aTab"],
+source: "selectItem: aTab\x0a\x09super selectItem: aTab.\x0a\x09self callback value: aTab",
+messageSends: ["selectItem:", "value:", "callback"],
+referencedClasses: []
+}),
+smalltalk.HLTabListWidget);
+
+
+
+smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'environment', 'history'], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "activate:",
@@ -3167,12 +3245,11 @@ var $1,$2;
 $1=_st($HLConfirmationWidget())._new();
 _st($1)._confirmationString_(aString);
 _st($1)._cancelBlock_(aBlock);
-$2=_st($1)._yourself();
-_st($2)._appendToJQuery_("body"._asJQuery());
+$2=_st($1)._show();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm:ifFalse:",{aString:aString,aBlock:aBlock},smalltalk.HLManager)})},
 args: ["aString", "aBlock"],
-source: "confirm: aString ifFalse: aBlock\x0a\x09(HLConfirmationWidget new\x0a\x09\x09confirmationString: aString;\x0a\x09\x09cancelBlock: aBlock;\x0a\x09\x09yourself)\x0a\x09\x09\x09appendToJQuery: 'body' asJQuery",
-messageSends: ["appendToJQuery:", "confirmationString:", "new", "cancelBlock:", "yourself", "asJQuery"],
+source: "confirm: aString ifFalse: aBlock\x0a\x09HLConfirmationWidget new\x0a\x09\x09confirmationString: aString;\x0a\x09\x09cancelBlock: aBlock;\x0a\x09\x09show",
+messageSends: ["confirmationString:", "new", "cancelBlock:", "show"],
 referencedClasses: ["HLConfirmationWidget"]
 }),
 smalltalk.HLManager);
@@ -3189,12 +3266,11 @@ var $1,$2;
 $1=_st($HLConfirmationWidget())._new();
 _st($1)._confirmationString_(aString);
 _st($1)._actionBlock_(aBlock);
-$2=_st($1)._yourself();
-_st($2)._appendToJQuery_("body"._asJQuery());
+$2=_st($1)._show();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm:ifTrue:",{aString:aString,aBlock:aBlock},smalltalk.HLManager)})},
 args: ["aString", "aBlock"],
-source: "confirm: aString ifTrue: aBlock\x0a\x09(HLConfirmationWidget new\x0a\x09\x09confirmationString: aString;\x0a\x09\x09actionBlock: aBlock;\x0a\x09\x09yourself)\x0a\x09\x09\x09appendToJQuery: 'body' asJQuery",
-messageSends: ["appendToJQuery:", "confirmationString:", "new", "actionBlock:", "yourself", "asJQuery"],
+source: "confirm: aString ifTrue: aBlock\x0a\x09HLConfirmationWidget new\x0a\x09\x09confirmationString: aString;\x0a\x09\x09actionBlock: aBlock;\x0a\x09\x09show",
+messageSends: ["confirmationString:", "new", "actionBlock:", "show"],
 referencedClasses: ["HLConfirmationWidget"]
 }),
 smalltalk.HLManager);
@@ -3349,19 +3425,13 @@ fn: function (){
 var self=this;
 function $HLKeyBinder(){return smalltalk.HLKeyBinder||(typeof HLKeyBinder=="undefined"?nil:HLKeyBinder)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@keyBinder"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@keyBinder"]=_st($HLKeyBinder())._new();
-$1=self["@keyBinder"];
-} else {
-$1=$2;
-};
+var $1;
+$1=_st($HLKeyBinder())._current();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"keyBinder",{},smalltalk.HLManager)})},
 args: [],
-source: "keyBinder\x0a\x09^ keyBinder ifNil: [ keyBinder := HLKeyBinder new ]",
-messageSends: ["ifNil:", "new"],
+source: "keyBinder\x0a\x09^ HLKeyBinder current",
+messageSends: ["current"],
 referencedClasses: ["HLKeyBinder"]
 }),
 smalltalk.HLManager);
@@ -3664,12 +3734,11 @@ $1=_st($HLRequestWidget())._new();
 _st($1)._confirmationString_(aString);
 _st($1)._actionBlock_(aBlock);
 _st($1)._value_(valueString);
-$2=_st($1)._yourself();
-_st($2)._appendToJQuery_("body"._asJQuery());
+$2=_st($1)._show();
 return self}, function($ctx1) {$ctx1.fill(self,"request:value:do:",{aString:aString,valueString:valueString,aBlock:aBlock},smalltalk.HLManager)})},
 args: ["aString", "valueString", "aBlock"],
-source: "request: aString value: valueString do: aBlock\x0a\x09(HLRequestWidget new\x0a\x09\x09confirmationString: aString;\x0a\x09\x09actionBlock: aBlock;\x0a\x09\x09value: valueString;\x0a\x09\x09yourself)\x0a\x09\x09\x09appendToJQuery: 'body' asJQuery",
-messageSends: ["appendToJQuery:", "confirmationString:", "new", "actionBlock:", "value:", "yourself", "asJQuery"],
+source: "request: aString value: valueString do: aBlock\x0a\x09HLRequestWidget new\x0a\x09\x09confirmationString: aString;\x0a\x09\x09actionBlock: aBlock;\x0a\x09\x09value: valueString;\x0a\x09\x09show",
+messageSends: ["confirmationString:", "new", "actionBlock:", "value:", "show"],
 referencedClasses: ["HLRequestWidget"]
 }),
 smalltalk.HLManager);
@@ -3826,6 +3895,22 @@ referencedClasses: []
 }),
 smalltalk.HLModalWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirm",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._remove();
+return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLModalWidget)})},
+args: [],
+source: "confirm\x0a\x09\x22Override in subclasses\x22\x0a\x09self remove",
+messageSends: ["remove"],
+referencedClasses: []
+}),
+smalltalk.HLModalWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "cssClass",
@@ -3842,6 +3927,22 @@ referencedClasses: []
 }),
 smalltalk.HLModalWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "hasButtons",
+category: 'rendering',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return true;
+}, function($ctx1) {$ctx1.fill(self,"hasButtons",{},smalltalk.HLModalWidget)})},
+args: [],
+source: "hasButtons\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLModalWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "remove",
@@ -3869,11 +3970,36 @@ selector: "renderButtonsOn:",
 category: 'rendering',
 fn: function (html){
 var self=this;
+var confirmButton;
 return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLModalWidget)})},
+var $1,$3,$4,$5,$6,$2;
+$1=_st(html)._div();
+_st($1)._class_("buttons");
+$2=_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx2) {
+$3=_st(html)._button();
+_st($3)._class_("button");
+_st($3)._with_("Cancel");
+$4=_st($3)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._cancel();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)})}));
+$4;
+$5=_st(html)._button();
+_st($5)._class_("button default");
+_st($5)._with_("Confirm");
+$6=_st($5)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._confirm();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,3)})}));
+confirmButton=$6;
+return confirmButton;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
+_st(_st(confirmButton)._asJQuery())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html,confirmButton:confirmButton},smalltalk.HLModalWidget)})},
 args: ["html"],
-source: "renderButtonsOn: html",
-messageSends: [],
+source: "renderButtonsOn: html\x0a\x09| confirmButton |\x0a\x09\x0a\x09html div \x0a\x09\x09class: 'buttons';\x0a\x09\x09with: [\x0a\x09\x09\x09html button\x0a\x09\x09\x09\x09class: 'button';\x0a\x09\x09\x09\x09with: 'Cancel';\x0a\x09\x09\x09\x09onClick: [ self cancel ].\x0a\x09\x09\x09confirmButton := html button\x0a\x09\x09\x09\x09class: 'button default';\x0a\x09\x09\x09\x09with: 'Confirm';\x0a\x09\x09\x09\x09onClick: [ self confirm ] ].\x0a\x0a\x09confirmButton asJQuery focus",
+messageSends: ["class:", "div", "with:", "button", "onClick:", "cancel", "confirm", "focus", "asJQuery"],
 referencedClasses: []
 }),
 smalltalk.HLModalWidget);
@@ -3886,23 +4012,24 @@ fn: function (html){
 var self=this;
 var confirmButton;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$2;
+var $1,$3,$2;
 _st(_st(html)._div())._id_("overlay");
 $1=_st(html)._div();
 _st($1)._class_("dialog ".__comma(self._cssClass()));
 $2=_st($1)._with_((function(){
 return smalltalk.withContext(function($ctx2) {
-$3=self;
-_st($3)._renderMainOn_(html);
-$4=_st($3)._renderButtonsOn_(html);
-return $4;
+self._renderMainOn_(html);
+$3=self._hasButtons();
+if(smalltalk.assert($3)){
+return self._renderButtonsOn_(html);
+};
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
 _st(".dialog"._asJQuery())._addClass_("active");
 self._setupKeyBindings();
 return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html,confirmButton:confirmButton},smalltalk.HLModalWidget)})},
 args: ["html"],
-source: "renderContentOn: html\x0a\x09| confirmButton |\x0a\x09\x0a\x09html div id: 'overlay'.\x0a\x09html div \x0a\x09\x09class: 'dialog ', self cssClass;\x0a\x09\x09with: [\x0a\x09\x09\x09self\x0a\x09\x09\x09\x09renderMainOn: html;\x0a\x09\x09\x09\x09renderButtonsOn: html ].\x0a\x0a\x09'.dialog' asJQuery addClass: 'active'.\x0a\x09self setupKeyBindings",
-messageSends: ["id:", "div", "class:", ",", "cssClass", "with:", "renderMainOn:", "renderButtonsOn:", "addClass:", "asJQuery", "setupKeyBindings"],
+source: "renderContentOn: html\x0a\x09| confirmButton |\x0a\x09\x0a\x09html div id: 'overlay'.\x0a\x09html div \x0a\x09\x09class: 'dialog ', self cssClass;\x0a\x09\x09with: [\x0a\x09\x09\x09self renderMainOn: html.\x0a\x09\x09\x09self hasButtons ifTrue: [ \x0a\x09\x09\x09\x09self renderButtonsOn: html ] ].\x0a\x0a\x09'.dialog' asJQuery addClass: 'active'.\x0a\x09self setupKeyBindings",
+messageSends: ["id:", "div", "class:", ",", "cssClass", "with:", "renderMainOn:", "ifTrue:", "hasButtons", "renderButtonsOn:", "addClass:", "asJQuery", "setupKeyBindings"],
 referencedClasses: []
 }),
 smalltalk.HLModalWidget);
@@ -3928,19 +4055,36 @@ selector: "setupKeyBindings",
 category: 'rendering',
 fn: function (){
 var self=this;
+function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
 _st(".dialog"._asJQuery())._keyup_((function(e){
 return smalltalk.withContext(function($ctx2) {
-$1=_st(_st(e)._keyCode()).__eq((27));
+$1=_st(_st(e)._keyCode()).__eq(_st(_st($String())._esc())._asciiValue());
 if(smalltalk.assert($1)){
 return self._cancel();
 };
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1,1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLModalWidget)})},
 args: [],
-source: "setupKeyBindings\x0a\x09'.dialog' asJQuery keyup: [ :e |\x0a\x09\x09e keyCode = 27 ifTrue: [ self cancel ] ]",
-messageSends: ["keyup:", "asJQuery", "ifTrue:", "=", "keyCode", "cancel"],
+source: "setupKeyBindings\x0a\x09'.dialog' asJQuery keyup: [ :e |\x0a\x09\x09e keyCode = String esc asciiValue ifTrue: [ self cancel ] ]",
+messageSends: ["keyup:", "asJQuery", "ifTrue:", "=", "keyCode", "asciiValue", "esc", "cancel"],
+referencedClasses: ["String"]
+}),
+smalltalk.HLModalWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "show",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._appendToJQuery_("body"._asJQuery());
+return self}, function($ctx1) {$ctx1.fill(self,"show",{},smalltalk.HLModalWidget)})},
+args: [],
+source: "show\x0a\x09self appendToJQuery: 'body' asJQuery",
+messageSends: ["appendToJQuery:", "asJQuery"],
 referencedClasses: []
 }),
 smalltalk.HLModalWidget);
@@ -3998,11 +4142,11 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 _st(self._cancelBlock())._value();
-self._remove();
+smalltalk.HLConfirmationWidget.superclass.fn.prototype._cancel.apply(_st(self), []);
 return self}, function($ctx1) {$ctx1.fill(self,"cancel",{},smalltalk.HLConfirmationWidget)})},
 args: [],
-source: "cancel\x0a\x09self cancelBlock value.\x0a\x09self remove",
-messageSends: ["value", "cancelBlock", "remove"],
+source: "cancel\x0a\x09self cancelBlock value.\x0a\x09super cancel",
+messageSends: ["value", "cancelBlock", "cancel"],
 referencedClasses: []
 }),
 smalltalk.HLConfirmationWidget);
@@ -4055,12 +4199,12 @@ category: 'actions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLConfirmationWidget.superclass.fn.prototype._confirm.apply(_st(self), []);
 _st(self._actionBlock())._value();
-self._remove();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLConfirmationWidget)})},
 args: [],
-source: "confirm\x0a\x09self actionBlock value.\x0a\x09self remove",
-messageSends: ["value", "actionBlock", "remove"],
+source: "confirm\x0a\x09super confirm.\x0a\x09self actionBlock value",
+messageSends: ["confirm", "value", "actionBlock"],
 referencedClasses: []
 }),
 smalltalk.HLConfirmationWidget);
@@ -4104,67 +4248,6 @@ referencedClasses: []
 }),
 smalltalk.HLConfirmationWidget);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "remove",
-category: 'actions',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(".dialog"._asJQuery())._removeClass_("active");
-_st((function(){
-return smalltalk.withContext(function($ctx2) {
-_st("#overlay"._asJQuery())._remove();
-return _st(".dialog"._asJQuery())._remove();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._valueWithTimeout_((300));
-return self}, function($ctx1) {$ctx1.fill(self,"remove",{},smalltalk.HLConfirmationWidget)})},
-args: [],
-source: "remove\x0a\x09'.dialog' asJQuery removeClass: 'active'.\x0a\x09[ \x0a\x09\x09'#overlay' asJQuery remove.\x0a\x09\x09'.dialog' asJQuery remove\x0a\x09] valueWithTimeout: 300",
-messageSends: ["removeClass:", "asJQuery", "valueWithTimeout:", "remove"],
-referencedClasses: []
-}),
-smalltalk.HLConfirmationWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderButtonsOn:",
-category: 'rendering',
-fn: function (html){
-var self=this;
-var confirmButton;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$5,$6,$2;
-$1=_st(html)._div();
-_st($1)._class_("buttons");
-$2=_st($1)._with_((function(){
-return smalltalk.withContext(function($ctx2) {
-$3=_st(html)._button();
-_st($3)._class_("button");
-_st($3)._with_("Cancel");
-$4=_st($3)._onClick_((function(){
-return smalltalk.withContext(function($ctx3) {
-return self._cancel();
-}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)})}));
-$4;
-$5=_st(html)._button();
-_st($5)._class_("button default");
-_st($5)._with_("Confirm");
-$6=_st($5)._onClick_((function(){
-return smalltalk.withContext(function($ctx3) {
-return self._confirm();
-}, function($ctx3) {$ctx3.fillBlock({},$ctx2,3)})}));
-confirmButton=$6;
-return confirmButton;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
-_st(_st(confirmButton)._asJQuery())._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html,confirmButton:confirmButton},smalltalk.HLConfirmationWidget)})},
-args: ["html"],
-source: "renderButtonsOn: html\x0a\x09| confirmButton |\x0a\x09\x0a\x09html div \x0a\x09\x09class: 'buttons';\x0a\x09\x09with: [\x0a\x09\x09\x09html button\x0a\x09\x09\x09\x09class: 'button';\x0a\x09\x09\x09\x09with: 'Cancel';\x0a\x09\x09\x09\x09onClick: [ self cancel ].\x0a\x09\x09\x09confirmButton := html button\x0a\x09\x09\x09\x09class: 'button default';\x0a\x09\x09\x09\x09with: 'Confirm';\x0a\x09\x09\x09\x09onClick: [ self confirm ] ].\x0a\x0a\x09confirmButton asJQuery focus",
-messageSends: ["class:", "div", "with:", "button", "onClick:", "cancel", "confirm", "focus", "asJQuery"],
-referencedClasses: []
-}),
-smalltalk.HLConfirmationWidget);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderMainOn:",
@@ -4192,12 +4275,12 @@ category: 'actions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLRequestWidget.superclass.fn.prototype._confirm.apply(_st(self), []);
 _st(self._actionBlock())._value_(_st(_st(self["@input"])._asJQuery())._val());
-self._remove();
 return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLRequestWidget)})},
 args: [],
-source: "confirm\x0a\x09self actionBlock value: input asJQuery val.\x0a\x09self remove",
-messageSends: ["value:", "actionBlock", "val", "asJQuery", "remove"],
+source: "confirm\x0a\x09super confirm.\x0a\x09self actionBlock value: input asJQuery val",
+messageSends: ["confirm", "value:", "actionBlock", "val", "asJQuery"],
 referencedClasses: []
 }),
 smalltalk.HLRequestWidget);
@@ -4343,6 +4426,22 @@ referencedClasses: []
 }),
 smalltalk.HLProgressWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "hasButtons",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return false;
+}, function($ctx1) {$ctx1.fill(self,"hasButtons",{},smalltalk.HLProgressWidget)})},
+args: [],
+source: "hasButtons\x0a\x09^ false",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLProgressWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "isVisible",
@@ -4436,21 +4535,6 @@ referencedClasses: []
 }),
 smalltalk.HLProgressWidget);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderButtonsOn:",
-category: 'rendering',
-fn: function (html){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLProgressWidget)})},
-args: ["html"],
-source: "renderButtonsOn: html",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLProgressWidget);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderMainOn:",
@@ -4482,12 +4566,12 @@ $1=self._isVisible();
 if(! smalltalk.assert($1)){
 self["@visible"]=true;
 self["@visible"];
-self._appendToJQuery_("body"._asJQuery());
+smalltalk.HLProgressWidget.superclass.fn.prototype._show.apply(_st(self), []);
 };
 return self}, function($ctx1) {$ctx1.fill(self,"show",{},smalltalk.HLProgressWidget)})},
 args: [],
-source: "show\x0a\x09self isVisible ifFalse: [\x0a\x09\x09visible := true.\x0a\x09\x09self appendToJQuery: 'body' asJQuery ]",
-messageSends: ["ifFalse:", "isVisible", "appendToJQuery:", "asJQuery"],
+source: "show\x0a\x09self isVisible ifFalse: [\x0a\x09\x09visible := true.\x0a\x09\x09super show ]",
+messageSends: ["ifFalse:", "isVisible", "show"],
 referencedClasses: []
 }),
 smalltalk.HLProgressWidget);
@@ -4519,6 +4603,405 @@ referencedClasses: []
 smalltalk.HLProgressWidget.klass);
 
 
+smalltalk.addClass('HLTabSelectionWidget', smalltalk.HLModalWidget, ['tabs', 'tabList', 'selectedTab', 'selectCallback', 'cancelCallback', 'confirmCallback'], 'Helios-Core');
+smalltalk.HLTabSelectionWidget.comment="I am a modal window used to select or create tabs.";
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cancel",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._cancel.apply(_st(self), []);
+_st(self._cancelCallback())._value();
+return self}, function($ctx1) {$ctx1.fill(self,"cancel",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "cancel\x0a\x09super cancel.\x0a\x09self cancelCallback value",
+messageSends: ["cancel", "value", "cancelCallback"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cancelCallback",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@cancelCallback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"cancelCallback",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "cancelCallback\x0a\x09^ cancelCallback ifNil: [ [] ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cancelCallback:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@cancelCallback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"cancelCallback:",{aBlock:aBlock},smalltalk.HLTabSelectionWidget)})},
+args: ["aBlock"],
+source: "cancelCallback: aBlock\x0a\x09cancelCallback := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirm",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._confirm.apply(_st(self), []);
+_st(self._confirmCallback())._value_(self._selectedTab());
+return self}, function($ctx1) {$ctx1.fill(self,"confirm",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "confirm\x0a\x09super confirm.\x0a\x09self confirmCallback value: self selectedTab",
+messageSends: ["confirm", "value:", "confirmCallback", "selectedTab"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirmCallback",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@confirmCallback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"confirmCallback",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "confirmCallback\x0a\x09^ confirmCallback ifNil: [ [] ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirmCallback:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@confirmCallback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"confirmCallback:",{aBlock:aBlock},smalltalk.HLTabSelectionWidget)})},
+args: ["aBlock"],
+source: "confirmCallback: aBlock\x0a\x09confirmCallback := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderContentOn:",
+category: 'rendering',
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._renderContentOn_.apply(_st(self), [html]);
+_st(self._tabList())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLTabSelectionWidget)})},
+args: ["html"],
+source: "renderContentOn: html\x0a\x09super renderContentOn: html.\x0a\x09self tabList focus",
+messageSends: ["renderContentOn:", "focus", "tabList"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderMainOn:",
+category: 'rendering',
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(html)._div();
+_st($1)._class_("title");
+$2=_st($1)._with_("Tab selection");
+_st(html)._with_(self._tabList());
+return self}, function($ctx1) {$ctx1.fill(self,"renderMainOn:",{html:html},smalltalk.HLTabSelectionWidget)})},
+args: ["html"],
+source: "renderMainOn: html\x0a\x09html div \x0a\x09\x09class: 'title'; \x0a\x09\x09with: 'Tab selection'.\x0a\x09\x0a\x09html with: self tabList",
+messageSends: ["class:", "div", "with:", "tabList"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderTab:on:",
+category: 'rendering',
+fn: function (aTab,html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(html)._span();
+_st($1)._class_(_st(aTab)._cssClass());
+$2=_st($1)._with_(_st(aTab)._label());
+return self}, function($ctx1) {$ctx1.fill(self,"renderTab:on:",{aTab:aTab,html:html},smalltalk.HLTabSelectionWidget)})},
+args: ["aTab", "html"],
+source: "renderTab: aTab on: html\x0a\x09html \x0a\x09\x09span \x0a\x09\x09\x09class: aTab cssClass;\x0a\x09\x09\x09with: aTab label",
+messageSends: ["class:", "span", "cssClass", "with:", "label"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderTabsOn:",
+category: 'rendering',
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self._tabs())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(html)._li())._with_((function(){
+return smalltalk.withContext(function($ctx3) {
+$1=_st(html)._a();
+_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx4) {
+return self._renderTab_on_(each,html);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx3,3)})}));
+$2=_st($1)._onClick_((function(){
+return smalltalk.withContext(function($ctx4) {
+return self._selectTab_(each);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx3,4)})}));
+return $2;
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"renderTabsOn:",{html:html},smalltalk.HLTabSelectionWidget)})},
+args: ["html"],
+source: "renderTabsOn: html\x0a\x09self tabs do: [ :each |\x0a\x09\x09html li with: [ \x0a\x09\x09\x09html a \x0a\x09\x09\x09\x09with: [ \x0a\x09\x09\x09\x09\x09self renderTab: each on: html ];\x0a\x09\x09\x09\x09onClick: [ self selectTab: each ] ] ]",
+messageSends: ["do:", "tabs", "with:", "li", "a", "renderTab:on:", "onClick:", "selectTab:"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectCallback",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@selectCallback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=(function(){
+return smalltalk.withContext(function($ctx2) {
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})});
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectCallback",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "selectCallback\x0a\x09^ selectCallback ifNil: [ [] ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectCallback:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@selectCallback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"selectCallback:",{aBlock:aBlock},smalltalk.HLTabSelectionWidget)})},
+args: ["aBlock"],
+source: "selectCallback: aBlock\x0a\x09selectCallback := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectTab:",
+category: 'actions',
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._selectedTab_(aTab);
+_st(self._selectCallback())._value_(aTab);
+return self}, function($ctx1) {$ctx1.fill(self,"selectTab:",{aTab:aTab},smalltalk.HLTabSelectionWidget)})},
+args: ["aTab"],
+source: "selectTab: aTab\x0a\x09self selectedTab: aTab.\x0a\x09self selectCallback value: aTab",
+messageSends: ["selectedTab:", "value:", "selectCallback"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectedTab",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@selectedTab"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"selectedTab",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "selectedTab\x0a\x09^ selectedTab",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectedTab:",
+category: 'accessing',
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@selectedTab"]=aTab;
+return self}, function($ctx1) {$ctx1.fill(self,"selectedTab:",{aTab:aTab},smalltalk.HLTabSelectionWidget)})},
+args: ["aTab"],
+source: "selectedTab: aTab\x0a\x09selectedTab := aTab",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "setupKeyBindings",
+category: 'actions',
+fn: function (){
+var self=this;
+function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+smalltalk.HLTabSelectionWidget.superclass.fn.prototype._setupKeyBindings.apply(_st(self), []);
+_st(".dialog"._asJQuery())._keyup_((function(e){
+return smalltalk.withContext(function($ctx2) {
+$1=_st(_st(e)._keyCode()).__eq(_st(_st($String())._cr())._asciiValue());
+if(smalltalk.assert($1)){
+return self._confirm();
+};
+}, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1,1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "setupKeyBindings\x0a\x09super setupKeyBindings.\x0a\x09'.dialog' asJQuery keyup: [ :e |\x0a\x09\x09e keyCode = String cr asciiValue ifTrue: [ self confirm ] ]",
+messageSends: ["setupKeyBindings", "keyup:", "asJQuery", "ifTrue:", "=", "keyCode", "asciiValue", "cr", "confirm"],
+referencedClasses: ["String"]
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabList",
+category: 'rendering',
+fn: function (){
+var self=this;
+function $HLTabListWidget(){return smalltalk.HLTabListWidget||(typeof HLTabListWidget=="undefined"?nil:HLTabListWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3,$4;
+$1=self["@tabList"];
+if(($receiver = $1) == nil || $receiver == undefined){
+self["@tabList"]=_st($HLTabListWidget())._new();
+self["@tabList"];
+$2=self["@tabList"];
+_st($2)._callback_((function(tab){
+return smalltalk.withContext(function($ctx2) {
+self._selectTab_(tab);
+return _st(self["@tabList"])._focus();
+}, function($ctx2) {$ctx2.fillBlock({tab:tab},$ctx1,2)})}));
+_st($2)._selectedItem_(self._selectedTab());
+$3=_st($2)._items_(self._tabs());
+$3;
+} else {
+$1;
+};
+$4=self["@tabList"];
+return $4;
+}, function($ctx1) {$ctx1.fill(self,"tabList",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "tabList\x0a\x09tabList ifNil: [ \x0a\x09\x09tabList := HLTabListWidget new.\x0a\x09\x09tabList\x0a\x09\x09\x09callback: [ :tab | self selectTab: tab. tabList focus ];\x0a\x09\x09\x09selectedItem: self selectedTab;\x0a\x09\x09\x09items: self tabs ].\x0a\x09\x0a\x09^ tabList",
+messageSends: ["ifNil:", "new", "callback:", "selectTab:", "focus", "selectedItem:", "selectedTab", "items:", "tabs"],
+referencedClasses: ["HLTabListWidget"]
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabs",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@tabs"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=[];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"tabs",{},smalltalk.HLTabSelectionWidget)})},
+args: [],
+source: "tabs\x0a\x09^ tabs ifNil: [ #() ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabs:",
+category: 'accessing',
+fn: function (aCollection){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@tabs"]=aCollection;
+return self}, function($ctx1) {$ctx1.fill(self,"tabs:",{aCollection:aCollection},smalltalk.HLTabSelectionWidget)})},
+args: ["aCollection"],
+source: "tabs: aCollection\x0a\x09tabs := aCollection",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLTabSelectionWidget);
+
+
+
 smalltalk.addClass('HLProgressBarWidget', smalltalk.HLWidget, ['label', 'parent', 'workBlock', 'collection', 'bar'], 'Helios-Core');
 smalltalk.HLProgressBarWidget.comment="I am a widget used to display a progress bar while iterating over a collection.";
 smalltalk.addMethod(

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 322 - 321
js/Helios-KeyBindings.deploy.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 254 - 300
js/Helios-KeyBindings.js


+ 1 - 1
js/Helios-Workspace-Tests.js

@@ -15,7 +15,7 @@ self._assert_(_st(_st($HLCodeWidget())._pcKeyMap())._isKindOf_($HashedCollection
 self._assert_(_st(_st($HLCodeWidget())._macKeyMap())._isKindOf_($HashedCollection()));
 return self}, function($ctx1) {$ctx1.fill(self,"testKeyMap",{},smalltalk.HLCodeWidgetTest)})},
 args: [],
-source: "testKeyMap\x0a\x22Key maps are a collection of associations.\x22\x0aself assert: ( HLCodeWidget pcKeyMap isKindOf: HashedCollection ).\x0aself assert: ( HLCodeWidget macKeyMap isKindOf: HashedCollection ).",
+source: "testKeyMap\x0a\x09\x22Key maps are a collection of associations.\x22\x0a\x09self assert: (HLCodeWidget pcKeyMap isKindOf: HashedCollection).\x0a\x09self assert: (HLCodeWidget macKeyMap isKindOf: HashedCollection)",
 messageSends: ["assert:", "isKindOf:", "pcKeyMap", "macKeyMap"],
 referencedClasses: ["HLCodeWidget", "HashedCollection"]
 }),

+ 73 - 73
js/Importer-Exporter.deploy.js

@@ -35,7 +35,7 @@ $1=_st(aClass)._name();
 };
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass},smalltalk.AbstractExporter)})},
-messageSends: ["ifTrue:ifFalse:", ",", "name", "instanceClass", "isNil", "isMetaclass"]}),
+messageSends: ["ifTrue:ifFalse:", "isMetaclass", ",", "name", "instanceClass", "isNil"]}),
 smalltalk.AbstractExporter);
 
 smalltalk.addMethod(
@@ -117,10 +117,10 @@ $2=_st($1)._nextPutAll_("instanceVariableNames: '");
 _st(_st(aClass)._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(each);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(" ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $3=aStream;
 _st($3)._nextPutAll_("'");
 _st($3)._lf();
@@ -138,7 +138,7 @@ $7;
 };
 _st(aStream)._lf();
 return self}, function($ctx1) {$ctx1.fill(self,"exportDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.ChunkExporter)})},
-messageSends: ["nextPutAll:", "classNameFor:", "superclass", ",", "lf", "tab", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "chunkEscape:", "comment", "notEmpty"]}),
+messageSends: ["nextPutAll:", "classNameFor:", "superclass", ",", "lf", "tab", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "notEmpty", "comment", "chunkEscape:"]}),
 smalltalk.ChunkExporter);
 
 smalltalk.addMethod(
@@ -157,10 +157,10 @@ $3;
 _st(_st(_st(aClass)._class())._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(each);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(" ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}));
 $4=aStream;
 _st($4)._nextPutAll_("'!");
 _st($4)._lf();
@@ -168,7 +168,7 @@ $5=_st($4)._lf();
 $5;
 };
 return self}, function($ctx1) {$ctx1.fill(self,"exportMetaDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.ChunkExporter)})},
-messageSends: ["ifFalse:", "nextPutAll:", "classNameFor:", "class", "do:separatedBy:", "instanceVariableNames", "lf", "isEmpty"]}),
+messageSends: ["ifFalse:", "isEmpty", "instanceVariableNames", "class", "nextPutAll:", "classNameFor:", "do:separatedBy:", "lf"]}),
 smalltalk.ChunkExporter);
 
 smalltalk.addMethod(
@@ -209,10 +209,10 @@ fn: function (aPackage){
 var self=this;
 var name,map,result;
 function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
+function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
 function $MethodCategory(){return smalltalk.MethodCategory||(typeof MethodCategory=="undefined"?nil:MethodCategory)}
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
-function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
 name=_st(aPackage)._name();
@@ -229,20 +229,20 @@ $1=_st(category).__eq("*".__comma(name));
 if(smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx3)})}));
+}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx3,3)})}));
 return _st(result)._addAll_(_st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
 return _st(a).__lt_eq(b);
-}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3)})})))._collect_((function(category){
+}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3,5)})})))._collect_((function(category){
 return smalltalk.withContext(function($ctx4) {
 return _st($MethodCategory())._name_theClass_methods_(category,aClass,_st(map)._at_(category));
-}, function($ctx4) {$ctx4.fillBlock({category:category},$ctx3)})})));
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2)})}));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx4) {$ctx4.fillBlock({category:category},$ctx3,6)})})));
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $2=result;
 return $2;
 }, function($ctx1) {$ctx1.fill(self,"extensionCategoriesOfPackage:",{aPackage:aPackage,name:name,map:map,result:result},smalltalk.ChunkExporter)})},
-messageSends: ["name", "new", "do:", "protocolsDo:", "ifTrue:", "at:put:", "=", ",", "addAll:", "collect:", "name:theClass:methods:", "at:", "sorted:", "<=", "keys", "class", "sortedClasses:", "classes", "current"]}),
+messageSends: ["name", "new", "do:", "sortedClasses:", "classes", "current", "class", "protocolsDo:", "ifTrue:", "=", ",", "at:put:", "addAll:", "collect:", "sorted:", "keys", "<=", "name:theClass:methods:", "at:"]}),
 smalltalk.ChunkExporter);
 
 smalltalk.addMethod(
@@ -255,10 +255,10 @@ var $1;
 $1=_st(_st(aCategory)._methods())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"methodsOfCategory:",{aCategory:aCategory},smalltalk.ChunkExporter)})},
-messageSends: ["sorted:", "<=", "selector", "methods"]}),
+messageSends: ["sorted:", "methods", "<=", "selector"]}),
 smalltalk.ChunkExporter);
 
 smalltalk.addMethod(
@@ -278,17 +278,17 @@ $1=_st(category)._match_("^\x5c*");
 if(! smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1,1)})}));
 $2=_st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
 return _st(a).__lt_eq(b);
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._collect_((function(category){
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,3)})})))._collect_((function(category){
 return smalltalk.withContext(function($ctx2) {
 return _st($MethodCategory())._name_theClass_methods_(category,aClass,_st(map)._at_(category));
-}, function($ctx2) {$ctx2.fillBlock({category:category},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({category:category},$ctx1,4)})}));
 return $2;
 }, function($ctx1) {$ctx1.fill(self,"ownCategoriesOfClass:",{aClass:aClass,map:map},smalltalk.ChunkExporter)})},
-messageSends: ["new", "protocolsDo:", "ifFalse:", "at:put:", "match:", "collect:", "name:theClass:methods:", "at:", "sorted:", "<=", "keys"]}),
+messageSends: ["new", "protocolsDo:", "ifFalse:", "match:", "at:put:", "collect:", "sorted:", "keys", "<=", "name:theClass:methods:", "at:"]}),
 smalltalk.ChunkExporter);
 
 smalltalk.addMethod(
@@ -343,7 +343,7 @@ $1=_st(aClass)._name();
 };
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass},smalltalk.Exporter)})},
-messageSends: ["ifTrue:ifFalse:", ",", "name", "instanceClass", "isNil", "isMetaclass"]}),
+messageSends: ["ifTrue:ifFalse:", "isMetaclass", ",", "name", "instanceClass", "isNil"]}),
 smalltalk.Exporter);
 
 smalltalk.addMethod(
@@ -362,10 +362,10 @@ $2=_st($1)._nextPutAll_(", [");
 _st(_st(aClass)._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(_st("'".__comma(each)).__comma("'"));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(", ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $3=aStream;
 _st($3)._nextPutAll_("], '");
 _st($3)._nextPutAll_(_st(_st(aClass)._category()).__comma("'"));
@@ -383,7 +383,7 @@ $7;
 };
 _st(aStream)._lf();
 return self}, function($ctx1) {$ctx1.fill(self,"exportDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.Exporter)})},
-messageSends: ["lf", "nextPutAll:", ",", "classNameFor:", "superclass", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "asJavascript", "comment", "notEmpty"]}),
+messageSends: ["lf", "nextPutAll:", ",", "classNameFor:", "superclass", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "notEmpty", "comment", "asJavascript"]}),
 smalltalk.Exporter);
 
 smalltalk.addMethod(
@@ -404,14 +404,14 @@ $3;
 _st(_st(_st(aClass)._class())._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(_st("'".__comma(each)).__comma("'"));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(",");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}));
 _st(aStream)._nextPutAll_("];".__comma(_st($String())._lf()));
 };
 return self}, function($ctx1) {$ctx1.fill(self,"exportMetaDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.Exporter)})},
-messageSends: ["lf", "ifFalse:", "nextPutAll:", ",", "classNameFor:", "class", "do:separatedBy:", "instanceVariableNames", "isEmpty"]}),
+messageSends: ["lf", "ifFalse:", "isEmpty", "instanceVariableNames", "class", "nextPutAll:", ",", "classNameFor:", "do:separatedBy:"]}),
 smalltalk.Exporter);
 
 smalltalk.addMethod(
@@ -501,8 +501,8 @@ fn: function (aPackage){
 var self=this;
 var name,result;
 function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
 name=_st(aPackage)._name();
@@ -514,16 +514,16 @@ return smalltalk.withContext(function($ctx3) {
 return _st(result)._addAll_(_st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
 return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3)})})))._select_((function(method){
+}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3,3)})})))._select_((function(method){
 return smalltalk.withContext(function($ctx4) {
 return _st(_st(method)._category()).__eq("*".__comma(name));
-}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx3)})})));
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2)})}));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx3,4)})})));
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $1=result;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"extensionMethodsOfPackage:",{aPackage:aPackage,name:name,result:result},smalltalk.Exporter)})},
-messageSends: ["name", "new", "do:", "addAll:", "select:", "=", ",", "category", "sorted:", "<=", "selector", "values", "methodDictionary", "class", "sortedClasses:", "classes", "current"]}),
+messageSends: ["name", "new", "do:", "sortedClasses:", "classes", "current", "class", "addAll:", "select:", "sorted:", "values", "methodDictionary", "<=", "selector", "=", "category", ","]}),
 smalltalk.Exporter);
 
 smalltalk.addMethod(
@@ -536,13 +536,13 @@ var $1;
 $1=_st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._reject_((function(each){
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,1)})})))._reject_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(each)._category())._match_("^\x5c*");
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"ownMethodsOfClass:",{aClass:aClass},smalltalk.Exporter)})},
-messageSends: ["reject:", "match:", "category", "sorted:", "<=", "selector", "values", "methodDictionary"]}),
+messageSends: ["reject:", "sorted:", "values", "methodDictionary", "<=", "selector", "match:", "category"]}),
 smalltalk.Exporter);
 
 smalltalk.addMethod(
@@ -591,10 +591,10 @@ $2=_st($1)._nextPutAll_(", [");
 _st(_st(aClass)._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(_st("'".__comma(each)).__comma("'"));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(", ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $3=aStream;
 _st($3)._nextPutAll_("], '");
 _st($3)._nextPutAll_(_st(_st(aClass)._category()).__comma("'"));
@@ -650,7 +650,7 @@ return smalltalk.withContext(function($ctx2) {
 char=_st(self["@stream"])._next();
 char;
 return _st(char)._notNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._whileTrue_((function(){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(char).__eq("!");
 if(smalltalk.assert($1)){
@@ -663,12 +663,12 @@ throw $early=[$3];
 };
 };
 return _st(result)._nextPut_(char);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return nil;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
 }, function($ctx1) {$ctx1.fill(self,"nextChunk",{char:char,result:result,chunk:chunk},smalltalk.ChunkParser)})},
-messageSends: ["writeStream", "whileTrue:", "ifTrue:", "ifTrue:ifFalse:", "next", "trimBoth", "contents", "=", "peek", "nextPut:", "notNil"]}),
+messageSends: ["writeStream", "whileTrue:", "next", "notNil", "ifTrue:", "=", "ifTrue:ifFalse:", "peek", "trimBoth", "contents", "nextPut:"]}),
 smalltalk.ChunkParser);
 
 smalltalk.addMethod(
@@ -709,12 +709,12 @@ recipeStream=_st(aRecipe)._readStream();
 _st((function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(recipeStream)._atEnd();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._whileFalse_((function(){
 return smalltalk.withContext(function($ctx2) {
 return self._interpretStep_for_on_(_st(recipeStream)._next(),anObject,aStream);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"interpret:for:on:",{aRecipe:aRecipe,anObject:anObject,aStream:aStream,recipeStream:recipeStream},smalltalk.ExportRecipeInterpreter)})},
-messageSends: ["readStream", "whileFalse:", "interpretStep:for:on:", "next", "atEnd"]}),
+messageSends: ["readStream", "whileFalse:", "atEnd", "interpretStep:for:on:", "next"]}),
 smalltalk.ExportRecipeInterpreter);
 
 smalltalk.addMethod(
@@ -731,7 +731,7 @@ return $2;
 };
 _st(_st(aRecipeStep)._key())._perform_withArguments_(_st(aRecipeStep)._value(),[anObject,aStream]);
 return self}, function($ctx1) {$ctx1.fill(self,"interpretStep:for:on:",{aRecipeStep:aRecipeStep,anObject:anObject,aStream:aStream},smalltalk.ExportRecipeInterpreter)})},
-messageSends: ["ifTrue:", "interpretSubRecipe:for:on:", "==", "value", "perform:withArguments:", "key"]}),
+messageSends: ["ifTrue:", "==", "value", "interpretSubRecipe:for:on:", "perform:withArguments:", "key"]}),
 smalltalk.ExportRecipeInterpreter);
 
 smalltalk.addMethod(
@@ -745,9 +745,9 @@ selection=_st(_st(_st(aRecipe)._first())._key())._perform_withArguments_(_st(_st
 _st(selection)._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return self._interpret_for_on_(_st(aRecipe)._allButFirst(),each,aStream);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"interpretSubRecipe:for:on:",{aRecipe:aRecipe,anObject:anObject,aStream:aStream,selection:selection},smalltalk.ExportRecipeInterpreter)})},
-messageSends: ["perform:withArguments:", "value", "first", "key", "do:", "interpret:for:on:", "allButFirst"]}),
+messageSends: ["perform:withArguments:", "key", "first", "value", "do:", "interpret:for:on:", "allButFirst"]}),
 smalltalk.ExportRecipeInterpreter);
 
 
@@ -770,7 +770,7 @@ return smalltalk.withContext(function($ctx2) {
 chunk=_st(parser)._nextChunk();
 chunk;
 return _st(chunk)._isNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._whileFalse_((function(){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(chunk)._isEmpty();
 if(smalltalk.assert($1)){
@@ -786,9 +786,9 @@ lastEmpty;
 return _st(result)._scanFrom_(parser);
 };
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"import:",{aStream:aStream,chunk:chunk,result:result,parser:parser,lastEmpty:lastEmpty},smalltalk.Importer)})},
-messageSends: ["on:", "whileFalse:", "ifTrue:ifFalse:", "evaluateExpression:", "new", "ifTrue:", "scanFrom:", "isEmpty", "nextChunk", "isNil"]}),
+messageSends: ["on:", "whileFalse:", "nextChunk", "isNil", "ifTrue:ifFalse:", "isEmpty", "evaluateExpression:", "new", "ifTrue:", "scanFrom:"]}),
 smalltalk.Importer);
 
 
@@ -896,7 +896,7 @@ return smalltalk.withContext(function($ctx1) {
 self._ajax_(smalltalk.HashedCollection._from_(["url".__minus_gt(aURL),"type".__minus_gt("PUT"),"data".__minus_gt(aString),"contentType".__minus_gt("text/plain;charset=UTF-8"),"error".__minus_gt((function(xhr){
 return smalltalk.withContext(function($ctx2) {
 return self._error_(_st(_st(_st("Commiting ".__comma(aURL)).__comma(" failed with reason: \x22")).__comma(_st(xhr)._responseText())).__comma("\x22"));
-}, function($ctx2) {$ctx2.fillBlock({xhr:xhr},$ctx1)})}))]));
+}, function($ctx2) {$ctx2.fillBlock({xhr:xhr},$ctx1,1)})}))]));
 return self}, function($ctx1) {$ctx1.fill(self,"ajaxPutAt:data:",{aURL:aURL,aString:aString},smalltalk.PackageHandler)})},
 messageSends: ["ajax:", "->", "error:", ",", "responseText"]}),
 smalltalk.PackageHandler);
@@ -906,8 +906,8 @@ smalltalk.method({
 selector: "commit:",
 fn: function (aPackage){
 var self=this;
-function $PluggableExporter(){return smalltalk.PluggableExporter||(typeof PluggableExporter=="undefined"?nil:PluggableExporter)}
 function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
+function $PluggableExporter(){return smalltalk.PluggableExporter||(typeof PluggableExporter=="undefined"?nil:PluggableExporter)}
 return smalltalk.withContext(function($ctx1) { 
 _st(self._commitChannels())._do_displayingProgress_((function(commitStrategyFactory){
 var fileContents,commitStrategy;
@@ -917,12 +917,12 @@ commitStrategy;
 fileContents=_st($String())._streamContents_((function(stream){
 return smalltalk.withContext(function($ctx3) {
 return _st(_st($PluggableExporter())._forRecipe_(_st(commitStrategy)._key()))._exportPackage_on_(aPackage,stream);
-}, function($ctx3) {$ctx3.fillBlock({stream:stream},$ctx2)})}));
+}, function($ctx3) {$ctx3.fillBlock({stream:stream},$ctx2,2)})}));
 fileContents;
 return self._ajaxPutAt_data_(_st(commitStrategy)._value(),fileContents);
-}, function($ctx2) {$ctx2.fillBlock({commitStrategyFactory:commitStrategyFactory,fileContents:fileContents,commitStrategy:commitStrategy},$ctx1)})}),"Committing package ".__comma(_st(aPackage)._name()));
+}, function($ctx2) {$ctx2.fillBlock({commitStrategyFactory:commitStrategyFactory,fileContents:fileContents,commitStrategy:commitStrategy},$ctx1,1)})}),"Committing package ".__comma(_st(aPackage)._name()));
 return self}, function($ctx1) {$ctx1.fill(self,"commit:",{aPackage:aPackage},smalltalk.PackageHandler)})},
-messageSends: ["do:displayingProgress:", "value:", "streamContents:", "exportPackage:on:", "forRecipe:", "key", "ajaxPutAt:data:", "value", ",", "name", "commitChannels"]}),
+messageSends: ["do:displayingProgress:", "commitChannels", "value:", "streamContents:", "exportPackage:on:", "forRecipe:", "key", "ajaxPutAt:data:", "value", ",", "name"]}),
 smalltalk.PackageHandler);
 
 smalltalk.addMethod(
@@ -1014,16 +1014,16 @@ var $1;
 $1=[(function(pkg){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($Exporter())._default())._recipe()).__minus_gt(_st(_st(_st(_st(pkg)._commitPathJs()).__comma("/")).__comma(_st(pkg)._name())).__comma(".js"));
-}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1)})}),(function(pkg){
+}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1,1)})}),(function(pkg){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($StrippedExporter())._default())._recipe()).__minus_gt(_st(_st(_st(_st(pkg)._commitPathJs()).__comma("/")).__comma(_st(pkg)._name())).__comma(".deploy.js"));
-}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1)})}),(function(pkg){
+}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1,2)})}),(function(pkg){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($ChunkExporter())._default())._recipe()).__minus_gt(_st(_st(_st(_st(pkg)._commitPathSt()).__comma("/")).__comma(_st(pkg)._name())).__comma(".st"));
-}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1)})})];
+}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1,3)})})];
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"commitChannels",{},smalltalk.LegacyPackageHandler)})},
-messageSends: ["->", ",", "name", "commitPathJs", "recipe", "default", "commitPathSt"]}),
+messageSends: ["->", "recipe", "default", ",", "commitPathJs", "name", "commitPathSt"]}),
 smalltalk.LegacyPackageHandler);
 
 smalltalk.addMethod(
@@ -1067,12 +1067,12 @@ $1=_st(_st(jqXHR)._readyState()).__eq((4));
 if(smalltalk.assert($1)){
 return self._setupPackageNamed_prefix_(packageName,aString);
 };
-}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1)})})),"error".__minus_gt((function(){
+}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1,1)})})),"error".__minus_gt((function(){
 return smalltalk.withContext(function($ctx2) {
 return self._alert_("Could not load package at: ".__comma(url));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))]));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}))]));
 return self}, function($ctx1) {$ctx1.fill(self,"loadPackage:prefix:",{packageName:packageName,aString:aString,url:url},smalltalk.LegacyPackageHandler)})},
-messageSends: [",", "ajax:", "->", "ifTrue:", "setupPackageNamed:prefix:", "=", "readyState", "alert:"]}),
+messageSends: [",", "ajax:", "->", "ifTrue:", "=", "readyState", "setupPackageNamed:prefix:", "alert:"]}),
 smalltalk.LegacyPackageHandler);
 
 smalltalk.addMethod(
@@ -1084,7 +1084,7 @@ return smalltalk.withContext(function($ctx1) {
 _st(aCollection)._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return self._loadPackage_prefix_(each,aString);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"loadPackages:prefix:",{aCollection:aCollection,aString:aString},smalltalk.LegacyPackageHandler)})},
 messageSends: ["do:", "loadPackage:prefix:"]}),
 smalltalk.LegacyPackageHandler);
@@ -1228,8 +1228,8 @@ smalltalk.method({
 selector: "exportAllPackages",
 fn: function (){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
 $1=_st($String())._streamContents_((function(stream){
@@ -1237,11 +1237,11 @@ return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($Smalltalk())._current())._packages())._do_((function(pkg){
 return smalltalk.withContext(function($ctx3) {
 return self._exportPackage_on_(pkg,stream);
-}, function($ctx3) {$ctx3.fillBlock({pkg:pkg},$ctx2)})}));
-}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1)})}));
+}, function($ctx3) {$ctx3.fillBlock({pkg:pkg},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1,1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"exportAllPackages",{},smalltalk.PluggableExporter)})},
-messageSends: ["streamContents:", "do:", "exportPackage:on:", "packages", "current"]}),
+messageSends: ["streamContents:", "do:", "packages", "current", "exportPackage:on:"]}),
 smalltalk.PluggableExporter);
 
 smalltalk.addMethod(
@@ -1252,7 +1252,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
 _st(self._interpreter())._interpret_for_on_(self._recipe(),aPackage,aStream);
 return self}, function($ctx1) {$ctx1.fill(self,"exportPackage:on:",{aPackage:aPackage,aStream:aStream},smalltalk.PluggableExporter)})},
-messageSends: ["interpret:for:on:", "recipe", "interpreter"]}),
+messageSends: ["interpret:for:on:", "interpreter", "recipe"]}),
 smalltalk.PluggableExporter);
 
 smalltalk.addMethod(
@@ -1353,10 +1353,10 @@ $2=$3;
 $1=_st($2)._at_ifAbsentPut_("commitPathJs",(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(self._transport())._commitPathJsFor_(self);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"commitPathJs",{},smalltalk.Package)})},
-messageSends: ["at:ifAbsentPut:", "commitPathJsFor:", "transport", "ifNil:"]}),
+messageSends: ["at:ifAbsentPut:", "ifNil:", "commitPathJsFor:", "transport"]}),
 smalltalk.Package);
 
 smalltalk.addMethod(
@@ -1396,10 +1396,10 @@ $2=$3;
 $1=_st($2)._at_ifAbsentPut_("commitPathSt",(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(self._transport())._commitPathStFor_(self);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"commitPathSt",{},smalltalk.Package)})},
-messageSends: ["at:ifAbsentPut:", "commitPathStFor:", "transport", "ifNil:"]}),
+messageSends: ["at:ifAbsentPut:", "ifNil:", "commitPathStFor:", "transport"]}),
 smalltalk.Package);
 
 smalltalk.addMethod(

+ 77 - 77
js/Importer-Exporter.js

@@ -44,7 +44,7 @@ return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass},smalltalk.AbstractExporter)})},
 args: ["aClass"],
 source: "classNameFor: aClass\x0a\x09^aClass isMetaclass\x0a\x09\x09ifTrue: [ aClass instanceClass name, ' class' ]\x0a\x09\x09ifFalse: [\x0a\x09\x09\x09aClass isNil\x0a\x09\x09\x09\x09ifTrue: [ 'nil' ]\x0a\x09\x09\x09\x09ifFalse: [ aClass name ] ]",
-messageSends: ["ifTrue:ifFalse:", ",", "name", "instanceClass", "isNil", "isMetaclass"],
+messageSends: ["ifTrue:ifFalse:", "isMetaclass", ",", "name", "instanceClass", "isNil"],
 referencedClasses: []
 }),
 smalltalk.AbstractExporter);
@@ -150,10 +150,10 @@ $2=_st($1)._nextPutAll_("instanceVariableNames: '");
 _st(_st(aClass)._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(each);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(" ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $3=aStream;
 _st($3)._nextPutAll_("'");
 _st($3)._lf();
@@ -173,7 +173,7 @@ _st(aStream)._lf();
 return self}, function($ctx1) {$ctx1.fill(self,"exportDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.ChunkExporter)})},
 args: ["aClass", "aStream"],
 source: "exportDefinitionOf: aClass on: aStream\x0a\x09\x22Chunk format.\x22\x0a\x0a\x09aStream\x0a\x09\x09nextPutAll: (self classNameFor: aClass superclass);\x0a\x09\x09nextPutAll: ' subclass: #', (self classNameFor: aClass); lf;\x0a\x09\x09tab; nextPutAll: 'instanceVariableNames: '''.\x0a\x09aClass instanceVariableNames\x0a\x09\x09do: [:each | aStream nextPutAll: each]\x0a\x09\x09separatedBy: [aStream nextPutAll: ' '].\x0a\x09aStream\x0a\x09\x09nextPutAll: ''''; lf;\x0a\x09\x09tab; nextPutAll: 'package: ''', aClass category, '''!'; lf.\x0a\x09aClass comment notEmpty ifTrue: [\x0a\x09\x09aStream\x0a\x09\x09nextPutAll: '!', (self classNameFor: aClass), ' commentStamp!';lf;\x0a\x09\x09nextPutAll: (self chunkEscape: aClass comment), '!';lf].\x0a\x09aStream lf",
-messageSends: ["nextPutAll:", "classNameFor:", "superclass", ",", "lf", "tab", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "chunkEscape:", "comment", "notEmpty"],
+messageSends: ["nextPutAll:", "classNameFor:", "superclass", ",", "lf", "tab", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "notEmpty", "comment", "chunkEscape:"],
 referencedClasses: []
 }),
 smalltalk.ChunkExporter);
@@ -195,10 +195,10 @@ $3;
 _st(_st(_st(aClass)._class())._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(each);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(" ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}));
 $4=aStream;
 _st($4)._nextPutAll_("'!");
 _st($4)._lf();
@@ -208,7 +208,7 @@ $5;
 return self}, function($ctx1) {$ctx1.fill(self,"exportMetaDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.ChunkExporter)})},
 args: ["aClass", "aStream"],
 source: "exportMetaDefinitionOf: aClass on: aStream\x0a\x0a\x09aClass class instanceVariableNames isEmpty ifFalse: [\x0a\x09\x09aStream\x0a\x09\x09\x09nextPutAll: (self classNameFor: aClass class);\x0a\x09\x09\x09nextPutAll: ' instanceVariableNames: '''.\x0a\x09\x09aClass class instanceVariableNames\x0a\x09\x09\x09do: [:each | aStream nextPutAll: each]\x0a\x09\x09\x09separatedBy: [aStream nextPutAll: ' '].\x0a\x09\x09aStream\x0a\x09\x09\x09nextPutAll: '''!'; lf; lf]",
-messageSends: ["ifFalse:", "nextPutAll:", "classNameFor:", "class", "do:separatedBy:", "instanceVariableNames", "lf", "isEmpty"],
+messageSends: ["ifFalse:", "isEmpty", "instanceVariableNames", "class", "nextPutAll:", "classNameFor:", "do:separatedBy:", "lf"],
 referencedClasses: []
 }),
 smalltalk.ChunkExporter);
@@ -262,10 +262,10 @@ fn: function (aPackage){
 var self=this;
 var name,map,result;
 function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
+function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
 function $MethodCategory(){return smalltalk.MethodCategory||(typeof MethodCategory=="undefined"?nil:MethodCategory)}
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
-function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
 name=_st(aPackage)._name();
@@ -282,23 +282,23 @@ $1=_st(category).__eq("*".__comma(name));
 if(smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx3)})}));
+}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx3,3)})}));
 return _st(result)._addAll_(_st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
 return _st(a).__lt_eq(b);
-}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3)})})))._collect_((function(category){
+}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3,5)})})))._collect_((function(category){
 return smalltalk.withContext(function($ctx4) {
 return _st($MethodCategory())._name_theClass_methods_(category,aClass,_st(map)._at_(category));
-}, function($ctx4) {$ctx4.fillBlock({category:category},$ctx3)})})));
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2)})}));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx4) {$ctx4.fillBlock({category:category},$ctx3,6)})})));
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $2=result;
 return $2;
 }, function($ctx1) {$ctx1.fill(self,"extensionCategoriesOfPackage:",{aPackage:aPackage,name:name,map:map,result:result},smalltalk.ChunkExporter)})},
 args: ["aPackage"],
 source: "extensionCategoriesOfPackage: aPackage\x0a\x09\x22Issue #143: sort protocol alphabetically\x22\x0a\x0a\x09| name map result |\x0a\x09name := aPackage name.\x0a\x09result := OrderedCollection new.\x0a\x09(Package sortedClasses: Smalltalk current classes) do: [:each |\x0a\x09\x09{each. each class} do: [:aClass |\x0a\x09\x09\x09map := Dictionary new.\x0a\x09\x09\x09aClass protocolsDo: [:category :methods |\x0a\x09\x09\x09\x09category = ('*', name) ifTrue: [ map at: category put: methods ]].\x0a\x09\x09\x09result addAll: ((map keys sorted: [:a :b | a <= b ]) collect: [:category |\x0a\x09\x09\x09\x09MethodCategory name: category theClass: aClass methods: (map at: category)]) ]].\x0a\x09^result",
-messageSends: ["name", "new", "do:", "protocolsDo:", "ifTrue:", "at:put:", "=", ",", "addAll:", "collect:", "name:theClass:methods:", "at:", "sorted:", "<=", "keys", "class", "sortedClasses:", "classes", "current"],
-referencedClasses: ["OrderedCollection", "Dictionary", "MethodCategory", "Smalltalk", "Package"]
+messageSends: ["name", "new", "do:", "sortedClasses:", "classes", "current", "class", "protocolsDo:", "ifTrue:", "=", ",", "at:put:", "addAll:", "collect:", "sorted:", "keys", "<=", "name:theClass:methods:", "at:"],
+referencedClasses: ["OrderedCollection", "Package", "Smalltalk", "Dictionary", "MethodCategory"]
 }),
 smalltalk.ChunkExporter);
 
@@ -313,12 +313,12 @@ var $1;
 $1=_st(_st(aCategory)._methods())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"methodsOfCategory:",{aCategory:aCategory},smalltalk.ChunkExporter)})},
 args: ["aCategory"],
 source: "methodsOfCategory: aCategory\x0a\x09\x22Issue #143: sort methods alphabetically\x22\x0a\x0a\x09^(aCategory methods) sorted: [:a :b | a selector <= b selector]",
-messageSends: ["sorted:", "<=", "selector", "methods"],
+messageSends: ["sorted:", "methods", "<=", "selector"],
 referencedClasses: []
 }),
 smalltalk.ChunkExporter);
@@ -341,19 +341,19 @@ $1=_st(category)._match_("^\x5c*");
 if(! smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1,1)})}));
 $2=_st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
 return _st(a).__lt_eq(b);
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._collect_((function(category){
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,3)})})))._collect_((function(category){
 return smalltalk.withContext(function($ctx2) {
 return _st($MethodCategory())._name_theClass_methods_(category,aClass,_st(map)._at_(category));
-}, function($ctx2) {$ctx2.fillBlock({category:category},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({category:category},$ctx1,4)})}));
 return $2;
 }, function($ctx1) {$ctx1.fill(self,"ownCategoriesOfClass:",{aClass:aClass,map:map},smalltalk.ChunkExporter)})},
 args: ["aClass"],
 source: "ownCategoriesOfClass: aClass\x0a\x09\x22Answer the protocols of aClassthat are not package extensions\x22\x0a\x09\x0a\x09\x22Issue #143: sort protocol alphabetically\x22\x0a\x0a\x09| map |\x0a\x09map := Dictionary new.\x0a\x09aClass protocolsDo: [:category :methods |\x0a\x09\x09(category match: '^\x5c*') ifFalse: [ map at: category put: methods ]].\x0a\x09^(map keys sorted: [:a :b | a <= b ]) collect: [:category |\x0a\x09\x09MethodCategory name: category theClass: aClass methods: (map at: category) ]",
-messageSends: ["new", "protocolsDo:", "ifFalse:", "at:put:", "match:", "collect:", "name:theClass:methods:", "at:", "sorted:", "<=", "keys"],
+messageSends: ["new", "protocolsDo:", "ifFalse:", "match:", "at:put:", "collect:", "sorted:", "keys", "<=", "name:theClass:methods:", "at:"],
 referencedClasses: ["Dictionary", "MethodCategory"]
 }),
 smalltalk.ChunkExporter);
@@ -424,7 +424,7 @@ return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass},smalltalk.Exporter)})},
 args: ["aClass"],
 source: "classNameFor: aClass\x0a\x09^aClass isMetaclass\x0a\x09\x09ifTrue: [ aClass instanceClass name, '.klass' ]\x0a\x09\x09ifFalse: [\x0a\x09\x09\x09aClass isNil\x0a\x09\x09\x09\x09ifTrue: [ 'nil' ]\x0a\x09\x09\x09\x09ifFalse: [ aClass name ] ]",
-messageSends: ["ifTrue:ifFalse:", ",", "name", "instanceClass", "isNil", "isMetaclass"],
+messageSends: ["ifTrue:ifFalse:", "isMetaclass", ",", "name", "instanceClass", "isNil"],
 referencedClasses: []
 }),
 smalltalk.Exporter);
@@ -446,10 +446,10 @@ $2=_st($1)._nextPutAll_(", [");
 _st(_st(aClass)._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(_st("'".__comma(each)).__comma("'"));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(", ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $3=aStream;
 _st($3)._nextPutAll_("], '");
 _st($3)._nextPutAll_(_st(_st(aClass)._category()).__comma("'"));
@@ -469,7 +469,7 @@ _st(aStream)._lf();
 return self}, function($ctx1) {$ctx1.fill(self,"exportDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.Exporter)})},
 args: ["aClass", "aStream"],
 source: "exportDefinitionOf: aClass on: aStream\x0a\x09aStream\x0a\x09\x09lf;\x0a\x09\x09nextPutAll: 'smalltalk.addClass(';\x0a\x09\x09nextPutAll: '''', (self classNameFor: aClass), ''', ';\x0a\x09\x09nextPutAll: 'smalltalk.', (self classNameFor: aClass superclass);\x0a\x09\x09nextPutAll: ', ['.\x0a\x09aClass instanceVariableNames\x0a\x09\x09do: [:each | aStream nextPutAll: '''', each, '''']\x0a\x09\x09separatedBy: [aStream nextPutAll: ', '].\x0a\x09aStream\x0a\x09\x09nextPutAll: '], ''';\x0a\x09\x09nextPutAll: aClass category, '''';\x0a\x09\x09nextPutAll: ');'.\x0a\x09aClass comment notEmpty ifTrue: [\x0a\x09\x09aStream\x0a\x09\x09\x09lf;\x0a\x09\x09nextPutAll: 'smalltalk.';\x0a\x09\x09nextPutAll: (self classNameFor: aClass);\x0a\x09\x09nextPutAll: '.comment=';\x0a\x09\x09nextPutAll: aClass comment asJavascript;\x0a\x09\x09nextPutAll: ';'].\x0a\x09aStream lf",
-messageSends: ["lf", "nextPutAll:", ",", "classNameFor:", "superclass", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "asJavascript", "comment", "notEmpty"],
+messageSends: ["lf", "nextPutAll:", ",", "classNameFor:", "superclass", "do:separatedBy:", "instanceVariableNames", "category", "ifTrue:", "notEmpty", "comment", "asJavascript"],
 referencedClasses: []
 }),
 smalltalk.Exporter);
@@ -493,16 +493,16 @@ $3;
 _st(_st(_st(aClass)._class())._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(_st("'".__comma(each)).__comma("'"));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(",");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}));
 _st(aStream)._nextPutAll_("];".__comma(_st($String())._lf()));
 };
 return self}, function($ctx1) {$ctx1.fill(self,"exportMetaDefinitionOf:on:",{aClass:aClass,aStream:aStream},smalltalk.Exporter)})},
 args: ["aClass", "aStream"],
 source: "exportMetaDefinitionOf: aClass on: aStream\x0a\x09aStream lf.\x0a\x09aClass class instanceVariableNames isEmpty ifFalse: [\x0a\x09\x09aStream\x0a\x09\x09nextPutAll: 'smalltalk.', (self classNameFor: aClass class);\x0a\x09\x09nextPutAll: '.iVarNames = ['.\x0a\x09\x09aClass class instanceVariableNames\x0a\x09\x09do: [:each | aStream nextPutAll: '''', each, '''']\x0a\x09\x09separatedBy: [aStream nextPutAll: ','].\x0a\x09\x09aStream nextPutAll: '];', String lf]",
-messageSends: ["lf", "ifFalse:", "nextPutAll:", ",", "classNameFor:", "class", "do:separatedBy:", "instanceVariableNames", "isEmpty"],
+messageSends: ["lf", "ifFalse:", "isEmpty", "instanceVariableNames", "class", "nextPutAll:", ",", "classNameFor:", "do:separatedBy:"],
 referencedClasses: ["String"]
 }),
 smalltalk.Exporter);
@@ -615,8 +615,8 @@ fn: function (aPackage){
 var self=this;
 var name,result;
 function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
 name=_st(aPackage)._name();
@@ -628,19 +628,19 @@ return smalltalk.withContext(function($ctx3) {
 return _st(result)._addAll_(_st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
 return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3)})})))._select_((function(method){
+}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx3,3)})})))._select_((function(method){
 return smalltalk.withContext(function($ctx4) {
 return _st(_st(method)._category()).__eq("*".__comma(name));
-}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx3)})})));
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2)})}));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx3,4)})})));
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $1=result;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"extensionMethodsOfPackage:",{aPackage:aPackage,name:name,result:result},smalltalk.Exporter)})},
 args: ["aPackage"],
 source: "extensionMethodsOfPackage: aPackage\x0a\x09\x22Issue #143: sort classes and methods alphabetically\x22\x0a\x0a\x09| name result |\x0a\x09name := aPackage name.\x0a\x09result := OrderedCollection new.\x0a\x09(Package sortedClasses: Smalltalk current classes) do: [:each |\x0a\x09\x09{each. each class} do: [:aClass |\x0a\x09\x09\x09result addAll: (((aClass methodDictionary values)\x0a\x09\x09\x09\x09sorted: [:a :b | a selector <= b selector])\x0a\x09\x09\x09\x09select: [:method | method category = ('*', name)]) ]].\x0a\x09^result",
-messageSends: ["name", "new", "do:", "addAll:", "select:", "=", ",", "category", "sorted:", "<=", "selector", "values", "methodDictionary", "class", "sortedClasses:", "classes", "current"],
-referencedClasses: ["OrderedCollection", "Smalltalk", "Package"]
+messageSends: ["name", "new", "do:", "sortedClasses:", "classes", "current", "class", "addAll:", "select:", "sorted:", "values", "methodDictionary", "<=", "selector", "=", "category", ","],
+referencedClasses: ["OrderedCollection", "Package", "Smalltalk"]
 }),
 smalltalk.Exporter);
 
@@ -655,15 +655,15 @@ var $1;
 $1=_st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._reject_((function(each){
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,1)})})))._reject_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(each)._category())._match_("^\x5c*");
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"ownMethodsOfClass:",{aClass:aClass},smalltalk.Exporter)})},
 args: ["aClass"],
 source: "ownMethodsOfClass: aClass\x0a\x09\x22Issue #143: sort methods alphabetically\x22\x0a\x0a\x09^((aClass methodDictionary values) sorted: [:a :b | a selector <= b selector])\x0a\x09\x09reject: [:each | (each category match: '^\x5c*')]",
-messageSends: ["reject:", "match:", "category", "sorted:", "<=", "selector", "values", "methodDictionary"],
+messageSends: ["reject:", "sorted:", "values", "methodDictionary", "<=", "selector", "match:", "category"],
 referencedClasses: []
 }),
 smalltalk.Exporter);
@@ -726,10 +726,10 @@ $2=_st($1)._nextPutAll_(", [");
 _st(_st(aClass)._instanceVariableNames())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(_st("'".__comma(each)).__comma("'"));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}),(function(){
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(aStream)._nextPutAll_(", ");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 $3=aStream;
 _st($3)._nextPutAll_("], '");
 _st($3)._nextPutAll_(_st(_st(aClass)._category()).__comma("'"));
@@ -796,7 +796,7 @@ return smalltalk.withContext(function($ctx2) {
 char=_st(self["@stream"])._next();
 char;
 return _st(char)._notNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._whileTrue_((function(){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(char).__eq("!");
 if(smalltalk.assert($1)){
@@ -809,14 +809,14 @@ throw $early=[$3];
 };
 };
 return _st(result)._nextPut_(char);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return nil;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
 }, function($ctx1) {$ctx1.fill(self,"nextChunk",{char:char,result:result,chunk:chunk},smalltalk.ChunkParser)})},
 args: [],
 source: "nextChunk\x0a\x09\x22The chunk format (Smalltalk Interchange Format or Fileout format)\x0a\x09is a trivial format but can be a bit tricky to understand:\x0a\x09\x09- Uses the exclamation mark as delimiter of chunks.\x0a\x09\x09- Inside a chunk a normal exclamation mark must be doubled.\x0a\x09\x09- A non empty chunk must be a valid Smalltalk expression.\x0a\x09\x09- A chunk on top level with a preceding empty chunk is an instruction chunk:\x0a\x09\x09\x09- The object created by the expression then takes over reading chunks.\x0a\x0a\x09This metod returns next chunk as a String (trimmed), empty String (all whitespace) or nil.\x22\x0a\x0a\x09| char result chunk |\x0a\x09result := '' writeStream.\x0a\x09\x09[char := stream next.\x0a\x09\x09char notNil] whileTrue: [\x0a\x09\x09\x09\x09char = '!' ifTrue: [\x0a\x09\x09\x09\x09\x09\x09stream peek = '!'\x0a\x09\x09\x09\x09\x09\x09\x09\x09ifTrue: [stream next \x22skipping the escape double\x22]\x0a\x09\x09\x09\x09\x09\x09\x09\x09ifFalse: [^result contents trimBoth \x22chunk end marker found\x22]].\x0a\x09\x09\x09\x09result nextPut: char].\x0a\x09^nil \x22a chunk needs to end with !\x22",
-messageSends: ["writeStream", "whileTrue:", "ifTrue:", "ifTrue:ifFalse:", "next", "trimBoth", "contents", "=", "peek", "nextPut:", "notNil"],
+messageSends: ["writeStream", "whileTrue:", "next", "notNil", "ifTrue:", "=", "ifTrue:ifFalse:", "peek", "trimBoth", "contents", "nextPut:"],
 referencedClasses: []
 }),
 smalltalk.ChunkParser);
@@ -871,14 +871,14 @@ recipeStream=_st(aRecipe)._readStream();
 _st((function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(recipeStream)._atEnd();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._whileFalse_((function(){
 return smalltalk.withContext(function($ctx2) {
 return self._interpretStep_for_on_(_st(recipeStream)._next(),anObject,aStream);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"interpret:for:on:",{aRecipe:aRecipe,anObject:anObject,aStream:aStream,recipeStream:recipeStream},smalltalk.ExportRecipeInterpreter)})},
 args: ["aRecipe", "anObject", "aStream"],
 source: "interpret: aRecipe for: anObject on: aStream\x0a\x09| recipeStream |\x0a\x09\x0a\x09recipeStream := aRecipe readStream.\x0a\x09\x0a\x09[ recipeStream atEnd ] whileFalse: [\x0a\x09\x09self \x0a\x09\x09\x09interpretStep: recipeStream next\x0a\x09\x09\x09for: anObject\x0a\x09\x09\x09on: aStream ]",
-messageSends: ["readStream", "whileFalse:", "interpretStep:for:on:", "next", "atEnd"],
+messageSends: ["readStream", "whileFalse:", "atEnd", "interpretStep:for:on:", "next"],
 referencedClasses: []
 }),
 smalltalk.ExportRecipeInterpreter);
@@ -900,7 +900,7 @@ _st(_st(aRecipeStep)._key())._perform_withArguments_(_st(aRecipeStep)._value(),[
 return self}, function($ctx1) {$ctx1.fill(self,"interpretStep:for:on:",{aRecipeStep:aRecipeStep,anObject:anObject,aStream:aStream},smalltalk.ExportRecipeInterpreter)})},
 args: ["aRecipeStep", "anObject", "aStream"],
 source: "interpretStep: aRecipeStep for: anObject on: aStream\x0a\x09aRecipeStep value == aRecipeStep ifTrue: [ \x0a\x09\x09^ self interpretSubRecipe: aRecipeStep for: anObject on: aStream ].\x0a\x09\x09\x09\x0a\x09aRecipeStep key perform: aRecipeStep value withArguments: { anObject. aStream }",
-messageSends: ["ifTrue:", "interpretSubRecipe:for:on:", "==", "value", "perform:withArguments:", "key"],
+messageSends: ["ifTrue:", "==", "value", "interpretSubRecipe:for:on:", "perform:withArguments:", "key"],
 referencedClasses: []
 }),
 smalltalk.ExportRecipeInterpreter);
@@ -917,11 +917,11 @@ selection=_st(_st(_st(aRecipe)._first())._key())._perform_withArguments_(_st(_st
 _st(selection)._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return self._interpret_for_on_(_st(aRecipe)._allButFirst(),each,aStream);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"interpretSubRecipe:for:on:",{aRecipe:aRecipe,anObject:anObject,aStream:aStream,selection:selection},smalltalk.ExportRecipeInterpreter)})},
 args: ["aRecipe", "anObject", "aStream"],
 source: "interpretSubRecipe: aRecipe for: anObject on: aStream\x0a\x09| selection |\x0a\x09selection := aRecipe first key \x0a\x09\x09perform: aRecipe first value \x0a\x09\x09withArguments: { anObject }.\x0a\x09selection do: [ :each |\x09\x0a\x09\x09self interpret: aRecipe allButFirst for: each on: aStream ]",
-messageSends: ["perform:withArguments:", "value", "first", "key", "do:", "interpret:for:on:", "allButFirst"],
+messageSends: ["perform:withArguments:", "key", "first", "value", "do:", "interpret:for:on:", "allButFirst"],
 referencedClasses: []
 }),
 smalltalk.ExportRecipeInterpreter);
@@ -948,7 +948,7 @@ return smalltalk.withContext(function($ctx2) {
 chunk=_st(parser)._nextChunk();
 chunk;
 return _st(chunk)._isNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._whileFalse_((function(){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(chunk)._isEmpty();
 if(smalltalk.assert($1)){
@@ -964,11 +964,11 @@ lastEmpty;
 return _st(result)._scanFrom_(parser);
 };
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"import:",{aStream:aStream,chunk:chunk,result:result,parser:parser,lastEmpty:lastEmpty},smalltalk.Importer)})},
 args: ["aStream"],
 source: "import: aStream\x0a\x09| chunk result parser lastEmpty |\x0a\x09parser := ChunkParser on: aStream.\x0a\x09lastEmpty := false.\x0a\x09[chunk := parser nextChunk.\x0a\x09chunk isNil] whileFalse: [\x0a\x09\x09chunk isEmpty\x0a\x09\x09\x09ifTrue: [lastEmpty := true]\x0a\x09\x09\x09ifFalse: [\x0a\x09\x09\x09\x09result := Compiler new evaluateExpression: chunk.\x0a\x09\x09\x09\x09lastEmpty\x0a\x09\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09\x09\x09\x09lastEmpty := false.\x0a\x09\x09\x09\x09\x09\x09\x09\x09\x09result scanFrom: parser]]]",
-messageSends: ["on:", "whileFalse:", "ifTrue:ifFalse:", "evaluateExpression:", "new", "ifTrue:", "scanFrom:", "isEmpty", "nextChunk", "isNil"],
+messageSends: ["on:", "whileFalse:", "nextChunk", "isNil", "ifTrue:ifFalse:", "isEmpty", "evaluateExpression:", "new", "ifTrue:", "scanFrom:"],
 referencedClasses: ["ChunkParser", "Compiler"]
 }),
 smalltalk.Importer);
@@ -1116,7 +1116,7 @@ return smalltalk.withContext(function($ctx1) {
 self._ajax_(smalltalk.HashedCollection._from_(["url".__minus_gt(aURL),"type".__minus_gt("PUT"),"data".__minus_gt(aString),"contentType".__minus_gt("text/plain;charset=UTF-8"),"error".__minus_gt((function(xhr){
 return smalltalk.withContext(function($ctx2) {
 return self._error_(_st(_st(_st("Commiting ".__comma(aURL)).__comma(" failed with reason: \x22")).__comma(_st(xhr)._responseText())).__comma("\x22"));
-}, function($ctx2) {$ctx2.fillBlock({xhr:xhr},$ctx1)})}))]));
+}, function($ctx2) {$ctx2.fillBlock({xhr:xhr},$ctx1,1)})}))]));
 return self}, function($ctx1) {$ctx1.fill(self,"ajaxPutAt:data:",{aURL:aURL,aString:aString},smalltalk.PackageHandler)})},
 args: ["aURL", "aString"],
 source: "ajaxPutAt: aURL data: aString\x0a\x09self\x0a\x09\x09ajax: #{\x0a\x09\x09\x09'url' -> aURL.\x0a\x09\x09\x09'type' -> 'PUT'.\x0a\x09\x09\x09'data' -> aString.\x0a\x09\x09\x09'contentType' -> 'text/plain;charset=UTF-8'.\x0a\x09\x09\x09'error' -> [ :xhr | self error: 'Commiting ' , aURL , ' failed with reason: \x22' , (xhr responseText) , '\x22'] }",
@@ -1131,8 +1131,8 @@ selector: "commit:",
 category: 'committing',
 fn: function (aPackage){
 var self=this;
-function $PluggableExporter(){return smalltalk.PluggableExporter||(typeof PluggableExporter=="undefined"?nil:PluggableExporter)}
 function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
+function $PluggableExporter(){return smalltalk.PluggableExporter||(typeof PluggableExporter=="undefined"?nil:PluggableExporter)}
 return smalltalk.withContext(function($ctx1) { 
 _st(self._commitChannels())._do_displayingProgress_((function(commitStrategyFactory){
 var fileContents,commitStrategy;
@@ -1142,15 +1142,15 @@ commitStrategy;
 fileContents=_st($String())._streamContents_((function(stream){
 return smalltalk.withContext(function($ctx3) {
 return _st(_st($PluggableExporter())._forRecipe_(_st(commitStrategy)._key()))._exportPackage_on_(aPackage,stream);
-}, function($ctx3) {$ctx3.fillBlock({stream:stream},$ctx2)})}));
+}, function($ctx3) {$ctx3.fillBlock({stream:stream},$ctx2,2)})}));
 fileContents;
 return self._ajaxPutAt_data_(_st(commitStrategy)._value(),fileContents);
-}, function($ctx2) {$ctx2.fillBlock({commitStrategyFactory:commitStrategyFactory,fileContents:fileContents,commitStrategy:commitStrategy},$ctx1)})}),"Committing package ".__comma(_st(aPackage)._name()));
+}, function($ctx2) {$ctx2.fillBlock({commitStrategyFactory:commitStrategyFactory,fileContents:fileContents,commitStrategy:commitStrategy},$ctx1,1)})}),"Committing package ".__comma(_st(aPackage)._name()));
 return self}, function($ctx1) {$ctx1.fill(self,"commit:",{aPackage:aPackage},smalltalk.PackageHandler)})},
 args: ["aPackage"],
 source: "commit: aPackage\x0a\x09self commitChannels\x0a\x09\x09do: [ :commitStrategyFactory || fileContents commitStrategy |\x0a\x09\x09\x09commitStrategy := commitStrategyFactory value: aPackage.\x0a\x09\x09\x09fileContents := String streamContents: [ :stream |\x0a\x09\x09\x09\x09(PluggableExporter forRecipe: commitStrategy key) exportPackage: aPackage on: stream ].\x0a\x09\x09\x09self ajaxPutAt: commitStrategy value data: fileContents ]\x0a\x09\x09displayingProgress: 'Committing package ', aPackage name",
-messageSends: ["do:displayingProgress:", "value:", "streamContents:", "exportPackage:on:", "forRecipe:", "key", "ajaxPutAt:data:", "value", ",", "name", "commitChannels"],
-referencedClasses: ["PluggableExporter", "String"]
+messageSends: ["do:displayingProgress:", "commitChannels", "value:", "streamContents:", "exportPackage:on:", "forRecipe:", "key", "ajaxPutAt:data:", "value", ",", "name"],
+referencedClasses: ["String", "PluggableExporter"]
 }),
 smalltalk.PackageHandler);
 
@@ -1275,18 +1275,18 @@ var $1;
 $1=[(function(pkg){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($Exporter())._default())._recipe()).__minus_gt(_st(_st(_st(_st(pkg)._commitPathJs()).__comma("/")).__comma(_st(pkg)._name())).__comma(".js"));
-}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1)})}),(function(pkg){
+}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1,1)})}),(function(pkg){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($StrippedExporter())._default())._recipe()).__minus_gt(_st(_st(_st(_st(pkg)._commitPathJs()).__comma("/")).__comma(_st(pkg)._name())).__comma(".deploy.js"));
-}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1)})}),(function(pkg){
+}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1,2)})}),(function(pkg){
 return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($ChunkExporter())._default())._recipe()).__minus_gt(_st(_st(_st(_st(pkg)._commitPathSt()).__comma("/")).__comma(_st(pkg)._name())).__comma(".st"));
-}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1)})})];
+}, function($ctx2) {$ctx2.fillBlock({pkg:pkg},$ctx1,3)})})];
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"commitChannels",{},smalltalk.LegacyPackageHandler)})},
 args: [],
 source: "commitChannels\x0a\x09^{ \x0a\x09\x09[ :pkg | Exporter default recipe -> (pkg commitPathJs, '/', pkg name, '.js') ].\x0a\x09\x09[ :pkg | StrippedExporter default recipe -> (pkg commitPathJs, '/', pkg name, '.deploy.js') ].\x0a\x09\x09[ :pkg | ChunkExporter default recipe -> (pkg commitPathSt, '/', pkg name, '.st') ]\x0a\x09}",
-messageSends: ["->", ",", "name", "commitPathJs", "recipe", "default", "commitPathSt"],
+messageSends: ["->", "recipe", "default", ",", "commitPathJs", "name", "commitPathSt"],
 referencedClasses: ["Exporter", "StrippedExporter", "ChunkExporter"]
 }),
 smalltalk.LegacyPackageHandler);
@@ -1343,14 +1343,14 @@ $1=_st(_st(jqXHR)._readyState()).__eq((4));
 if(smalltalk.assert($1)){
 return self._setupPackageNamed_prefix_(packageName,aString);
 };
-}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1)})})),"error".__minus_gt((function(){
+}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1,1)})})),"error".__minus_gt((function(){
 return smalltalk.withContext(function($ctx2) {
 return self._alert_("Could not load package at: ".__comma(url));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))]));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}))]));
 return self}, function($ctx1) {$ctx1.fill(self,"loadPackage:prefix:",{packageName:packageName,aString:aString,url:url},smalltalk.LegacyPackageHandler)})},
 args: ["packageName", "aString"],
 source: "loadPackage: packageName prefix: aString\x0a\x09| url |\x0a\x09url := '/', aString, '/js/', packageName, '.js'.\x0a\x09self\x0a\x09\x09ajax: #{\x0a\x09\x09\x09'url' -> url.\x0a\x09\x09\x09'type' -> 'GET'.\x0a\x09\x09\x09'dataType' -> 'script'.\x0a\x09\x09\x09'complete' -> [ :jqXHR :textStatus |\x0a\x09\x09\x09\x09jqXHR readyState = 4\x0a\x09\x09\x09\x09\x09ifTrue: [ self setupPackageNamed: packageName prefix: aString ] ].\x0a\x09\x09\x09'error' -> [ self alert: 'Could not load package at: ', url ]\x0a\x09\x09}",
-messageSends: [",", "ajax:", "->", "ifTrue:", "setupPackageNamed:prefix:", "=", "readyState", "alert:"],
+messageSends: [",", "ajax:", "->", "ifTrue:", "=", "readyState", "setupPackageNamed:prefix:", "alert:"],
 referencedClasses: []
 }),
 smalltalk.LegacyPackageHandler);
@@ -1365,7 +1365,7 @@ return smalltalk.withContext(function($ctx1) {
 _st(aCollection)._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return self._loadPackage_prefix_(each,aString);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"loadPackages:prefix:",{aCollection:aCollection,aString:aString},smalltalk.LegacyPackageHandler)})},
 args: ["aCollection", "aString"],
 source: "loadPackages: aCollection prefix: aString\x0a\x09aCollection do: [ :each |\x0a\x09\x09self loadPackage: each prefix: aString ]",
@@ -1560,8 +1560,8 @@ selector: "exportAllPackages",
 category: 'fileOut',
 fn: function (){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
 $1=_st($String())._streamContents_((function(stream){
@@ -1569,14 +1569,14 @@ return smalltalk.withContext(function($ctx2) {
 return _st(_st(_st($Smalltalk())._current())._packages())._do_((function(pkg){
 return smalltalk.withContext(function($ctx3) {
 return self._exportPackage_on_(pkg,stream);
-}, function($ctx3) {$ctx3.fillBlock({pkg:pkg},$ctx2)})}));
-}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1)})}));
+}, function($ctx3) {$ctx3.fillBlock({pkg:pkg},$ctx2,2)})}));
+}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1,1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"exportAllPackages",{},smalltalk.PluggableExporter)})},
 args: [],
 source: "exportAllPackages\x0a\x09\x22Export all packages in the system.\x22\x0a\x0a\x09^String streamContents: [:stream |\x0a\x09\x09Smalltalk current packages do: [:pkg |\x0a\x09\x09self exportPackage: pkg on: stream]]",
-messageSends: ["streamContents:", "do:", "exportPackage:on:", "packages", "current"],
-referencedClasses: ["Smalltalk", "String"]
+messageSends: ["streamContents:", "do:", "packages", "current", "exportPackage:on:"],
+referencedClasses: ["String", "Smalltalk"]
 }),
 smalltalk.PluggableExporter);
 
@@ -1591,7 +1591,7 @@ _st(self._interpreter())._interpret_for_on_(self._recipe(),aPackage,aStream);
 return self}, function($ctx1) {$ctx1.fill(self,"exportPackage:on:",{aPackage:aPackage,aStream:aStream},smalltalk.PluggableExporter)})},
 args: ["aPackage", "aStream"],
 source: "exportPackage: aPackage on: aStream\x0a\x09self interpreter interpret: self recipe for: aPackage on: aStream",
-messageSends: ["interpret:for:on:", "recipe", "interpreter"],
+messageSends: ["interpret:for:on:", "interpreter", "recipe"],
 referencedClasses: []
 }),
 smalltalk.PluggableExporter);
@@ -1725,12 +1725,12 @@ $2=$3;
 $1=_st($2)._at_ifAbsentPut_("commitPathJs",(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(self._transport())._commitPathJsFor_(self);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"commitPathJs",{},smalltalk.Package)})},
 args: [],
 source: "commitPathJs\x0a\x09^ (extension ifNil: [ extension := #{} ]) at: #commitPathJs ifAbsentPut: [self transport commitPathJsFor: self]",
-messageSends: ["at:ifAbsentPut:", "commitPathJsFor:", "transport", "ifNil:"],
+messageSends: ["at:ifAbsentPut:", "ifNil:", "commitPathJsFor:", "transport"],
 referencedClasses: []
 }),
 smalltalk.Package);
@@ -1778,12 +1778,12 @@ $2=$3;
 $1=_st($2)._at_ifAbsentPut_("commitPathSt",(function(){
 return smalltalk.withContext(function($ctx2) {
 return _st(self._transport())._commitPathStFor_(self);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"commitPathSt",{},smalltalk.Package)})},
 args: [],
 source: "commitPathSt\x0a\x09^ (extension ifNil: [ extension := #{} ]) at: #commitPathSt ifAbsentPut: [self transport commitPathStFor: self]",
-messageSends: ["at:ifAbsentPut:", "commitPathStFor:", "transport", "ifNil:"],
+messageSends: ["at:ifAbsentPut:", "ifNil:", "commitPathStFor:", "transport"],
 referencedClasses: []
 }),
 smalltalk.Package);

+ 1 - 1
js/Kernel-Classes.deploy.js

@@ -1049,7 +1049,7 @@ return $3;
 $4=self._basicAddSubclassOf_named_instanceVariableNames_package_(aClass,className,aCollection,packageName);
 return $4;
 }, function($ctx1) {$ctx1.fill(self,"addSubclassOf:named:instanceVariableNames:package:",{aClass:aClass,className:className,aCollection:aCollection,packageName:packageName,theClass:theClass,thePackage:thePackage},smalltalk.ClassBuilder)})},
-messageSends: ["at:", "current", "createPackageNamed:", "ifNotNil:", "package:", "ifFalse:", "migrateClassNamed:superclass:instanceVariableNames:package:", "==", "superclass", "basicAddSubclassOf:named:instanceVariableNames:package:"]}),
+messageSends: ["at:", "current", "createPackageNamed:", "ifNotNil:", "package:", "ifFalse:", "==", "superclass", "migrateClassNamed:superclass:instanceVariableNames:package:", "basicAddSubclassOf:named:instanceVariableNames:package:"]}),
 smalltalk.ClassBuilder);
 
 smalltalk.addMethod(

+ 1 - 1
js/Kernel-Classes.js

@@ -1376,7 +1376,7 @@ return $4;
 }, function($ctx1) {$ctx1.fill(self,"addSubclassOf:named:instanceVariableNames:package:",{aClass:aClass,className:className,aCollection:aCollection,packageName:packageName,theClass:theClass,thePackage:thePackage},smalltalk.ClassBuilder)})},
 args: ["aClass", "className", "aCollection", "packageName"],
 source: "addSubclassOf: aClass named: className instanceVariableNames: aCollection package: packageName\x0a\x09| theClass thePackage |\x0a\x09\x0a\x09theClass := Smalltalk current at: className.\x0a\x09thePackage := self createPackageNamed: packageName.\x0a\x09\x0a\x09theClass ifNotNil: [\x0a\x09\x09theClass package: thePackage.\x0a\x09\x09theClass superclass == aClass ifFalse: [\x0a\x09\x09\x09^ self\x0a\x09\x09\x09\x09migrateClassNamed: className\x0a\x09\x09\x09\x09superclass: aClass\x0a\x09\x09\x09\x09instanceVariableNames: aCollection\x0a\x09\x09\x09\x09package: packageName ] ].\x0a\x09\x09\x0a\x09^ self\x0a\x09\x09basicAddSubclassOf: aClass\x0a\x09\x09named: className\x0a\x09\x09instanceVariableNames: aCollection\x0a\x09\x09package: packageName",
-messageSends: ["at:", "current", "createPackageNamed:", "ifNotNil:", "package:", "ifFalse:", "migrateClassNamed:superclass:instanceVariableNames:package:", "==", "superclass", "basicAddSubclassOf:named:instanceVariableNames:package:"],
+messageSends: ["at:", "current", "createPackageNamed:", "ifNotNil:", "package:", "ifFalse:", "==", "superclass", "migrateClassNamed:superclass:instanceVariableNames:package:", "basicAddSubclassOf:named:instanceVariableNames:package:"],
 referencedClasses: ["Smalltalk"]
 }),
 smalltalk.ClassBuilder);

+ 13 - 0
js/Kernel-Collections.deploy.js

@@ -3319,6 +3319,19 @@ return self}, function($ctx1) {$ctx1.fill(self,"crlf",{},smalltalk.String.klass)
 messageSends: []}),
 smalltalk.String.klass);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "esc",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self._fromCharCode_((27));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"esc",{},smalltalk.String.klass)})},
+messageSends: ["fromCharCode:"]}),
+smalltalk.String.klass);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "fromCharCode:",

+ 18 - 0
js/Kernel-Collections.js

@@ -4463,6 +4463,24 @@ referencedClasses: []
 }),
 smalltalk.String.klass);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "esc",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self._fromCharCode_((27));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"esc",{},smalltalk.String.klass)})},
+args: [],
+source: "esc\x0a\x09^ self fromCharCode: 27",
+messageSends: ["fromCharCode:"],
+referencedClasses: []
+}),
+smalltalk.String.klass);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "fromCharCode:",

+ 40 - 0
st/Helios-Commands-Core.st

@@ -273,6 +273,46 @@ label
 	^ 'Workspace'
 ! !
 
+HLCommand subclass: #HLSwitchTabCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands-Core'!
+
+!HLSwitchTabCommand methodsFor: 'accessing'!
+
+selectedTab
+	^ HLManager current activeTab
+!
+
+tabs
+	^ HLManager current tabs
+! !
+
+!HLSwitchTabCommand methodsFor: 'executing'!
+
+execute
+	| activeTab |
+	
+	activeTab := self selectedTab.
+	
+	^ HLTabSelectionWidget new
+		tabs: self tabs;
+		selectedTab: self selectedTab;
+		selectCallback: [ :tab | tab activate ];
+		confirmCallback: [ :tab | tab focus ];
+		cancelCallback: [ activeTab activate ];
+		show
+! !
+
+!HLSwitchTabCommand class methodsFor: 'accessing'!
+
+key
+	^ 's'
+!
+
+label
+	^ 'Switch'
+! !
+
 HLCommand subclass: #HLViewCommand
 	instanceVariableNames: ''
 	package: 'Helios-Commands-Core'!

+ 199 - 55
st/Helios-Core.st

@@ -612,7 +612,7 @@ unregister
 
 !HLWidget methodsFor: 'keybindings'!
 
-bindKeyDown: keyDownBlock up: keyUpBlock
+bindKeyDown: keyDownBlock keyUp: keyUpBlock
 	self wrapper asJQuery
 		keydown: keyDownBlock;
 		keyup: keyUpBlock
@@ -625,7 +625,7 @@ registerBindings
 registerBindingsOn: aBindingGroup
 !
 
-unbindKeyDownUp
+unbindKeyDownKeyUp
 	self wrapper asJQuery
 		unbind: 'keydown';
 		unbind: 'keyup'
@@ -854,9 +854,9 @@ defaultItems
 !HLListWidget methodsFor: 'events'!
 
 setupKeyBindings 
-	(HLRepeatingKeyBindingHandler forWidget: self)
-		whileKeyPressed: 38 do: [ self activatePreviousListItem ];
-		whileKeyPressed: 40 do: [ self activateNextListItem ];
+	(HLRepeatedKeyDownHandler on: self)
+		whileKeyDown: 38 do: [ self activatePreviousListItem ];
+		whileKeyDown: 40 do: [ self activateNextListItem ];
 		rebindKeys
 ! !
 
@@ -1089,8 +1089,39 @@ on: aModel
         yourself
 ! !
 
+HLListWidget subclass: #HLTabListWidget
+	instanceVariableNames: 'callback'
+	package: 'Helios-Core'!
+!HLTabListWidget commentStamp!
+I am a widget used to display a list of helios tabs.
+
+When a tab is selected, `callback` is evaluated with the selected tab as argument.!
+
+!HLTabListWidget methodsFor: 'accessing'!
+
+callback
+	^ callback ifNil: [ [] ]
+!
+
+callback: aBlock
+	callback := aBlock
+! !
+
+!HLTabListWidget methodsFor: 'actions'!
+
+selectItem: aTab
+	super selectItem: aTab.
+	self callback value: aTab
+! !
+
+!HLTabListWidget methodsFor: 'rendering'!
+
+renderItemLabel: aTab on: html
+	html with: aTab label
+! !
+
 HLWidget subclass: #HLManager
-	instanceVariableNames: 'tabs activeTab keyBinder environment history'
+	instanceVariableNames: 'tabs activeTab environment history'
 	package: 'Helios-Core'!
 
 !HLManager methodsFor: 'accessing'!
@@ -1118,7 +1149,7 @@ history: aCollection
 !
 
 keyBinder
-	^ keyBinder ifNil: [ keyBinder := HLKeyBinder new ]
+	^ HLKeyBinder current
 !
 
 tabs
@@ -1149,19 +1180,17 @@ addToHistory: aTab
 !
 
 confirm: aString ifFalse: aBlock
-	(HLConfirmationWidget new
+	HLConfirmationWidget new
 		confirmationString: aString;
 		cancelBlock: aBlock;
-		yourself)
-			appendToJQuery: 'body' asJQuery
+		show
 !
 
 confirm: aString ifTrue: aBlock
-	(HLConfirmationWidget new
+	HLConfirmationWidget new
 		confirmationString: aString;
 		actionBlock: aBlock;
-		yourself)
-			appendToJQuery: 'body' asJQuery
+		show
 !
 
 registerErrorHandler: anErrorHandler
@@ -1204,12 +1233,11 @@ request: aString do: aBlock
 !
 
 request: aString value: valueString do: aBlock
-	(HLRequestWidget new
+	HLRequestWidget new
 		confirmationString: aString;
 		actionBlock: aBlock;
 		value: valueString;
-		yourself)
-			appendToJQuery: 'body' asJQuery
+		show
 ! !
 
 !HLManager methodsFor: 'defaults'!
@@ -1356,17 +1384,45 @@ cancel
 	self remove
 !
 
+confirm
+	"Override in subclasses"
+	self remove
+!
+
 remove
 	'.dialog' asJQuery removeClass: 'active'.
 	[ 
 		'#overlay' asJQuery remove.
 		'.dialog' asJQuery remove
 	] valueWithTimeout: 300
+!
+
+show
+	self appendToJQuery: 'body' asJQuery
 ! !
 
 !HLModalWidget methodsFor: 'rendering'!
 
+hasButtons
+	^ true
+!
+
 renderButtonsOn: html
+	| confirmButton |
+	
+	html div 
+		class: 'buttons';
+		with: [
+			html button
+				class: 'button';
+				with: 'Cancel';
+				onClick: [ self cancel ].
+			confirmButton := html button
+				class: 'button default';
+				with: 'Confirm';
+				onClick: [ self confirm ] ].
+
+	confirmButton asJQuery focus
 !
 
 renderContentOn: html
@@ -1376,9 +1432,9 @@ renderContentOn: html
 	html div 
 		class: 'dialog ', self cssClass;
 		with: [
-			self
-				renderMainOn: html;
-				renderButtonsOn: html ].
+			self renderMainOn: html.
+			self hasButtons ifTrue: [ 
+				self renderButtonsOn: html ] ].
 
 	'.dialog' asJQuery addClass: 'active'.
 	self setupKeyBindings
@@ -1389,7 +1445,7 @@ renderMainOn: html
 
 setupKeyBindings
 	'.dialog' asJQuery keyup: [ :e |
-		e keyCode = 27 ifTrue: [ self cancel ] ]
+		e keyCode = String esc asciiValue ifTrue: [ self cancel ] ]
 ! !
 
 HLModalWidget subclass: #HLConfirmationWidget
@@ -1430,42 +1486,16 @@ confirmationString: aString
 
 cancel
 	self cancelBlock value.
-	self remove
+	super cancel
 !
 
 confirm
-	self actionBlock value.
-	self remove
-!
-
-remove
-	'.dialog' asJQuery removeClass: 'active'.
-	[ 
-		'#overlay' asJQuery remove.
-		'.dialog' asJQuery remove
-	] valueWithTimeout: 300
+	super confirm.
+	self actionBlock value
 ! !
 
 !HLConfirmationWidget methodsFor: 'rendering'!
 
-renderButtonsOn: html
-	| confirmButton |
-	
-	html div 
-		class: 'buttons';
-		with: [
-			html button
-				class: 'button';
-				with: 'Cancel';
-				onClick: [ self cancel ].
-			confirmButton := html button
-				class: 'button default';
-				with: 'Confirm';
-				onClick: [ self confirm ] ].
-
-	confirmButton asJQuery focus
-!
-
 renderMainOn: html
 	html span with: self confirmationString
 ! !
@@ -1495,8 +1525,8 @@ value: aString
 !HLRequestWidget methodsFor: 'actions'!
 
 confirm
-	self actionBlock value: input asJQuery val.
-	self remove
+	super confirm.
+	self actionBlock value: input asJQuery val
 ! !
 
 !HLRequestWidget methodsFor: 'rendering'!
@@ -1566,14 +1596,11 @@ removeProgressBar: aProgressBar
 show
 	self isVisible ifFalse: [
 		visible := true.
-		self appendToJQuery: 'body' asJQuery ]
+		super show ]
 ! !
 
 !HLProgressWidget methodsFor: 'rendering'!
 
-renderButtonsOn: html
-!
-
 renderMainOn: html
 	self progressBars do: [ :each |
 		html with: each ]
@@ -1581,6 +1608,10 @@ renderMainOn: html
 
 !HLProgressWidget methodsFor: 'testing'!
 
+hasButtons
+	^ false
+!
+
 isVisible
 	^ visible ifNil: [ false ]
 ! !
@@ -1593,6 +1624,119 @@ default
 	^ default ifNil: [ default := self new ]
 ! !
 
+HLModalWidget subclass: #HLTabSelectionWidget
+	instanceVariableNames: 'tabs tabList selectedTab selectCallback cancelCallback confirmCallback'
+	package: 'Helios-Core'!
+!HLTabSelectionWidget commentStamp!
+I am a modal window used to select or create tabs.!
+
+!HLTabSelectionWidget methodsFor: 'accessing'!
+
+cancelCallback
+	^ cancelCallback ifNil: [ [] ]
+!
+
+cancelCallback: aBlock
+	cancelCallback := aBlock
+!
+
+confirmCallback
+	^ confirmCallback ifNil: [ [] ]
+!
+
+confirmCallback: aBlock
+	confirmCallback := aBlock
+!
+
+selectCallback
+	^ selectCallback ifNil: [ [] ]
+!
+
+selectCallback: aBlock
+	selectCallback := aBlock
+!
+
+selectedTab
+	^ selectedTab
+!
+
+selectedTab: aTab
+	selectedTab := aTab
+!
+
+tabs
+	^ tabs ifNil: [ #() ]
+!
+
+tabs: aCollection
+	tabs := aCollection
+! !
+
+!HLTabSelectionWidget methodsFor: 'actions'!
+
+cancel
+	super cancel.
+	self cancelCallback value
+!
+
+confirm
+	super confirm.
+	self confirmCallback value: self selectedTab
+!
+
+selectTab: aTab
+	self selectedTab: aTab.
+	self selectCallback value: aTab
+!
+
+setupKeyBindings
+	super setupKeyBindings.
+	'.dialog' asJQuery keyup: [ :e |
+		e keyCode = String cr asciiValue ifTrue: [ self confirm ] ]
+! !
+
+!HLTabSelectionWidget methodsFor: 'rendering'!
+
+renderContentOn: html
+	super renderContentOn: html.
+	self tabList focus
+!
+
+renderMainOn: html
+	html div 
+		class: 'title'; 
+		with: 'Tab selection'.
+	
+	html with: self tabList
+!
+
+renderTab: aTab on: html
+	html 
+		span 
+			class: aTab cssClass;
+			with: aTab label
+!
+
+renderTabsOn: html
+	self tabs do: [ :each |
+		html li with: [ 
+			html a 
+				with: [ 
+					self renderTab: each on: html ];
+				onClick: [ self selectTab: each ] ] ]
+!
+
+tabList
+	tabList ifNil: [ 
+		tabList := HLTabListWidget new.
+		tabList
+			callback: [ :tab | self selectTab: tab. tabList focus ];
+			selectedItem: self selectedTab;
+			items: self tabs ].
+	
+	^ tabList
+! !
+
 HLWidget subclass: #HLProgressBarWidget
 	instanceVariableNames: 'label parent workBlock collection bar'
 	package: 'Helios-Core'!

+ 218 - 165
st/Helios-KeyBindings.st

@@ -2,10 +2,21 @@ Smalltalk current createPackage: 'Helios-KeyBindings'!
 Object subclass: #HLBinding
 	instanceVariableNames: 'key label'
 	package: 'Helios-KeyBindings'!
+!HLBinding commentStamp!
+I am the abstract representation of a keybinding in Helios. My instances hold a key (integer value) and a label. 
+
+Bindings are built into a tree of keys, so pressing a key may result in more key choices (for example, to open a workspace, 'o' is pressed first then 'w' is pressed).
+
+Binding action handling and selection is handled by the `current` instance of `HLKeyBinder`.
+
+Subclasses implement specific behavior like evaluating actions or (sub-)grouping other bindings.!
 
 !HLBinding methodsFor: 'accessing'!
 
 atKey: aKey
+	"Answer the sub-binding at key aKey.
+	Always answer nil here. See HLBindingGroup for more."
+	
 	^ nil
 !
 
@@ -35,7 +46,7 @@ shortcut
 
 !HLBinding methodsFor: 'actions'!
 
-applyOn: aKeyBinder
+apply
 !
 
 release
@@ -43,17 +54,6 @@ release
 
 !HLBinding methodsFor: 'rendering'!
 
-renderActionFor: aBinder html: html
-	html span class: 'command'; with: [
-		html span 
-			class: 'label'; 
-			with: self shortcut asLowercase.
-  		html a 
-        	class: 'action'; 
-            with: self displayLabel;
-  			onClick: [ aBinder applyBinding: self ] ]
-!
-
 renderOn: aBindingHelper html: html
 ! !
 
@@ -61,12 +61,6 @@ renderOn: aBindingHelper html: html
 
 isActive
 	^ self subclassResponsibility
-!
-
-isFinal
-	" Answer true if the receiver is the final binding of a sequence "
-	
-	^ false
 ! !
 
 !HLBinding class methodsFor: 'instance creation'!
@@ -81,6 +75,10 @@ on: anInteger labelled: aString
 HLBinding subclass: #HLBindingAction
 	instanceVariableNames: 'command'
 	package: 'Helios-KeyBindings'!
+!HLBindingAction commentStamp!
+My instances are the leafs of the binding tree. They evaluate actions through commands, instances of concrete subclasses of `HLCommand`.
+
+The `#apply` methods is used to evaluate the `command`. If the command requires user input, an `inputWidget` will be displayed to the user.!
 
 !HLBindingAction methodsFor: 'accessing'!
 
@@ -92,6 +90,10 @@ command: aCommand
 	command := aCommand
 !
 
+input: aString
+	self command input: aString
+!
+
 inputBinding
 	^ HLBindingInput new
 		label: self command inputLabel;
@@ -103,29 +105,46 @@ inputBinding
 				input: val;
 				execute ];
 		yourself
+!
+
+inputWidget
+	^ HLBindingActionInputWidget new
+		ghostText: self command displayLabel;
+		defaultValue: self command defaultInput;
+		inputCompletion: self command inputCompletion;
+		callback: [ :value | 
+			self 
+				input: value;
+				executeCommand ];
+		yourself
 ! !
 
 !HLBindingAction methodsFor: 'actions'!
 
-applyOn: aKeyBinder
+apply
 	self command isInputRequired
-		ifTrue: [ aKeyBinder selectBinding: self inputBinding ]
-		ifFalse: [ self command execute ]
+		ifTrue: [ HLKeyBinder current helper showWidget: self inputWidget ]
+		ifFalse: [ self executeCommand ]
+!
+
+executeCommand
+	self command execute.
+	HLKeyBinder current deactivate
 ! !
 
 !HLBindingAction methodsFor: 'testing'!
 
 isActive
 	^ self command isActive
-!
-
-isFinal
-	^ self command isInputRequired not
 ! !
 
 HLBinding subclass: #HLBindingGroup
 	instanceVariableNames: 'bindings'
 	package: 'Helios-KeyBindings'!
+!HLBindingGroup commentStamp!
+My instances hold other bindings, either actions or groups, and do not have actions by themselves.
+
+Children are accessed with `atKey:` and added with the `add*` methods.!
 
 !HLBindingGroup methodsFor: 'accessing'!
 
@@ -133,20 +152,6 @@ activeBindings
 	^ self bindings select: [ :each | each isActive ]
 !
 
-add: aBinding
-	^ self bindings add: aBinding
-!
-
-addActionKey: anInteger labelled: aString callback: aBlock
-	self add: ((HLBindingAction on: anInteger labelled: aString)
-    	callback: aBlock;
-        yourself)
-!
-
-addGroupKey: anInteger labelled: aString
-	self add: (HLBindingGroup on: anInteger labelled: aString)
-!
-
 at: aString
 	^ self bindings 
     	detect: [ :each | each label = aString ]
@@ -182,6 +187,24 @@ release
 	self bindings do: [ :each | each release ]
 ! !
 
+!HLBindingGroup methodsFor: 'add'!
+
+addGroupKey: anInteger labelled: aString
+	self add: (HLBindingGroup on: anInteger labelled: aString)
+! !
+
+!HLBindingGroup methodsFor: 'adding'!
+
+add: aBinding
+	^ self bindings add: aBinding
+!
+
+addActionKey: anInteger labelled: aString callback: aBlock
+	self add: ((HLBindingAction on: anInteger labelled: aString)
+    	callback: aBlock;
+        yourself)
+! !
+
 !HLBindingGroup methodsFor: 'rendering'!
 
 renderOn: aBindingHelper html: html
@@ -195,15 +218,13 @@ isActive
 	^ self activeBindings notEmpty
 ! !
 
-HLBinding subclass: #HLBindingInput
-	instanceVariableNames: 'input callback status wrapper binder ghostText isFinal message messageTag inputCompletion defaultValue'
+HLWidget subclass: #HLBindingActionInputWidget
+	instanceVariableNames: 'input callback status wrapper ghostText message inputCompletion defaultValue messageTag'
 	package: 'Helios-KeyBindings'!
+!HLBindingActionInputWidget commentStamp!
+My instances are built when a `HLBindingAction` that requires user input is applied.!
 
-!HLBindingInput methodsFor: 'accessing'!
-
-atKey: aKey
-	aKey = 13 ifFalse: [ ^ nil ]
-!
+!HLBindingActionInputWidget methodsFor: 'accessing'!
 
 callback
 	^ callback ifNil: [ callback := [ :value | ] ]
@@ -257,12 +278,7 @@ status: aStatus
 	status := aStatus
 ! !
 
-!HLBindingInput methodsFor: 'actions'!
-
-applyOn: aKeyBinder
-	self isFinal: true.
-	self evaluate: self input asJQuery val
-!
+!HLBindingActionInputWidget methodsFor: 'actions'!
 
 clearStatus
 	self status: 'info'.
@@ -275,36 +291,27 @@ errorStatus
 	self refresh
 !
 
-evaluate: aString
-	
+evaluate: aString	
 	[ self callback value: aString ]
-	on: Error
-	do: [:ex |
-		self input asJQuery 
-			one: 'keydown' 
-			do: [ self clearStatus ].
-		self message: ex messageText.
-		self errorStatus.
-		self isFinal: false ].
+		on: Error
+		do: [:ex |
+			self input asJQuery 
+				one: 'keydown' 
+				do: [ self clearStatus ].
+			self message: ex messageText.
+			self errorStatus ]
 !
 
-release
-	status := nil.
-	wrapper := nil.
-	binder := nil
-! !
-
-!HLBindingInput methodsFor: 'rendering'!
-
 refresh
 	wrapper ifNil: [ ^ self ].
     
 	wrapper class: self status.
 	messageTag contents: self message
-!
+! !
 
-renderOn: aBinder html: html
-	binder := aBinder.
+!HLBindingActionInputWidget methodsFor: 'rendering'!
+
+renderOn: html
 	wrapper ifNil: [ wrapper := html span ].
 
 	wrapper 
@@ -313,6 +320,9 @@ renderOn: aBinder html: html
 			input := html input
 				placeholder: self ghostText;
 				value: self defaultValue;
+				onKeyDown: [ :event | 
+					event which = 13 ifTrue: [
+						self evaluate: input asJQuery val ] ]
 				yourself.
 			input asJQuery 
 				typeahead: #{ 'source' -> self inputCompletion }.
@@ -328,23 +338,19 @@ renderOn: aBinder html: html
 	[ input asJQuery focus ] valueWithTimeout: 10
 ! !
 
-!HLBindingInput methodsFor: 'testing'!
+Object subclass: #HLKeyBinder
+	instanceVariableNames: 'modifierKey helper bindings selectedBinding'
+	package: 'Helios-KeyBindings'!
+!HLKeyBinder commentStamp!
+My `current` instance holds keybindings for Helios actions and evaluate them.
 
-isActive
-	^ true
-!
+Bindings can be nested by groups. The `bindings` instance variable holds the root of the key bindings tree.
 
-isFinal
-	^ isFinal ifNil: [ isFinal := super isFinal ]
-!
+Bindings are instances of a concrete subclass of `HLBinding`.
 
-isFinal: aBoolean
-	isFinal := aBoolean
-! !
+I am always either in 'active' or 'inactive' state. In active state I capture key down events and my `helper` widget is displayed at the bottom of the window. My `selectedBinding`, if any, is displayed by the helper.
 
-Object subclass: #HLKeyBinder
-	instanceVariableNames: 'modifierKey helper bindings selectedBinding'
-	package: 'Helios-KeyBindings'!
+Bindings are evaluated through `applyBinding:`. If a binding is final (not a group of other bindings), evaluating it will result in deactivating the binder, and hiding the `helper` widget.!
 
 !HLKeyBinder methodsFor: 'accessing'!
 
@@ -384,9 +390,7 @@ applyBinding: aBinding
 	aBinding isActive ifFalse: [ ^ self ].
 	
 	self selectBinding: aBinding.
-    aBinding applyOn: self.
-	
-	aBinding isFinal ifTrue: [ self deactivate ]
+    aBinding apply
 !
 
 deactivate
@@ -412,8 +416,8 @@ defaultBindings
 	| group |
 	
 	group := HLBindingGroup new
-		addGroupKey: 86 labelled: 'View';
 		add: HLCloseTabCommand new asBinding;
+		add: HLSwitchTabCommand new asBinding;
 		yourself.
 		
 	HLOpenCommand registerConcreteClassesOn: group.
@@ -469,7 +473,7 @@ setupEvents
 
 initialize
 	super initialize.
-	helper := HLKeyBinderHelper on: self.
+	helper := HLKeyBinderHelperWidget on: self.
 	helper 	
 		renderStart;
 		renderCog
@@ -485,11 +489,27 @@ systemIsMac
 	^ navigator platform match: 'Mac'
 ! !
 
-HLWidget subclass: #HLKeyBinderHelper
+HLKeyBinder class instanceVariableNames: 'current'!
+
+!HLKeyBinder class methodsFor: 'instance creation'!
+
+current
+	^ current ifNil: [ current := super new ]
+!
+
+new
+	self shouldNotImplement
+! !
+
+HLWidget subclass: #HLKeyBinderHelperWidget
 	instanceVariableNames: 'keyBinder'
 	package: 'Helios-KeyBindings'!
+!HLKeyBinderHelperWidget commentStamp!
+I am the widget responsible for displaying active keybindings in a bar at the bottom of the window. Each keybinding is an instance of `HLBinding`. 
 
-!HLKeyBinderHelper methodsFor: 'accessing'!
+Rendering is done through a double dispatch, see `#renderSelectedBindingOn:`.!
+
+!HLKeyBinderHelperWidget methodsFor: 'accessing'!
 
 cssClass
 	^ 'key_helper'
@@ -503,11 +523,15 @@ keyBinder: aKeyBinder
 	keyBinder := aKeyBinder
 !
 
+mainId
+	^ 'binding-helper-main'
+!
+
 selectedBinding
 	^ self keyBinder selectedBinding
 ! !
 
-!HLKeyBinderHelper methodsFor: 'actions'!
+!HLKeyBinderHelperWidget methodsFor: 'actions'!
 
 hide
 	('.', self cssClass) asJQuery remove.
@@ -525,24 +549,33 @@ show
 
 showCog
 	'#cog-helper' asJQuery show
-! !
-
-!HLKeyBinderHelper methodsFor: 'keyBindings'!
+!
 
-registerBindings
-	"Do nothing"
+showWidget: aWidget
+	"Some actions need to display more info to the user or request input.
+	This method is the right place for that"
+	
+	('#', self mainId) asJQuery empty.
+	aWidget appendToJQuery: ('#', self mainId) asJQuery
 ! !
 
-!HLKeyBinderHelper methodsFor: 'rendering'!
+!HLKeyBinderHelperWidget methodsFor: 'rendering'!
+
+renderBindingActionFor: aBinding on: html
+	html span class: 'command'; with: [
+		html span 
+			class: 'label'; 
+			with: aBinding shortcut asLowercase.
+  		html a 
+        	class: 'action'; 
+            with: aBinding displayLabel;
+  			onClick: [ self keyBinder applyBinding: aBinding ] ]
+!
 
 renderBindingGroup: aBindingGroup on: html
 	(aBindingGroup activeBindings 
     	sorted: [ :a :b | a key < b key ])
-        do: [ :each | each renderActionFor: self keyBinder html: html ]
-!
-
-renderBindingOn: html
-	self selectedBinding renderOn: self html: html
+        do: [ :each | self renderBindingActionFor: each on: html ]
 !
 
 renderCloseOn: html
@@ -565,18 +598,23 @@ renderCog
 
 renderContentOn: html
 	html div class: self cssClass; with: [
-      	self 
-        	renderSelectionOn:html;
-          	renderBindingOn: html;
-			renderCloseOn: html ]
+      	self renderLabelOn:html.
+		html div
+			id: self mainId;
+			with: [ self renderSelectedBindingOn: html ].
+		self renderCloseOn: html ]
 !
 
-renderSelectionOn: html
+renderLabelOn: html
 		html span 
         	class: 'selected'; 
             with: (self selectedBinding label ifNil: [ 'Action' ])
 !
 
+renderSelectedBindingOn: html
+	self selectedBinding renderOn: self html: html
+!
+
 renderStart
 	'#helper' asJQuery remove.
 
@@ -589,7 +627,7 @@ renderStart
 		valueWithTimeout: 2000
 ! !
 
-!HLKeyBinderHelper class methodsFor: 'instance creation'!
+!HLKeyBinderHelperWidget class methodsFor: 'instance creation'!
 
 on: aKeyBinder
 	^ self new
@@ -597,100 +635,115 @@ on: aKeyBinder
         yourself
 ! !
 
-Object subclass: #HLRepeatingKeyBindingHandler
-	instanceVariableNames: 'repeatInterval delay interval keyBindings widget isKeyCurrentlyPressed'
+Object subclass: #HLRepeatedKeyDownHandler
+	instanceVariableNames: 'repeatInterval delay interval keyBindings widget keyDown'
 	package: 'Helios-KeyBindings'!
-!HLRepeatingKeyBindingHandler commentStamp!
+!HLRepeatedKeyDownHandler commentStamp!
+I am responsible for handling repeated key down actions for widgets.
+
 ##Usage
 
-    (HLRepeatingKeyBindingHandler forWidget: aWidget)
-        whileKeyPressed: keyCode do: [xxxx];
-        whileKeyPressed: anotherKey do: [yyy];
-        rebind
+    (self on: aWidget)
+        whileKeyDown: 38 do: aBlock;
+        whileKeyDown: 40 do: anotherBlock;
+        bindKeys
+
+I perform an action block on a key press, wait for 300 ms and then preform the same action block every `repeatInterval` milliseconds until the key is released.!
 
-Performs an action on a key press, waits for 300 ms and then preforms the action every repeatInterval ms until the button is released!
+!HLRepeatedKeyDownHandler methodsFor: 'accessing'!
 
-!HLRepeatingKeyBindingHandler methodsFor: 'accessing'!
+keyBindings
+	^ keyBindings ifNil: [ keyBindings := Dictionary new ]
+!
 
-repeatInterval: aMillisecondIntegerValue 
-	repeatInterval := aMillisecondIntegerValue
+repeatInterval
+	^ repeatInterval ifNil: [ self defaultRepeatInterval ]
 !
 
-whileKeyPressed: aKey do: aBlock
-	keyBindings at: aKey put: aBlock
+repeatInterval: anInteger
+	repeatInterval := anInteger
+!
+
+widget
+	^ widget
 !
 
 widget: aWidget
 	widget := aWidget
 ! !
 
-!HLRepeatingKeyBindingHandler methodsFor: 'actions'!
+!HLRepeatedKeyDownHandler methodsFor: 'actions'!
 
-bindKeys
-	widget bindKeyDown: [ :e | self handleKeyDown: e ] up: [ :e | self handleKeyUp: e ]
+startRepeatingAction: aBlock
+	^ [ (self widget hasFocus)
+		ifTrue: [ aBlock value ]
+		ifFalse: [ self handleKeyUp ] ] valueWithInterval: self repeatInterval
 !
 
-delayBeforeStartingRepeatWithAction: action
-	^ [ interval := self startRepeatingAction: action ] valueWithTimeout: 300
-!
+whileKeyDown: aKey do: aBlock
+	self keyBindings at: aKey put: aBlock
+! !
 
-handleKeyUp
-	isKeyCurrentlyPressed := false.
-	interval ifNotNil: [ interval clearInterval ].
-	delay ifNotNil: [ delay clearTimeout ]
+!HLRepeatedKeyDownHandler methodsFor: 'binding'!
+
+bindKeys
+	self widget 
+		bindKeyDown: [ :e | self handleKeyDown: e ] 
+		keyUp: [ :e | self handleKeyUp ]
 !
 
 rebindKeys
-	self unbindKeys;
+	self 
+		unbindKeys;
 		bindKeys
 !
 
-startRepeatingAction: action
-	^ [ (widget hasFocus)
-		ifTrue: [ action value ]
-		ifFalse: [ self handleKeyUp ] ] valueWithInterval: repeatInterval
-!
-
 unbindKeys
-	widget unbindKeyDownUp
+	self widget unbindKeyDownKeyUp
+! !
+
+!HLRepeatedKeyDownHandler methodsFor: 'defaults'!
+
+defaultRepeatInterval
+	^ 70
 ! !
 
-!HLRepeatingKeyBindingHandler methodsFor: 'events-processing'!
+!HLRepeatedKeyDownHandler methodsFor: 'events handling'!
 
-handleKeyDown: e
-	 keyBindings keysAndValuesDo: [ :key :action | 
-		self ifKey: key wasPressedIn: e thenDo: action ]
+handleEvent: anEvent forKey: anInteger action: aBlock
+	(anEvent which = anInteger and: [ self isKeyDown not ])
+		ifTrue: [ self whileKeyDownDo: aBlock ]
 !
 
-handleKeyUp: e
-	isKeyCurrentlyPressed
-		ifTrue: [ self handleKeyUp ]
+handleKeyDown: anEvent
+	self keyBindings keysAndValuesDo: [ :key :action | 
+		self handleEvent: anEvent forKey: key action: action ]
 !
 
-ifKey: key wasPressedIn: e thenDo: action
-	(e which = key and: [ isKeyCurrentlyPressed = false ])
-		ifTrue: [  self whileTheKeyIsPressedDo: action ]
+handleKeyUp
+	self isKeyDown ifTrue: [
+		keyDown := false.
+		interval ifNotNil: [ interval clearInterval ].
+		delay ifNotNil: [ delay clearTimeout ] ]
 !
 
-whileTheKeyIsPressedDo: action
-	isKeyCurrentlyPressed := true.
-	action value.
-	delay := self delayBeforeStartingRepeatWithAction: action
+whileKeyDownDo: aBlock
+	keyDown := true.
+	aBlock value.
+	delay := [ interval := self startRepeatingAction: aBlock ] 
+		valueWithTimeout: 300
 ! !
 
-!HLRepeatingKeyBindingHandler methodsFor: 'initialization'!
+!HLRepeatedKeyDownHandler methodsFor: 'testing'!
 
-initialize 
-	super initialize.
-	keyBindings := Dictionary new.
-	isKeyCurrentlyPressed := false.
-	repeatInterval := 70.
+isKeyDown
+	^ keyDown ifNil: [ false ]
 ! !
 
-!HLRepeatingKeyBindingHandler class methodsFor: 'instance-creation'!
+!HLRepeatedKeyDownHandler class methodsFor: 'instance creation'!
 
-forWidget: aWidget
-	^self new
+on: aWidget
+	^ self new
 		widget: aWidget;
 		yourself
 ! !

+ 3 - 3
st/Helios-Workspace-Tests.st

@@ -6,8 +6,8 @@ TestCase subclass: #HLCodeWidgetTest
 !HLCodeWidgetTest methodsFor: 'tests'!
 
 testKeyMap
-"Key maps are a collection of associations."
-self assert: ( HLCodeWidget pcKeyMap isKindOf: HashedCollection ).
-self assert: ( HLCodeWidget macKeyMap isKindOf: HashedCollection ).
+	"Key maps are a collection of associations."
+	self assert: (HLCodeWidget pcKeyMap isKindOf: HashedCollection).
+	self assert: (HLCodeWidget macKeyMap isKindOf: HashedCollection)
 ! !
 

+ 4 - 0
st/Kernel-Collections.st

@@ -1476,6 +1476,10 @@ crlf
 	<return '\r\n'>
 !
 
+esc
+	^ self fromCharCode: 27
+!
+
 lf
 	<return '\n'>
 !

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott