浏览代码

Better tabs handling

Nicolas Petton 11 年之前
父节点
当前提交
5d705bcc2c

+ 178 - 0
js/Helios-Commands.deploy.js

@@ -433,3 +433,181 @@ messageSends: []}),
 smalltalk.HLToggleInstanceSideCommand.klass);
 
 
+smalltalk.addClass('HLCloseTabCommand', smalltalk.HLCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(_st((smalltalk.HLManager || HLManager))._current())._removeActiveTab();
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLCloseTabCommand)})},
+messageSends: ["removeActiveTab", "current"]}),
+smalltalk.HLCloseTabCommand);
+
+
+smalltalk.addMethod(
+"_bindingGroup",
+smalltalk.method({
+selector: "bindingGroup",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Close";
+}, function($ctx1) {$ctx1.fill(self,"bindingGroup",{}, smalltalk.HLCloseTabCommand.klass)})},
+messageSends: []}),
+smalltalk.HLCloseTabCommand.klass);
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (67);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLCloseTabCommand.klass)})},
+messageSends: []}),
+smalltalk.HLCloseTabCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Close tab";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLCloseTabCommand.klass)})},
+messageSends: []}),
+smalltalk.HLCloseTabCommand.klass);
+
+
+smalltalk.addClass('HLOpenCommand', smalltalk.HLCommand, [], 'Helios-Commands');
+
+smalltalk.addMethod(
+"_bindingGroup",
+smalltalk.method({
+selector: "bindingGroup",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Open";
+}, function($ctx1) {$ctx1.fill(self,"bindingGroup",{}, smalltalk.HLOpenCommand.klass)})},
+messageSends: []}),
+smalltalk.HLOpenCommand.klass);
+
+
+smalltalk.addClass('HLOpenBrowserCommand', smalltalk.HLOpenCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLBrowser || HLBrowser))._openAsTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLOpenBrowserCommand)})},
+messageSends: ["openAsTab"]}),
+smalltalk.HLOpenBrowserCommand);
+
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (66);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLOpenBrowserCommand.klass)})},
+messageSends: []}),
+smalltalk.HLOpenBrowserCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Browser";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLOpenBrowserCommand.klass)})},
+messageSends: []}),
+smalltalk.HLOpenBrowserCommand.klass);
+
+
+smalltalk.addClass('HLOpenTranscriptCommand', smalltalk.HLOpenCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLTranscript || HLTranscript))._openAsTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLOpenTranscriptCommand)})},
+messageSends: ["openAsTab"]}),
+smalltalk.HLOpenTranscriptCommand);
+
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (84);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLOpenTranscriptCommand.klass)})},
+messageSends: []}),
+smalltalk.HLOpenTranscriptCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Transcript";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLOpenTranscriptCommand.klass)})},
+messageSends: []}),
+smalltalk.HLOpenTranscriptCommand.klass);
+
+
+smalltalk.addClass('HLOpenWorkspaceCommand', smalltalk.HLOpenCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLWorkspace || HLWorkspace))._openAsTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLOpenWorkspaceCommand)})},
+messageSends: ["openAsTab"]}),
+smalltalk.HLOpenWorkspaceCommand);
+
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (87);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLOpenWorkspaceCommand.klass)})},
+messageSends: []}),
+smalltalk.HLOpenWorkspaceCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Workspace";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLOpenWorkspaceCommand.klass)})},
+messageSends: []}),
+smalltalk.HLOpenWorkspaceCommand.klass);
+
+
+smalltalk.addClass('HLViewCommand', smalltalk.HLCommand, [], 'Helios-Commands');
+
+

+ 248 - 0
js/Helios-Commands.js

@@ -608,3 +608,251 @@ referencedClasses: []
 smalltalk.HLToggleInstanceSideCommand.klass);
 
 
+smalltalk.addClass('HLCloseTabCommand', smalltalk.HLCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(_st((smalltalk.HLManager || HLManager))._current())._removeActiveTab();
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLCloseTabCommand)})},
+args: [],
+source: "execute\x0a\x09HLManager current removeActiveTab",
+messageSends: ["removeActiveTab", "current"],
+referencedClasses: ["HLManager"]
+}),
+smalltalk.HLCloseTabCommand);
+
+
+smalltalk.addMethod(
+"_bindingGroup",
+smalltalk.method({
+selector: "bindingGroup",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Close";
+}, function($ctx1) {$ctx1.fill(self,"bindingGroup",{}, smalltalk.HLCloseTabCommand.klass)})},
+args: [],
+source: "bindingGroup\x0a\x09^ 'Close'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCloseTabCommand.klass);
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (67);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLCloseTabCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 67",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCloseTabCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Close tab";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLCloseTabCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Close tab'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCloseTabCommand.klass);
+
+
+smalltalk.addClass('HLOpenCommand', smalltalk.HLCommand, [], 'Helios-Commands');
+
+smalltalk.addMethod(
+"_bindingGroup",
+smalltalk.method({
+selector: "bindingGroup",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Open";
+}, function($ctx1) {$ctx1.fill(self,"bindingGroup",{}, smalltalk.HLOpenCommand.klass)})},
+args: [],
+source: "bindingGroup\x0a\x09^ 'Open'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLOpenCommand.klass);
+
+
+smalltalk.addClass('HLOpenBrowserCommand', smalltalk.HLOpenCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLBrowser || HLBrowser))._openAsTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLOpenBrowserCommand)})},
+args: [],
+source: "execute\x0a\x09^ HLBrowser openAsTab",
+messageSends: ["openAsTab"],
+referencedClasses: ["HLBrowser"]
+}),
+smalltalk.HLOpenBrowserCommand);
+
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (66);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLOpenBrowserCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 66",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLOpenBrowserCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Browser";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLOpenBrowserCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Browser'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLOpenBrowserCommand.klass);
+
+
+smalltalk.addClass('HLOpenTranscriptCommand', smalltalk.HLOpenCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLTranscript || HLTranscript))._openAsTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLOpenTranscriptCommand)})},
+args: [],
+source: "execute\x0a\x09^ HLTranscript openAsTab",
+messageSends: ["openAsTab"],
+referencedClasses: ["HLTranscript"]
+}),
+smalltalk.HLOpenTranscriptCommand);
+
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (84);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLOpenTranscriptCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 84",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLOpenTranscriptCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Transcript";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLOpenTranscriptCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Transcript'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLOpenTranscriptCommand.klass);
+
+
+smalltalk.addClass('HLOpenWorkspaceCommand', smalltalk.HLOpenCommand, [], 'Helios-Commands');
+smalltalk.addMethod(
+"_execute",
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st((smalltalk.HLWorkspace || HLWorkspace))._openAsTab();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"execute",{}, smalltalk.HLOpenWorkspaceCommand)})},
+args: [],
+source: "execute\x0a\x09^ HLWorkspace openAsTab",
+messageSends: ["openAsTab"],
+referencedClasses: ["HLWorkspace"]
+}),
+smalltalk.HLOpenWorkspaceCommand);
+
+
+smalltalk.addMethod(
+"_key",
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return (87);
+}, function($ctx1) {$ctx1.fill(self,"key",{}, smalltalk.HLOpenWorkspaceCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 87",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLOpenWorkspaceCommand.klass);
+
+smalltalk.addMethod(
+"_label",
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "Workspace";
+}, function($ctx1) {$ctx1.fill(self,"label",{}, smalltalk.HLOpenWorkspaceCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Workspace'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLOpenWorkspaceCommand.klass);
+
+
+smalltalk.addClass('HLViewCommand', smalltalk.HLCommand, [], 'Helios-Commands');
+
+

+ 82 - 5
js/Helios-Core.deploy.js

@@ -233,9 +233,15 @@ smalltalk.method({
 selector: "openAsTab",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st((smalltalk.HLManager || HLManager))._current())._addTab_(_st((smalltalk.HLTab || HLTab))._on_labelled_(_st(self)._new(),_st(self)._tabLabel()));
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=_st(self)._canBeOpenAsTab();
+if(! smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+_st(_st((smalltalk.HLManager || HLManager))._current())._addTab_(_st((smalltalk.HLTab || HLTab))._on_labelled_(_st(self)._new(),_st(self)._tabLabel()));
 return self}, function($ctx1) {$ctx1.fill(self,"openAsTab",{}, smalltalk.HLWidget.klass)})},
-messageSends: ["addTab:", "on:labelled:", "new", "tabLabel", "current"]}),
+messageSends: ["ifFalse:", "canBeOpenAsTab", "addTab:", "on:labelled:", "new", "tabLabel", "current"]}),
 smalltalk.HLWidget.klass);
 
 smalltalk.addMethod(
@@ -787,7 +793,7 @@ smalltalk.HLNavigationListWidget);
 
 
 
-smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'keyBinder', 'environment'], 'Helios-Core');
+smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'keyBinder', 'environment', 'history'], 'Helios-Core');
 smalltalk.addMethod(
 "_activate_",
 smalltalk.method({
@@ -799,9 +805,10 @@ _st(_st(self)._keyBinder())._flushBindings();
 self["@activeTab"]=aTab;
 $1=self;
 _st($1)._refresh();
+_st($1)._addToHistory_(aTab);
 $2=_st($1)._show_(aTab);
 return self}, function($ctx1) {$ctx1.fill(self,"activate:",{aTab:aTab}, smalltalk.HLManager)})},
-messageSends: ["flushBindings", "keyBinder", "refresh", "show:"]}),
+messageSends: ["flushBindings", "keyBinder", "refresh", "addToHistory:", "show:"]}),
 smalltalk.HLManager);
 
 smalltalk.addMethod(
@@ -829,6 +836,18 @@ return self}, function($ctx1) {$ctx1.fill(self,"addTab:",{aTab:aTab}, smalltalk.
 messageSends: ["add:", "tabs", "activate:"]}),
 smalltalk.HLManager);
 
+smalltalk.addMethod(
+"_addToHistory_",
+smalltalk.method({
+selector: "addToHistory:",
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._removeFromHistory_(aTab);
+_st(_st(self)._history())._add_(aTab);
+return self}, function($ctx1) {$ctx1.fill(self,"addToHistory:",{aTab:aTab}, smalltalk.HLManager)})},
+messageSends: ["removeFromHistory:", "add:", "history"]}),
+smalltalk.HLManager);
+
 smalltalk.addMethod(
 "_defaultEnvironment",
 smalltalk.method({
@@ -872,6 +891,36 @@ return self}, function($ctx1) {$ctx1.fill(self,"environment:",{anEnvironment:anE
 messageSends: []}),
 smalltalk.HLManager);
 
+smalltalk.addMethod(
+"_history",
+smalltalk.method({
+selector: "history",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@history"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@history"]=_st((smalltalk.OrderedCollection || OrderedCollection))._new();
+$1=self["@history"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"history",{}, smalltalk.HLManager)})},
+messageSends: ["ifNil:", "new"]}),
+smalltalk.HLManager);
+
+smalltalk.addMethod(
+"_history_",
+smalltalk.method({
+selector: "history:",
+fn: function (aCollection){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@history"]=aCollection;
+return self}, function($ctx1) {$ctx1.fill(self,"history:",{aCollection:aCollection}, smalltalk.HLManager)})},
+messageSends: []}),
+smalltalk.HLManager);
+
 smalltalk.addMethod(
 "_initialize",
 smalltalk.method({
@@ -916,6 +965,30 @@ return self}, function($ctx1) {$ctx1.fill(self,"refresh",{}, smalltalk.HLManager
 messageSends: ["remove", "jQuery:", "appendToJQuery:", "asJQuery"]}),
 smalltalk.HLManager);
 
+smalltalk.addMethod(
+"_removeActiveTab",
+smalltalk.method({
+selector: "removeActiveTab",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._removeTab_(_st(self)._activeTab());
+return self}, function($ctx1) {$ctx1.fill(self,"removeActiveTab",{}, smalltalk.HLManager)})},
+messageSends: ["removeTab:", "activeTab"]}),
+smalltalk.HLManager);
+
+smalltalk.addMethod(
+"_removeFromHistory_",
+smalltalk.method({
+selector: "removeFromHistory:",
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._history_(_st(_st(self)._history())._reject_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(each).__eq_eq(aTab);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})})));
+return self}, function($ctx1) {$ctx1.fill(self,"removeFromHistory:",{aTab:aTab}, smalltalk.HLManager)})},
+messageSends: ["history:", "reject:", "==", "history"]}),
+smalltalk.HLManager);
+
 smalltalk.addMethod(
 "_removeTab_",
 smalltalk.method({
@@ -928,10 +1001,14 @@ if(! smalltalk.assert($1)){
 $2=self;
 return $2;
 };
+_st(self)._removeFromHistory_(aTab);
 _st(_st(self)._tabs())._remove_(aTab);
 _st(self)._refresh();
+_st(_st(self)._history())._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(self)._history())._last())._activate();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"removeTab:",{aTab:aTab}, smalltalk.HLManager)})},
-messageSends: ["ifFalse:", "includes:", "tabs", "remove:", "refresh"]}),
+messageSends: ["ifFalse:", "includes:", "tabs", "removeFromHistory:", "remove:", "refresh", "ifNotEmpty:", "activate", "last", "history"]}),
 smalltalk.HLManager);
 
 smalltalk.addMethod(

+ 110 - 8
js/Helios-Core.js

@@ -319,11 +319,17 @@ selector: "openAsTab",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st((smalltalk.HLManager || HLManager))._current())._addTab_(_st((smalltalk.HLTab || HLTab))._on_labelled_(_st(self)._new(),_st(self)._tabLabel()));
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=_st(self)._canBeOpenAsTab();
+if(! smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+_st(_st((smalltalk.HLManager || HLManager))._current())._addTab_(_st((smalltalk.HLTab || HLTab))._on_labelled_(_st(self)._new(),_st(self)._tabLabel()));
 return self}, function($ctx1) {$ctx1.fill(self,"openAsTab",{}, smalltalk.HLWidget.klass)})},
 args: [],
-source: "openAsTab\x0a\x09HLManager current addTab: (HLTab on: self new labelled: self tabLabel)",
-messageSends: ["addTab:", "on:labelled:", "new", "tabLabel", "current"],
+source: "openAsTab\x0a\x09self canBeOpenAsTab ifFalse: [ ^ self ].\x0a\x09HLManager current addTab: (HLTab on: self new labelled: self tabLabel)",
+messageSends: ["ifFalse:", "canBeOpenAsTab", "addTab:", "on:labelled:", "new", "tabLabel", "current"],
 referencedClasses: ["HLTab", "HLManager"]
 }),
 smalltalk.HLWidget.klass);
@@ -1047,7 +1053,7 @@ smalltalk.HLNavigationListWidget);
 
 
 
-smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'keyBinder', 'environment'], 'Helios-Core');
+smalltalk.addClass('HLManager', smalltalk.HLWidget, ['tabs', 'activeTab', 'keyBinder', 'environment', 'history'], 'Helios-Core');
 smalltalk.addMethod(
 "_activate_",
 smalltalk.method({
@@ -1060,11 +1066,12 @@ _st(_st(self)._keyBinder())._flushBindings();
 self["@activeTab"]=aTab;
 $1=self;
 _st($1)._refresh();
+_st($1)._addToHistory_(aTab);
 $2=_st($1)._show_(aTab);
 return self}, function($ctx1) {$ctx1.fill(self,"activate:",{aTab:aTab}, smalltalk.HLManager)})},
 args: ["aTab"],
-source: "activate: aTab\x0a\x09self keyBinder flushBindings.\x0a\x09activeTab := aTab.\x0a    \x0a\x09self \x0a\x09\x09refresh;\x0a\x09\x09show: aTab",
-messageSends: ["flushBindings", "keyBinder", "refresh", "show:"],
+source: "activate: aTab\x0a\x09self keyBinder flushBindings.\x0a\x09activeTab := aTab.\x0a\x09\x0a\x09self \x0a\x09\x09refresh;\x0a\x09\x09addToHistory: aTab;\x0a\x09\x09show: aTab",
+messageSends: ["flushBindings", "keyBinder", "refresh", "addToHistory:", "show:"],
 referencedClasses: []
 }),
 smalltalk.HLManager);
@@ -1104,6 +1111,23 @@ referencedClasses: []
 }),
 smalltalk.HLManager);
 
+smalltalk.addMethod(
+"_addToHistory_",
+smalltalk.method({
+selector: "addToHistory:",
+category: 'actions',
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._removeFromHistory_(aTab);
+_st(_st(self)._history())._add_(aTab);
+return self}, function($ctx1) {$ctx1.fill(self,"addToHistory:",{aTab:aTab}, smalltalk.HLManager)})},
+args: ["aTab"],
+source: "addToHistory: aTab\x0a\x09self removeFromHistory: aTab.\x0a\x09self history add: aTab",
+messageSends: ["removeFromHistory:", "add:", "history"],
+referencedClasses: []
+}),
+smalltalk.HLManager);
+
 smalltalk.addMethod(
 "_defaultEnvironment",
 smalltalk.method({
@@ -1162,6 +1186,46 @@ referencedClasses: []
 }),
 smalltalk.HLManager);
 
+smalltalk.addMethod(
+"_history",
+smalltalk.method({
+selector: "history",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@history"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@history"]=_st((smalltalk.OrderedCollection || OrderedCollection))._new();
+$1=self["@history"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"history",{}, smalltalk.HLManager)})},
+args: [],
+source: "history\x0a\x09^ history ifNil: [ history := OrderedCollection new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["OrderedCollection"]
+}),
+smalltalk.HLManager);
+
+smalltalk.addMethod(
+"_history_",
+smalltalk.method({
+selector: "history:",
+category: 'accessing',
+fn: function (aCollection){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@history"]=aCollection;
+return self}, function($ctx1) {$ctx1.fill(self,"history:",{aCollection:aCollection}, smalltalk.HLManager)})},
+args: ["aCollection"],
+source: "history: aCollection\x0a\x09history := aCollection",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLManager);
+
 smalltalk.addMethod(
 "_initialize",
 smalltalk.method({
@@ -1221,6 +1285,40 @@ referencedClasses: []
 }),
 smalltalk.HLManager);
 
+smalltalk.addMethod(
+"_removeActiveTab",
+smalltalk.method({
+selector: "removeActiveTab",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._removeTab_(_st(self)._activeTab());
+return self}, function($ctx1) {$ctx1.fill(self,"removeActiveTab",{}, smalltalk.HLManager)})},
+args: [],
+source: "removeActiveTab\x0a\x09self removeTab: self activeTab",
+messageSends: ["removeTab:", "activeTab"],
+referencedClasses: []
+}),
+smalltalk.HLManager);
+
+smalltalk.addMethod(
+"_removeFromHistory_",
+smalltalk.method({
+selector: "removeFromHistory:",
+category: 'actions',
+fn: function (aTab){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._history_(_st(_st(self)._history())._reject_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(each).__eq_eq(aTab);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})})));
+return self}, function($ctx1) {$ctx1.fill(self,"removeFromHistory:",{aTab:aTab}, smalltalk.HLManager)})},
+args: ["aTab"],
+source: "removeFromHistory: aTab\x0a\x09self history: (self history reject: [ :each | each == aTab ])",
+messageSends: ["history:", "reject:", "==", "history"],
+referencedClasses: []
+}),
+smalltalk.HLManager);
+
 smalltalk.addMethod(
 "_removeTab_",
 smalltalk.method({
@@ -1234,12 +1332,16 @@ if(! smalltalk.assert($1)){
 $2=self;
 return $2;
 };
+_st(self)._removeFromHistory_(aTab);
 _st(_st(self)._tabs())._remove_(aTab);
 _st(self)._refresh();
+_st(_st(self)._history())._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(self)._history())._last())._activate();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"removeTab:",{aTab:aTab}, smalltalk.HLManager)})},
 args: ["aTab"],
-source: "removeTab: aTab\x0a\x09\x22Todo: activate the previously activated tab. Keep a history of tabs selection\x22\x0a\x0a\x09(self tabs includes: aTab) ifFalse: [ ^ self ].\x0a\x0a\x09self tabs remove: aTab.\x0a\x09self refresh",
-messageSends: ["ifFalse:", "includes:", "tabs", "remove:", "refresh"],
+source: "removeTab: aTab\x0a\x09(self tabs includes: aTab) ifFalse: [ ^ self ].\x0a\x0a\x09self removeFromHistory: aTab.\x0a\x09self tabs remove: aTab.\x0a\x09self refresh.\x0a\x09self history ifNotEmpty: [\x0a\x09\x09self history last activate ]",
+messageSends: ["ifFalse:", "includes:", "tabs", "removeFromHistory:", "remove:", "refresh", "ifNotEmpty:", "activate", "last", "history"],
 referencedClasses: []
 }),
 smalltalk.HLManager);

+ 25 - 2
js/Helios-KeyBindings.deploy.js

@@ -394,14 +394,14 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $2,$1;
 $2=self["@bindings"];
 if(($receiver = $2) == nil || $receiver == undefined){
-self["@bindings"]=_st((smalltalk.HLBindingGroup || HLBindingGroup))._new();
+self["@bindings"]=_st(self)._defaulBindings();
 $1=self["@bindings"];
 } else {
 $1=$2;
 };
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"bindings",{}, smalltalk.HLKeyBinder)})},
-messageSends: ["ifNil:", "new"]}),
+messageSends: ["ifNil:", "defaulBindings"]}),
 smalltalk.HLKeyBinder);
 
 smalltalk.addMethod(
@@ -417,6 +417,29 @@ return self}, function($ctx1) {$ctx1.fill(self,"deactivate",{}, smalltalk.HLKeyB
 messageSends: ["hide", "helper"]}),
 smalltalk.HLKeyBinder);
 
+smalltalk.addMethod(
+"_defaulBindings",
+smalltalk.method({
+selector: "defaulBindings",
+fn: function (){
+var self=this;
+var group;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+$1=_st((smalltalk.HLBindingGroup || HLBindingGroup))._new();
+_st($1)._addGroupKey_labelled_((79),"Open");
+_st($1)._addGroupKey_labelled_((86),"View");
+_st($1)._add_(_st(_st((smalltalk.HLCloseTabCommand || HLCloseTabCommand))._new())._asBinding());
+$2=_st($1)._yourself();
+group=$2;
+_st(_st((smalltalk.HLOpenCommand || HLOpenCommand))._allSubclasses())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(group)._at_(_st(each)._bindingGroup()))._add_(_st(_st(each)._new())._asBinding());
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+$3=group;
+return $3;
+}, function($ctx1) {$ctx1.fill(self,"defaulBindings",{group:group}, smalltalk.HLKeyBinder)})},
+messageSends: ["addGroupKey:labelled:", "new", "add:", "asBinding", "yourself", "do:", "at:", "bindingGroup", "allSubclasses"]}),
+smalltalk.HLKeyBinder);
+
 smalltalk.addMethod(
 "_escapeKey",
 smalltalk.method({

+ 32 - 4
js/Helios-KeyBindings.js

@@ -545,7 +545,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $2,$1;
 $2=self["@bindings"];
 if(($receiver = $2) == nil || $receiver == undefined){
-self["@bindings"]=_st((smalltalk.HLBindingGroup || HLBindingGroup))._new();
+self["@bindings"]=_st(self)._defaulBindings();
 $1=self["@bindings"];
 } else {
 $1=$2;
@@ -553,9 +553,9 @@ $1=$2;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"bindings",{}, smalltalk.HLKeyBinder)})},
 args: [],
-source: "bindings\x0a\x09^ bindings ifNil: [ bindings := HLBindingGroup new ]",
-messageSends: ["ifNil:", "new"],
-referencedClasses: ["HLBindingGroup"]
+source: "bindings\x0a\x09^ bindings ifNil: [ bindings := self defaulBindings ]",
+messageSends: ["ifNil:", "defaulBindings"],
+referencedClasses: []
 }),
 smalltalk.HLKeyBinder);
 
@@ -577,6 +577,34 @@ referencedClasses: []
 }),
 smalltalk.HLKeyBinder);
 
+smalltalk.addMethod(
+"_defaulBindings",
+smalltalk.method({
+selector: "defaulBindings",
+category: 'accessing',
+fn: function (){
+var self=this;
+var group;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+$1=_st((smalltalk.HLBindingGroup || HLBindingGroup))._new();
+_st($1)._addGroupKey_labelled_((79),"Open");
+_st($1)._addGroupKey_labelled_((86),"View");
+_st($1)._add_(_st(_st((smalltalk.HLCloseTabCommand || HLCloseTabCommand))._new())._asBinding());
+$2=_st($1)._yourself();
+group=$2;
+_st(_st((smalltalk.HLOpenCommand || HLOpenCommand))._allSubclasses())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(group)._at_(_st(each)._bindingGroup()))._add_(_st(_st(each)._new())._asBinding());
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+$3=group;
+return $3;
+}, function($ctx1) {$ctx1.fill(self,"defaulBindings",{group:group}, smalltalk.HLKeyBinder)})},
+args: [],
+source: "defaulBindings\x0a\x09| group |\x0a\x09\x0a\x09group := HLBindingGroup new\x0a\x09\x09addGroupKey: 79 labelled: 'Open';\x0a\x09\x09addGroupKey: 86 labelled: 'View';\x0a\x09\x09add: HLCloseTabCommand new asBinding;\x0a\x09\x09yourself.\x0a\x09\x09\x0a\x09HLOpenCommand allSubclasses do: [ :each | \x0a\x09\x09(group at: each bindingGroup) \x0a  \x09\x09\x09add: each new asBinding ].\x0a\x09\x09\x09\x09\x0a\x09^ group",
+messageSends: ["addGroupKey:labelled:", "new", "add:", "asBinding", "yourself", "do:", "at:", "bindingGroup", "allSubclasses"],
+referencedClasses: ["HLBindingGroup", "HLCloseTabCommand", "HLOpenCommand"]
+}),
+smalltalk.HLKeyBinder);
+
 smalltalk.addMethod(
 "_escapeKey",
 smalltalk.method({

+ 98 - 0
st/Helios-Commands.st

@@ -243,3 +243,101 @@ label
 	^ 'Instance side'
 ! !
 
+HLCommand subclass: #HLCloseTabCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands'!
+
+!HLCloseTabCommand methodsFor: 'executing'!
+
+execute
+	HLManager current removeActiveTab
+! !
+
+!HLCloseTabCommand class methodsFor: 'accessing'!
+
+bindingGroup
+	^ 'Close'
+!
+
+key
+	^ 67
+!
+
+label
+	^ 'Close tab'
+! !
+
+HLCommand subclass: #HLOpenCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands'!
+
+!HLOpenCommand class methodsFor: 'accessing'!
+
+bindingGroup
+	^ 'Open'
+! !
+
+HLOpenCommand subclass: #HLOpenBrowserCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands'!
+
+!HLOpenBrowserCommand methodsFor: 'executing'!
+
+execute
+	^ HLBrowser openAsTab
+! !
+
+!HLOpenBrowserCommand class methodsFor: 'accessing'!
+
+key
+	^ 66
+!
+
+label
+	^ 'Browser'
+! !
+
+HLOpenCommand subclass: #HLOpenTranscriptCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands'!
+
+!HLOpenTranscriptCommand methodsFor: 'executing'!
+
+execute
+	^ HLTranscript openAsTab
+! !
+
+!HLOpenTranscriptCommand class methodsFor: 'accessing'!
+
+key
+	^ 84
+!
+
+label
+	^ 'Transcript'
+! !
+
+HLOpenCommand subclass: #HLOpenWorkspaceCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands'!
+
+!HLOpenWorkspaceCommand methodsFor: 'executing'!
+
+execute
+	^ HLWorkspace openAsTab
+! !
+
+!HLOpenWorkspaceCommand class methodsFor: 'accessing'!
+
+key
+	^ 87
+!
+
+label
+	^ 'Workspace'
+! !
+
+HLCommand subclass: #HLViewCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands'!
+

+ 29 - 5
st/Helios-Core.st

@@ -95,6 +95,7 @@ refresh
 !HLWidget class methodsFor: 'accessing'!
 
 openAsTab
+	self canBeOpenAsTab ifFalse: [ ^ self ].
 	HLManager current addTab: (HLTab on: self new labelled: self tabLabel)
 !
 
@@ -347,7 +348,7 @@ setupKeyBindings
 ! !
 
 HLWidget subclass: #HLManager
-	instanceVariableNames: 'tabs activeTab keyBinder environment'
+	instanceVariableNames: 'tabs activeTab keyBinder environment history'
 	package: 'Helios-Core'!
 
 !HLManager methodsFor: 'accessing'!
@@ -366,6 +367,14 @@ environment: anEnvironment
 	environment := anEnvironment
 !
 
+history
+	^ history ifNil: [ history := OrderedCollection new ]
+!
+
+history: aCollection
+	history := aCollection
+!
+
 keyBinder
 	^ keyBinder ifNil: [ keyBinder := HLKeyBinder new ]
 !
@@ -379,9 +388,10 @@ tabs
 activate: aTab
 	self keyBinder flushBindings.
 	activeTab := aTab.
-    
+	
 	self 
 		refresh;
+		addToHistory: aTab;
 		show: aTab
 !
 
@@ -390,13 +400,27 @@ addTab: aTab
     self activate: aTab
 !
 
-removeTab: aTab
-	"Todo: activate the previously activated tab. Keep a history of tabs selection"
+addToHistory: aTab
+	self removeFromHistory: aTab.
+	self history add: aTab
+!
+
+removeActiveTab
+	self removeTab: self activeTab
+!
 
+removeFromHistory: aTab
+	self history: (self history reject: [ :each | each == aTab ])
+!
+
+removeTab: aTab
 	(self tabs includes: aTab) ifFalse: [ ^ self ].
 
+	self removeFromHistory: aTab.
 	self tabs remove: aTab.
-	self refresh
+	self refresh.
+	self history ifNotEmpty: [
+		self history last activate ]
 ! !
 
 !HLManager methodsFor: 'defaults'!

+ 17 - 1
st/Helios-KeyBindings.st

@@ -157,7 +157,23 @@ activationKeyLabel
 !
 
 bindings
-	^ bindings ifNil: [ bindings := HLBindingGroup new ]
+	^ bindings ifNil: [ bindings := self defaulBindings ]
+!
+
+defaulBindings
+	| group |
+	
+	group := HLBindingGroup new
+		addGroupKey: 79 labelled: 'Open';
+		addGroupKey: 86 labelled: 'View';
+		add: HLCloseTabCommand new asBinding;
+		yourself.
+		
+	HLOpenCommand allSubclasses do: [ :each | 
+		(group at: each bindingGroup) 
+  			add: each new asBinding ].
+				
+	^ group
 !
 
 escapeKey