[Gambas-user] Help with Observer 'Stop Event'

Tobias Boege taboege at ...626...
Mon Mar 27 22:18:47 CEST 2017


On Mon, 27 Mar 2017, Riccardo wrote:
> I have an observer on a ValueBox control to prevent it changing to zero and
> to prevent it becoming larger than the value in a different ValueBox.
> 
> Public Sub valNumObserver_change()
> 
>   If valNum.value = 0 Then valNum.Value = 1
>   If valNum.Value > valDen.Value Then Stop Event
> 
> End
> 
> With first case, where the zero value is changed to one, works. But the Stop
> Event doesn't do what I expect (it does nothing actually) in the second
> line...
> 

The documentation about Stop Event [1] says:

  This statement must be used in an event handler. It tells the interpreter
  that the event that called the event handler must be cancelled.

This may have mislead you to overestimate what the interpreter does when
it encounters a Stop Event.

What roughly happens when an object raises an event, by using the Raise
keyword, is: (1) all "before" observers receive the event, then (2) the
default observer of the object receives the event, and lastly (3) all
"after" observers receive the event. For each observer, the corresponding
event handler is called and as soon as one of these event handlers use
Stop Event, this whole chain is aborted.

But that's about all the interpreter can do. It stops propagation of the
event to later observers. Imagine that your Observer object is one of
potentially many observers waiting in line to be notified of the ValueBox
Change event. By using Stop Event you tell the interpreter to skip those
observers behind you, which have not seen the event yet.

At that point, the program flow gets back to the ValueBox -- but the
important fact is, for the component programmer, the one who wrote the
ValueBox code, obeying Stop Event is completely voluntary. What he does
is out of the interpreter's reach.

The programmer can choose to get a notification of whether the event was
aborted by getting the return value of the Raise keyword:

  Dim bCancel As Boolean

  bCancel = Raise Change

This value tells him if someone called Stop Event or not. But he is free
to ignore that value, or to react to it however he wants. He may even abort
the event whenever you tell him not to.

Now look at the source code of ValueBox (comp/src/gb.form/.src/ValueBox.class):

--8<---[ $ grep -C 2 "Raise Change" ValueBox.class ]--------
  If $hTextBox.Text <> $sLastText Then
    $sLastText = $hTextBox.Text
    Raise Change
  Endif

  --
  Public Sub DateBox_Change()

    Raise Change

  End
  --
  Public Sub CurrencyBox_Change()

    Raise Change

  End
  --
  Public Sub IpAddressBox_Change()

    Raise Change

  End
--8<--------------------------------------------------------

The programmer chose to ignore Stop Event for every instance of raising the
Change event [*]. I'm not sure if there is anything you can do about it,
apart from dirty hacks or writing your own ValueBox. Maybe you should just
try and ask Benoit to add support for Stop Event in the ValueBox.

Regards,
Tobi

[*] This is normal actually. You can grep through the source tree for
    "= Raise" on the one hand and "^ *Raise" on the other. It gives me
    a ratio of 28/865, so about 3% of Raise statements even consider the
    possibility that the user Stop Event's them. This is only counting
    non-native Gambas events, though.

[1] http://gambaswiki.org/wiki/lang/stopevent

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk




More information about the User mailing list