Browse Source

Helios: Confirm box related improvements

Nicolas Petton 11 years ago
parent
commit
d20b7d746c

+ 25 - 1
js/Helios-Announcements.deploy.js

@@ -1,5 +1,29 @@
 smalltalk.addPackage('Helios-Announcements');
-smalltalk.addClass('HLAboutToChange', smalltalk.Object, [], 'Helios-Announcements');
+smalltalk.addClass('HLAboutToChange', smalltalk.Object, ['actionBlock'], 'Helios-Announcements');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "actionBlock",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@actionBlock"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"actionBlock",{},smalltalk.HLAboutToChange)})},
+messageSends: []}),
+smalltalk.HLAboutToChange);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "actionBlock:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@actionBlock"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"actionBlock:",{aBlock:aBlock},smalltalk.HLAboutToChange)})},
+messageSends: []}),
+smalltalk.HLAboutToChange);
+
 
 
 smalltalk.addClass('HLAnnouncement', smalltalk.Object, [], 'Helios-Announcements');

+ 35 - 1
js/Helios-Announcements.js

@@ -1,5 +1,39 @@
 smalltalk.addPackage('Helios-Announcements');
-smalltalk.addClass('HLAboutToChange', smalltalk.Object, [], 'Helios-Announcements');
+smalltalk.addClass('HLAboutToChange', smalltalk.Object, ['actionBlock'], 'Helios-Announcements');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "actionBlock",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@actionBlock"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"actionBlock",{},smalltalk.HLAboutToChange)})},
+args: [],
+source: "actionBlock\x0a\x09^ actionBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLAboutToChange);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "actionBlock:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@actionBlock"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"actionBlock:",{aBlock:aBlock},smalltalk.HLAboutToChange)})},
+args: ["aBlock"],
+source: "actionBlock: aBlock\x0a\x09actionBlock := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLAboutToChange);
+
 
 
 smalltalk.addClass('HLAnnouncement', smalltalk.Object, [], 'Helios-Announcements');

+ 2 - 2
js/Helios-Browser.deploy.js

@@ -3080,13 +3080,13 @@ function $HLAboutToChange(){return smalltalk.HLAboutToChange||(typeof HLAboutToC
 return smalltalk.withContext(function($ctx1) { 
 _st((function(){
 return smalltalk.withContext(function($ctx2) {
-_st(_st(self)._announcer())._announce_(_st($HLAboutToChange())._new());
+_st(_st(self)._announcer())._announce_(_st(_st($HLAboutToChange())._new())._actionBlock_(aBlock));
 return _st(aBlock)._value();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._on_do_($HLChangeForbidden(),(function(ex){
 return smalltalk.withContext(function($ctx2) {
 }, function($ctx2) {$ctx2.fillBlock({ex:ex},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"withChangesDo:",{aBlock:aBlock},smalltalk.HLBrowserModel)})},
-messageSends: ["on:do:", "announce:", "new", "announcer", "value"]}),
+messageSends: ["on:do:", "announce:", "actionBlock:", "new", "announcer", "value"]}),
 smalltalk.HLBrowserModel);
 
 smalltalk.addMethod(

+ 3 - 3
js/Helios-Browser.js

@@ -3961,15 +3961,15 @@ function $HLAboutToChange(){return smalltalk.HLAboutToChange||(typeof HLAboutToC
 return smalltalk.withContext(function($ctx1) { 
 _st((function(){
 return smalltalk.withContext(function($ctx2) {
-_st(_st(self)._announcer())._announce_(_st($HLAboutToChange())._new());
+_st(_st(self)._announcer())._announce_(_st(_st($HLAboutToChange())._new())._actionBlock_(aBlock));
 return _st(aBlock)._value();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._on_do_($HLChangeForbidden(),(function(ex){
 return smalltalk.withContext(function($ctx2) {
 }, function($ctx2) {$ctx2.fillBlock({ex:ex},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"withChangesDo:",{aBlock:aBlock},smalltalk.HLBrowserModel)})},
 args: ["aBlock"],
-source: "withChangesDo: aBlock\x0a\x09[ \x0a\x09\x09self announcer announce: HLAboutToChange new.\x0a\x09\x09aBlock value\x0a\x09]\x0a\x09\x09on: HLChangeForbidden \x0a\x09\x09do: [ :ex | ]",
-messageSends: ["on:do:", "announce:", "new", "announcer", "value"],
+source: "withChangesDo: aBlock\x0a\x09[ \x0a\x09\x09self announcer announce: (HLAboutToChange new\x0a\x09\x09\x09actionBlock: aBlock).\x0a\x09\x09aBlock value.\x0a\x09]\x0a\x09\x09on: HLChangeForbidden \x0a\x09\x09do: [ :ex | ]",
+messageSends: ["on:do:", "announce:", "actionBlock:", "new", "announcer", "value"],
 referencedClasses: ["HLChangeForbidden", "HLAboutToChange"]
 }),
 smalltalk.HLBrowserModel);

+ 49 - 17
js/Helios-Core.deploy.js

@@ -902,12 +902,8 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 _st(self)._activateListItem_(_st(_st(window)._jQuery_(".focused .nav-pills .active"))._next());
-_st(_st(_st(window)._jQuery_(".focused .nav-pills .active"))._get())._ifEmpty_((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._activateFirstListItem();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"activateNextListItem",{},smalltalk.HLListWidget)})},
-messageSends: ["activateListItem:", "next", "jQuery:", "ifEmpty:", "activateFirstListItem", "get"]}),
+messageSends: ["activateListItem:", "next", "jQuery:"]}),
 smalltalk.HLListWidget);
 
 smalltalk.addMethod(
@@ -1228,7 +1224,7 @@ fn: function (){
 var self=this;
 var active,interval,delay,repeatInterval;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4,$5;
+var $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11;
 active=false;
 repeatInterval=(70);
 _st(_st(_st(self)._wrapper())._asJQuery())._unbind_("keydown");
@@ -1246,17 +1242,35 @@ delay=_st((function(){
 return smalltalk.withContext(function($ctx3) {
 interval=_st((function(){
 return smalltalk.withContext(function($ctx4) {
+$2=_st(_st(_st(self)._wrapper())._asJQuery())._hasClass_(_st(self)._focusClass());
+if(smalltalk.assert($2)){
 return _st(self)._activatePreviousListItem();
+} else {
+active=false;
+active;
+$3=interval;
+if(($receiver = $3) == nil || $receiver == undefined){
+$3;
+} else {
+_st(interval)._clearInterval();
+};
+$4=delay;
+if(($receiver = $4) == nil || $receiver == undefined){
+return $4;
+} else {
+return _st(delay)._clearTimeout();
+};
+};
 }, function($ctx4) {$ctx4.fillBlock({},$ctx1)})}))._valueWithInterval_(repeatInterval);
 return interval;
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}))._valueWithTimeout_((300));
 delay;
 };
-$2=_st(_st(_st(e)._which()).__eq((40)))._and_((function(){
+$5=_st(_st(_st(e)._which()).__eq((40)))._and_((function(){
 return smalltalk.withContext(function($ctx3) {
 return _st(active).__eq(false);
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($2)){
+if(smalltalk.assert($5)){
 active=true;
 active;
 _st(self)._activateNextListItem();
@@ -1264,7 +1278,25 @@ delay=_st((function(){
 return smalltalk.withContext(function($ctx3) {
 interval=_st((function(){
 return smalltalk.withContext(function($ctx4) {
+$6=_st(_st(_st(self)._wrapper())._asJQuery())._hasClass_(_st(self)._focusClass());
+if(smalltalk.assert($6)){
 return _st(self)._activateNextListItem();
+} else {
+active=false;
+active;
+$7=interval;
+if(($receiver = $7) == nil || $receiver == undefined){
+$7;
+} else {
+_st(interval)._clearInterval();
+};
+$8=delay;
+if(($receiver = $8) == nil || $receiver == undefined){
+return $8;
+} else {
+return _st(delay)._clearTimeout();
+};
+};
 }, function($ctx4) {$ctx4.fillBlock({},$ctx1)})}))._valueWithInterval_(repeatInterval);
 return interval;
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}))._valueWithTimeout_((300));
@@ -1273,26 +1305,26 @@ return delay;
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 _st(_st(_st(self)._wrapper())._asJQuery())._keyup_((function(e){
 return smalltalk.withContext(function($ctx2) {
-$3=active;
-if(smalltalk.assert($3)){
+$9=active;
+if(smalltalk.assert($9)){
 active=false;
 active;
-$4=interval;
-if(($receiver = $4) == nil || $receiver == undefined){
-$4;
+$10=interval;
+if(($receiver = $10) == nil || $receiver == undefined){
+$10;
 } else {
 _st(interval)._clearInterval();
 };
-$5=delay;
-if(($receiver = $5) == nil || $receiver == undefined){
-return $5;
+$11=delay;
+if(($receiver = $11) == nil || $receiver == undefined){
+return $11;
 } else {
 return _st(delay)._clearTimeout();
 };
 };
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{active:active,interval:interval,delay:delay,repeatInterval:repeatInterval},smalltalk.HLListWidget)})},
-messageSends: ["unbind:", "asJQuery", "wrapper", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "and:", "=", "which", "activateNextListItem", "keyup:", "ifNotNil:", "clearInterval", "clearTimeout"]}),
+messageSends: ["unbind:", "asJQuery", "wrapper", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "ifTrue:ifFalse:", "ifNotNil:", "clearInterval", "clearTimeout", "hasClass:", "focusClass", "and:", "=", "which", "activateNextListItem", "keyup:"]}),
 smalltalk.HLListWidget);
 
 

+ 51 - 19
js/Helios-Core.js

@@ -1193,14 +1193,10 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 _st(self)._activateListItem_(_st(_st(window)._jQuery_(".focused .nav-pills .active"))._next());
-_st(_st(_st(window)._jQuery_(".focused .nav-pills .active"))._get())._ifEmpty_((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._activateFirstListItem();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"activateNextListItem",{},smalltalk.HLListWidget)})},
 args: [],
-source: "activateNextListItem\x0a\x09self activateListItem: (window jQuery: '.focused .nav-pills .active') next.\x0a\x09\x0a\x09\x22select the first item if none is selected\x22\x0a\x09(window jQuery: '.focused .nav-pills .active') get ifEmpty: [\x0a\x09\x09self activateFirstListItem ]",
-messageSends: ["activateListItem:", "next", "jQuery:", "ifEmpty:", "activateFirstListItem", "get"],
+source: "activateNextListItem\x0a\x09self activateListItem: (window jQuery: '.focused .nav-pills .active') next",
+messageSends: ["activateListItem:", "next", "jQuery:"],
 referencedClasses: []
 }),
 smalltalk.HLListWidget);
@@ -1624,7 +1620,7 @@ fn: function (){
 var self=this;
 var active,interval,delay,repeatInterval;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4,$5;
+var $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11;
 active=false;
 repeatInterval=(70);
 _st(_st(_st(self)._wrapper())._asJQuery())._unbind_("keydown");
@@ -1642,17 +1638,35 @@ delay=_st((function(){
 return smalltalk.withContext(function($ctx3) {
 interval=_st((function(){
 return smalltalk.withContext(function($ctx4) {
+$2=_st(_st(_st(self)._wrapper())._asJQuery())._hasClass_(_st(self)._focusClass());
+if(smalltalk.assert($2)){
 return _st(self)._activatePreviousListItem();
+} else {
+active=false;
+active;
+$3=interval;
+if(($receiver = $3) == nil || $receiver == undefined){
+$3;
+} else {
+_st(interval)._clearInterval();
+};
+$4=delay;
+if(($receiver = $4) == nil || $receiver == undefined){
+return $4;
+} else {
+return _st(delay)._clearTimeout();
+};
+};
 }, function($ctx4) {$ctx4.fillBlock({},$ctx1)})}))._valueWithInterval_(repeatInterval);
 return interval;
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}))._valueWithTimeout_((300));
 delay;
 };
-$2=_st(_st(_st(e)._which()).__eq((40)))._and_((function(){
+$5=_st(_st(_st(e)._which()).__eq((40)))._and_((function(){
 return smalltalk.withContext(function($ctx3) {
 return _st(active).__eq(false);
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($2)){
+if(smalltalk.assert($5)){
 active=true;
 active;
 _st(self)._activateNextListItem();
@@ -1660,7 +1674,25 @@ delay=_st((function(){
 return smalltalk.withContext(function($ctx3) {
 interval=_st((function(){
 return smalltalk.withContext(function($ctx4) {
+$6=_st(_st(_st(self)._wrapper())._asJQuery())._hasClass_(_st(self)._focusClass());
+if(smalltalk.assert($6)){
 return _st(self)._activateNextListItem();
+} else {
+active=false;
+active;
+$7=interval;
+if(($receiver = $7) == nil || $receiver == undefined){
+$7;
+} else {
+_st(interval)._clearInterval();
+};
+$8=delay;
+if(($receiver = $8) == nil || $receiver == undefined){
+return $8;
+} else {
+return _st(delay)._clearTimeout();
+};
+};
 }, function($ctx4) {$ctx4.fillBlock({},$ctx1)})}))._valueWithInterval_(repeatInterval);
 return interval;
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}))._valueWithTimeout_((300));
@@ -1669,19 +1701,19 @@ return delay;
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 _st(_st(_st(self)._wrapper())._asJQuery())._keyup_((function(e){
 return smalltalk.withContext(function($ctx2) {
-$3=active;
-if(smalltalk.assert($3)){
+$9=active;
+if(smalltalk.assert($9)){
 active=false;
 active;
-$4=interval;
-if(($receiver = $4) == nil || $receiver == undefined){
-$4;
+$10=interval;
+if(($receiver = $10) == nil || $receiver == undefined){
+$10;
 } else {
 _st(interval)._clearInterval();
 };
-$5=delay;
-if(($receiver = $5) == nil || $receiver == undefined){
-return $5;
+$11=delay;
+if(($receiver = $11) == nil || $receiver == undefined){
+return $11;
 } else {
 return _st(delay)._clearTimeout();
 };
@@ -1689,8 +1721,8 @@ return _st(delay)._clearTimeout();
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{active:active,interval:interval,delay:delay,repeatInterval:repeatInterval},smalltalk.HLListWidget)})},
 args: [],
-source: "setupKeyBindings\x0a\x09\x22TODO: refactor this!\x22\x0a\x09\x0a\x09| active interval delay repeatInterval |\x0a\x09\x0a\x09active := false.\x0a\x09repeatInterval := 70.\x0a\x09self wrapper asJQuery unbind: 'keydown'.\x0a\x0a\x09self wrapper asJQuery keydown: [ :e |\x0a\x09\x09\x0a        (e which = 38 and: [ active = false ]) ifTrue: [ \x0a\x09\x09\x09active := true.\x0a\x09\x09\x09self activatePreviousListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [ self activatePreviousListItem ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ].\x0a\x09\x09\x09\x0a      \x09(e which = 40 and: [ active = false ]) ifTrue: [\x0a            active := true.\x0a\x09\x09\x09self activateNextListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [ self activateNextListItem ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ] ].\x0a\x09\x0a\x09self wrapper asJQuery keyup: [ :e |\x0a\x09\x09active ifTrue: [\x0a\x09\x09\x09active := false.\x0a\x09\x09\x09interval ifNotNil: [ interval clearInterval ].\x0a\x09\x09\x09delay ifNotNil: [ delay clearTimeout] ] ]",
-messageSends: ["unbind:", "asJQuery", "wrapper", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "and:", "=", "which", "activateNextListItem", "keyup:", "ifNotNil:", "clearInterval", "clearTimeout"],
+source: "setupKeyBindings\x0a\x09\x22TODO: refactor this!\x22\x0a\x09\x0a\x09| active interval delay repeatInterval |\x0a\x09\x0a\x09active := false.\x0a\x09repeatInterval := 70.\x0a\x09self wrapper asJQuery unbind: 'keydown'.\x0a\x0a\x09self wrapper asJQuery keydown: [ :e |\x0a\x09\x09\x0a        (e which = 38 and: [ active = false ]) ifTrue: [ \x0a\x09\x09\x09active := true.\x0a\x09\x09\x09self activatePreviousListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [\x0a\x09\x09\x09\x09\x09(self wrapper asJQuery hasClass: self focusClass)\x0a\x09\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09\x09self activatePreviousListItem ]\x0a\x09\x09\x09\x09\x09\x09ifFalse: [\x0a\x09\x09\x09\x09\x09\x09\x09active := false.\x0a\x09\x09\x09\x09\x09\x09\x09interval ifNotNil: [ interval clearInterval ].\x0a\x09\x09\x09\x09\x09\x09\x09delay ifNotNil: [ delay clearTimeout] ] ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ].\x0a\x09\x09\x09\x0a      \x09(e which = 40 and: [ active = false ]) ifTrue: [\x0a            active := true.\x0a\x09\x09\x09self activateNextListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [ \x0a\x09\x09\x09\x09\x09(self wrapper asJQuery hasClass: self focusClass)\x0a\x09\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09\x09self activateNextListItem ]\x0a\x09\x09\x09\x09\x09\x09ifFalse: [\x0a\x09\x09\x09\x09\x09\x09\x09active := false.\x0a\x09\x09\x09\x09\x09\x09\x09interval ifNotNil: [ interval clearInterval ].\x0a\x09\x09\x09\x09\x09\x09\x09delay ifNotNil: [ delay clearTimeout] ] ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ] ].\x0a\x09\x0a\x09self wrapper asJQuery keyup: [ :e |\x0a\x09\x09active ifTrue: [\x0a\x09\x09\x09active := false.\x0a\x09\x09\x09interval ifNotNil: [ interval clearInterval ].\x0a\x09\x09\x09delay ifNotNil: [ delay clearTimeout] ] ]",
+messageSends: ["unbind:", "asJQuery", "wrapper", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "ifTrue:ifFalse:", "ifNotNil:", "clearInterval", "clearTimeout", "hasClass:", "focusClass", "and:", "=", "which", "activateNextListItem", "keyup:"],
 referencedClasses: []
 }),
 smalltalk.HLListWidget);

+ 23 - 2
js/Helios-Workspace.deploy.js

@@ -1005,7 +1005,7 @@ return _st(self)._onSourceCodeSaved();
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 _st($1)._on_do_($HLAboutToChange(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
-return _st(self)._onBrowserAboutToChange();
+return _st(self)._onBrowserAboutToChange_(_st(ann)._actionBlock());
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 _st($1)._on_do_($HLParseErrorRaised(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
@@ -1040,7 +1040,7 @@ return smalltalk.withContext(function($ctx2) {
 return _st(self)._onSourceCodeFocusRequested();
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"observeBrowserModel",{},smalltalk.HLBrowserCodeWidget)})},
-messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onShowInstanceToggled", "onSourceCodeSaved", "onBrowserAboutToChange", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"]}),
+messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onShowInstanceToggled", "onSourceCodeSaved", "onBrowserAboutToChange:", "actionBlock", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"]}),
 smalltalk.HLBrowserCodeWidget);
 
 smalltalk.addMethod(
@@ -1100,6 +1100,27 @@ return self}, function($ctx1) {$ctx1.fill(self,"onBrowserAboutToChange",{},small
 messageSends: ["ifTrue:", "confirm:ifFalse:", "signal", "methodContents:", "contents", "hasModification"]}),
 smalltalk.HLBrowserCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onBrowserAboutToChange:",
+fn: function (aBlock){
+var self=this;
+function $HLChangeForbidden(){return smalltalk.HLChangeForbidden||(typeof HLChangeForbidden=="undefined"?nil:HLChangeForbidden)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self)._hasModification();
+if(smalltalk.assert($1)){
+_st(self)._confirm_ifTrue_("Do you want to cancel changes?",(function(){
+return smalltalk.withContext(function($ctx2) {
+_st(self)._methodContents_(_st(self)._contents());
+return _st(aBlock)._value();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+_st($HLChangeForbidden())._signal();
+};
+return self}, function($ctx1) {$ctx1.fill(self,"onBrowserAboutToChange:",{aBlock:aBlock},smalltalk.HLBrowserCodeWidget)})},
+messageSends: ["ifTrue:", "confirm:ifTrue:", "methodContents:", "contents", "value", "signal", "hasModification"]}),
+smalltalk.HLBrowserCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onClassSelected:",

+ 29 - 3
js/Helios-Workspace.js

@@ -1331,7 +1331,7 @@ return _st(self)._onSourceCodeSaved();
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 _st($1)._on_do_($HLAboutToChange(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
-return _st(self)._onBrowserAboutToChange();
+return _st(self)._onBrowserAboutToChange_(_st(ann)._actionBlock());
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 _st($1)._on_do_($HLParseErrorRaised(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
@@ -1367,8 +1367,8 @@ return _st(self)._onSourceCodeFocusRequested();
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"observeBrowserModel",{},smalltalk.HLBrowserCodeWidget)})},
 args: [],
-source: "observeBrowserModel\x0a\x09self browserModel announcer\x0a\x09\x09on: HLSaveSourceCode\x0a\x09\x09do: [ :ann | self onSaveIt ];\x0a\x09\x09on: HLShowInstanceToggled\x0a\x09\x09do: [ :ann | self onShowInstanceToggled ];\x0a\x09\x09on: HLSourceCodeSaved\x0a\x09\x09do: [ :ann | self onSourceCodeSaved ];\x0a\x09\x09on: HLAboutToChange\x0a\x09\x09do: [ :ann | self onBrowserAboutToChange ];\x0a\x09\x09on: HLParseErrorRaised\x0a\x09\x09do: [ :ann | self onParseError: ann ];\x0a\x09\x09on: HLCompileErrorRaised\x0a\x09\x09do: [ :ann | self onCompileError: ann error ];\x0a\x09\x09on: HLUnknownVariableErrorRaised\x0a\x09\x09do: [ :ann | self onUnknownVariableError: ann error ];\x0a\x09\x09on: HLInstVarAdded \x0a\x09\x09do: [ :ann | self onInstVarAdded ];\x0a\x09\x09on: HLMethodSelected \x0a\x09\x09do: [ :ann | self onMethodSelected: ann item ];\x0a    \x09on: HLClassSelected \x0a\x09\x09do: [ :ann | self onClassSelected: ann item ];\x0a    \x09on: HLProtocolSelected \x0a\x09\x09do: [ :ann | self onProtocolSelected: ann item ];\x0a\x09\x09on: HLSourceCodeFocusRequested \x0a\x09\x09do: [ :ann | self onSourceCodeFocusRequested ]",
-messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onShowInstanceToggled", "onSourceCodeSaved", "onBrowserAboutToChange", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"],
+source: "observeBrowserModel\x0a\x09self browserModel announcer\x0a\x09\x09on: HLSaveSourceCode\x0a\x09\x09do: [ :ann | self onSaveIt ];\x0a\x09\x09on: HLShowInstanceToggled\x0a\x09\x09do: [ :ann | self onShowInstanceToggled ];\x0a\x09\x09on: HLSourceCodeSaved\x0a\x09\x09do: [ :ann | self onSourceCodeSaved ];\x0a\x09\x09on: HLAboutToChange\x0a\x09\x09do: [ :ann | self onBrowserAboutToChange: ann actionBlock ];\x0a\x09\x09on: HLParseErrorRaised\x0a\x09\x09do: [ :ann | self onParseError: ann ];\x0a\x09\x09on: HLCompileErrorRaised\x0a\x09\x09do: [ :ann | self onCompileError: ann error ];\x0a\x09\x09on: HLUnknownVariableErrorRaised\x0a\x09\x09do: [ :ann | self onUnknownVariableError: ann error ];\x0a\x09\x09on: HLInstVarAdded \x0a\x09\x09do: [ :ann | self onInstVarAdded ];\x0a\x09\x09on: HLMethodSelected \x0a\x09\x09do: [ :ann | self onMethodSelected: ann item ];\x0a    \x09on: HLClassSelected \x0a\x09\x09do: [ :ann | self onClassSelected: ann item ];\x0a    \x09on: HLProtocolSelected \x0a\x09\x09do: [ :ann | self onProtocolSelected: ann item ];\x0a\x09\x09on: HLSourceCodeFocusRequested \x0a\x09\x09do: [ :ann | self onSourceCodeFocusRequested ]",
+messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onShowInstanceToggled", "onSourceCodeSaved", "onBrowserAboutToChange:", "actionBlock", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"],
 referencedClasses: ["HLSaveSourceCode", "HLShowInstanceToggled", "HLSourceCodeSaved", "HLAboutToChange", "HLParseErrorRaised", "HLCompileErrorRaised", "HLUnknownVariableErrorRaised", "HLInstVarAdded", "HLMethodSelected", "HLClassSelected", "HLProtocolSelected", "HLSourceCodeFocusRequested"]
 }),
 smalltalk.HLBrowserCodeWidget);
@@ -1440,6 +1440,32 @@ referencedClasses: ["HLChangeForbidden"]
 }),
 smalltalk.HLBrowserCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onBrowserAboutToChange:",
+category: 'reactions',
+fn: function (aBlock){
+var self=this;
+function $HLChangeForbidden(){return smalltalk.HLChangeForbidden||(typeof HLChangeForbidden=="undefined"?nil:HLChangeForbidden)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self)._hasModification();
+if(smalltalk.assert($1)){
+_st(self)._confirm_ifTrue_("Do you want to cancel changes?",(function(){
+return smalltalk.withContext(function($ctx2) {
+_st(self)._methodContents_(_st(self)._contents());
+return _st(aBlock)._value();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+_st($HLChangeForbidden())._signal();
+};
+return self}, function($ctx1) {$ctx1.fill(self,"onBrowserAboutToChange:",{aBlock:aBlock},smalltalk.HLBrowserCodeWidget)})},
+args: ["aBlock"],
+source: "onBrowserAboutToChange: aBlock\x0a\x09self hasModification\x0a\x09\x09ifTrue: [\x0a\x09\x09\x09self \x0a\x09\x09\x09\x09confirm: 'Do you want to cancel changes?' \x0a\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x22Don't ask twice\x22\x0a\x09\x09\x09\x09\x09self methodContents: self contents.\x0a\x09\x09\x09\x09\x09aBlock value ].\x0a\x09\x09\x09\x0a\x09\x09\x09\x0a\x09\x09\x09HLChangeForbidden signal ]",
+messageSends: ["ifTrue:", "confirm:ifTrue:", "methodContents:", "contents", "value", "signal", "hasModification"],
+referencedClasses: ["HLChangeForbidden"]
+}),
+smalltalk.HLBrowserCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onClassSelected:",

+ 11 - 1
st/Helios-Announcements.st

@@ -1,8 +1,18 @@
 Smalltalk current createPackage: 'Helios-Announcements'!
 Object subclass: #HLAboutToChange
-	instanceVariableNames: ''
+	instanceVariableNames: 'actionBlock'
 	package: 'Helios-Announcements'!
 
+!HLAboutToChange methodsFor: 'accessing'!
+
+actionBlock
+	^ actionBlock
+!
+
+actionBlock: aBlock
+	actionBlock := aBlock
+! !
+
 Object subclass: #HLAnnouncement
 	instanceVariableNames: ''
 	package: 'Helios-Announcements'!

+ 3 - 2
st/Helios-Browser.st

@@ -1277,8 +1277,9 @@ handleParseError: anError
 
 withChangesDo: aBlock
 	[ 
-		self announcer announce: HLAboutToChange new.
-		aBlock value
+		self announcer announce: (HLAboutToChange new
+			actionBlock: aBlock).
+		aBlock value.
 	]
 		on: HLChangeForbidden 
 		do: [ :ex | ]

+ 17 - 7
st/Helios-Core.st

@@ -408,11 +408,7 @@ activateListItem: aListItem
 !
 
 activateNextListItem
-	self activateListItem: (window jQuery: '.focused .nav-pills .active') next.
-	
-	"select the first item if none is selected"
-	(window jQuery: '.focused .nav-pills .active') get ifEmpty: [
-		self activateFirstListItem ]
+	self activateListItem: (window jQuery: '.focused .nav-pills .active') next
 !
 
 activatePreviousListItem
@@ -474,7 +470,14 @@ setupKeyBindings
 			active := true.
 			self activatePreviousListItem.
         	delay := [
-				interval := [ self activatePreviousListItem ]
+				interval := [
+					(self wrapper asJQuery hasClass: self focusClass)
+						ifTrue: [
+							self activatePreviousListItem ]
+						ifFalse: [
+							active := false.
+							interval ifNotNil: [ interval clearInterval ].
+							delay ifNotNil: [ delay clearTimeout] ] ]
 					valueWithInterval: repeatInterval ]
 						valueWithTimeout: 300 ].
 			
@@ -482,7 +485,14 @@ setupKeyBindings
             active := true.
 			self activateNextListItem.
         	delay := [
-				interval := [ self activateNextListItem ]
+				interval := [ 
+					(self wrapper asJQuery hasClass: self focusClass)
+						ifTrue: [
+							self activateNextListItem ]
+						ifFalse: [
+							active := false.
+							interval ifNotNil: [ interval clearInterval ].
+							delay ifNotNil: [ delay clearTimeout] ] ]
 					valueWithInterval: repeatInterval ]
 						valueWithTimeout: 300 ] ].
 	

+ 15 - 1
st/Helios-Workspace.st

@@ -491,7 +491,7 @@ observeBrowserModel
 		on: HLSourceCodeSaved
 		do: [ :ann | self onSourceCodeSaved ];
 		on: HLAboutToChange
-		do: [ :ann | self onBrowserAboutToChange ];
+		do: [ :ann | self onBrowserAboutToChange: ann actionBlock ];
 		on: HLParseErrorRaised
 		do: [ :ann | self onParseError: ann ];
 		on: HLCompileErrorRaised
@@ -548,6 +548,20 @@ onBrowserAboutToChange
 			self methodContents: self contents ]
 !
 
+onBrowserAboutToChange: aBlock
+	self hasModification
+		ifTrue: [
+			self 
+				confirm: 'Do you want to cancel changes?' 
+				ifTrue: [
+					"Don't ask twice"
+					self methodContents: self contents.
+					aBlock value ].
+			
+			
+			HLChangeForbidden signal ]
+!
+
 onClassSelected: aClass
 	aClass ifNil: [ ^ self contents: '' ].