Folks,

thank you for the feedback on this one! 

@Bob: Displaying obviously invalid values for the derived fields as long as the field for data entry is in an invalid state might just work (-1 being a prominent example). My problems with this approach are more of an emotional than intellectual nature: I do not like using Guards on the one hand but  alloying my system to be in an invalid state on the other, even if it is invalid in an controlled and obvious way.

@Rene: The moment read your line " END NotifierA;" my head went BOOM. Probably my eyes did show a "does not compute" message at this moment due to intellectual overload. It took me quite a while to figure out what you probably wanted to say (see the attached file if you're interested in how serious my difficulties were). Here is what I believe to have understood and would like to know if that's correct:
-> Instead of checking a changed field for correctness (and doing computations based on it) just remember that it has been changed. It will be checked when any other field is changed.
Apart from the additional complexity this looks promising. Yet the last input will always be unnoticed and unchecked.
Perhaps the wrapper view may be the most elegant solution, but it sounds pretty sophisticated for my tastes.

@Robert: Delaying the validity check (and the subsequent calculations) with Services.Action might just be easy enough for me to give it a try. :-)

Thank's again for the inspiring pointers.
gunnar

-----Ursprüngliche Nachricht-----
Von: BlackBox [mailto:BLACKBOX@LISTS.OBERON.CH] Im Auftrag von Rene A. Krywult
Gesendet: Dienstag, 12. Januar 2010 10:57
An: BLACKBOX@LISTS.OBERON.CH
Betreff: Re: [BLACKBOX] limiting integer values in interactor field

You could also do a Wrapper view that has the following in the HandleCtrlMsg:

IF msg IS Controllers.MarkMsg THEN
   WITH msg:Controllers.MarkMsg DO
      IF msg.show=FALSE THEN
         StdLog.String("Lost focus");StdLog.Ln();
      ELSE	
         StdLog.String("Got focus");StdLog.Ln();
      END;
   END;
END;

Where 

StdLog.String("Lost focus");StdLog.Ln();

would do the checking.

Lastly, you could probably change Controls.Field.HandleCtrlMsg2, so that a new op is given for MarkMsg.show=FALSE, or that the op:=Dialog.changed is used for a change, when msg.show=FALSE.

Rene 

-------- Original-Nachricht --------
> Datum: Tue, 12 Jan 2010 10:09:52 +0100
> Von: "Rene A. Krywult" <rene.krywult@GMX.AT>
> An: BLACKBOX@LISTS.OBERON.CH
> Betreff: Re: [BLACKBOX] limiting integer values in interactor field

> What about a solution like this?
> 
> Rene
> 
> MODULE PrivTestLeave;
> IMPORT Dialog,StdLog;
> 
> VAR
> dialog*:RECORD;
> 	a*,b*,c*:INTEGER;
> END;
> 
> oldDialog*:RECORD;
> 	a*,b*,c*:INTEGER;
> END;
> 
> aChanged,bChanged,cChanged:BOOLEAN;
> 
> PROCEDURE IsValid(i:INTEGER):BOOLEAN;
> BEGIN
> 	IF ((i > 6) & (i < 15)) THEN
> 		RETURN TRUE;
> 	ELSE
> 		RETURN FALSE;
> 	END
> END IsValid;
> 
> PROCEDURE NotifierA* (op, from, to: INTEGER); BEGIN
> 	IF op=Dialog.changed THEN 
> 		IF ~aChanged THEN
> 		  IF bChanged THEN
> 			 IF ~IsValid(dialog.b) THEN
> 				 dialog.a:=oldDialog.a;
> 			 ELSE
> 				 bChanged:=FALSE;
> 				 aChanged:=TRUE;
> 				 oldDialog.b:=dialog.b;
> 			 END;
> 		  ELSIF cChanged THEN
> 			 IF ~IsValid(dialog.c) THEN
> 				 dialog.a:=oldDialog.a;
> 			 ELSE
> 				 cChanged:=FALSE;
> 				 aChanged:=TRUE;
> 				 oldDialog.c:=dialog.c;
> 			 END;
> 		  ELSE aChanged:=TRUE
> 		  END;
> 	ELSE
> 		aChanged:=TRUE;
> 		END;
> 	END;
> 	Dialog.Update(dialog);
> END NotifierA;
> 
> PROCEDURE NotifierB* (op, from, to: INTEGER); BEGIN
> 	IF op=Dialog.changed THEN 
> 		IF ~bChanged THEN
> 		  IF aChanged THEN
> 			 IF ~IsValid(dialog.a) THEN
> 				 dialog.b:=oldDialog.b;
> 			 ELSE
> 				 aChanged:=FALSE;
> 				 bChanged:=TRUE;
> 				 oldDialog.a:=dialog.a;
> 			 END;
> 		  ELSIF cChanged THEN
> 			 IF ~IsValid(dialog.c) THEN
> 				 dialog.b:=oldDialog.b;
> 			 ELSE
> 				 cChanged:=FALSE;
> 				 bChanged:=TRUE;
> 				 oldDialog.c:=dialog.c;
> 			 END;
> 		  ELSE bChanged:=TRUE
> 		  END;
> 		END;
> 	END;
> 	Dialog.Update(dialog);
> END NotifierB;
> 
> PROCEDURE NotifierC* (op, from, to: INTEGER); BEGIN
> 	IF op=Dialog.changed THEN 
> 		IF ~cChanged THEN
> 		  IF aChanged THEN
> 			 IF ~IsValid(dialog.a) THEN
> 				 dialog.c:=oldDialog.c;
> 			 ELSE
> 				 aChanged:=FALSE;
> 				 cChanged:=TRUE;
> 				 oldDialog.a:=dialog.a;
> 			 END;
> 		  ELSIF bChanged THEN
> 			 IF ~IsValid(dialog.b) THEN
> 				 dialog.c:=oldDialog.c;
> 			 ELSE
> 				 cChanged:=FALSE;
> 				 cChanged:=TRUE;
> 				 oldDialog.b:=dialog.b;
> 			 END;
> 		  ELSE cChanged:=TRUE
> 		  END;
> 		END;
> 	END;
> 	Dialog.Update(dialog);
> END NotifierC;
> END PrivTestLeave.
> 
> -------- Original-Nachricht --------
[...]Q0gg