Red-lang Event: symetric of over (not-over)? - rebol

https://doc.red-lang.org/en/view.html
over
mouse
Mouse cursor passing over a face. This event is produced once when the mouse enters the face and once when it exits. If flags facet contains all‑over flag, then all intermediary events are produced too.
There is no symetric event ? How do I know mouse is not over anymore ?
In rebol there was http://www.rebol.com/how-to/feel.html
but this syntax doesn't exist anymore in Red or I am mistaken ?
view layout [
box "A Box" forest feel [
over: func [face act pos] [print [act pos]]
]
]

No symetric event is needed as you can use the event/away? flag to check if the over event is exiting the face area. See https://doc.red-lang.org/en/view.html#_event_datatype
feel in Rebol/VID is just a keyword for listing event handlers, it's not needed in Red/VID, as event handlers are first-class citizens. So in Red/VID, you would write it:
view [box "A Box" forest on-over [print [event/offset event/away?]]]

Related

Why does this code not clear mouse events from the SDL Events Poll?

I found some of this code from other StackOverflow questions, but basically in my code I run an SDL_Delay and I don't want any mouse events to be registered during this delay, but they still are so I run this code:
SDL_FlushEvents(SDL_USEREVENT, SDL_LASTEVENT);
SDL_PollEvent( &event );
event.type = SDL_USEREVENT;
event.button.x = 0;
event.button.y = 0;
But even after this code after the next SDL_PollEvent(&event), the mouse up events are registered. How do I fix this and stop these mouse events from being registered?
SDL_FlushEvents only clears events that are currently in the SDL queue. Events are put into queue by SDL_PumpEvents call (called internally by SDL_PollEvent). In addition, in clears events in specified type range. As written in question, it clears only events of type "user event" (every type with value higher than SDL_USEREVENT is available as user event type). To clear all events, you want to clear types [0, MAX], or special aliases SDL_FIRSTEVENT (0) and SDL_LASTEVENT (maximum value event type can take).
To sum it up:
SDL_PumpEvents();
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
If required, you can check actual values of event types in SDL_event.h file. If you only want to clear mouse events, it would be e.g. SDL_FlushEvents(SDL_MOUSEMOTION, SDL_MOUSEMOTION+0x50).
The other way to do the same is to process entire event queue until it is empty - e.g.
while(SDL_PollEvent(NULL)) {}

Rebol: Dynamic binding of block words

In Rebol, there are words like foreach that allow "block parametrization" over a given word and a series, e.g., foreach w [1 2 3] [print w]. Since I find that syntax very convenient (as opposed to passing func blocks), I'd like to use it for my own words that operate on lazy lists, e.g map/stream x s [... x ... ].
How is that syntax idiom called? How is it properly implemented?
I was searching the docs, but I could not find a straight answer, so I tried to implement foreach on my own. Basically, my implementation comes in two parts. The first part is a function that binds a specific word in a block to a given value and yields a new block with the bound words.
bind-var: funct [block word value] [
qw: load rejoin ["'" word]
do compose [
set (:qw) value
bind [(block)] (:qw)
[(block)] ; This shouldn't work? see Question 2
]
]
Using that, I implemented foreach as follows:
my-foreach: func ['word s block] [
if empty? block [return none]
until [
do bind-var block word first s
s: next s
tail? s
]
]
I find that approach quite clumsy (and it probably is), so I was wondering how the problem can be solved more elegantly. Regardless, after coming up with my contraption, I am left with two questions:
In bind-var, I had to do some wrapping in bind [(block)] (:qw) because (block) would "dissolve". Why?
Because (?) of 2, the bind operation is performed on a new block (created by the [(block)] expression), not the original one passed to my-foreach, with seperate bindings, so I have to operate on that. By mistake, I added [(block)] and it still works. But why?
Great question. :-) Writing your own custom loop constructs in Rebol2 and R3-Alpha (and now, history repeating with Red) has many unanswered problems. These kinds of problems were known to the Rebol3 developers and considered blocking bugs.
(The reason that Ren-C was started was to address such concerns. Progress has been made in several areas, though at time of writing many outstanding design problems remain. I'll try to just answer your questions under the historical assumptions, however.)
In bind-var, I had to do some wrapping in bind [(block)] (:qw) because (block) would "dissolve". Why?
That's how COMPOSE works by default...and it's often the preferred behavior. If you don't want that, use COMPOSE/ONLY and blocks will not be spliced, but inserted as-is.
qw: load rejoin ["'" word]
You can convert WORD! to LIT-WORD! via to lit-word! word. You can also shift the quoting responsibility into your boilerplate, e.g. set quote (word) value, and avoid qw altogether.
Avoiding LOAD is also usually preferable, because it always brings things into the user context by default--so it loses the binding of the original word. Doing a TO conversion will preserve the binding of the original WORD! in the generated LIT-WORD!.
do compose [
set (:qw) value
bind [(block)] (:qw)
[(block)] ; This shouldn't work? see Question 2
]
Presumably you meant COMPOSE/DEEP here, otherwise this won't work at all... with regular COMPOSE the embedded PAREN!s cough, GROUP!s for [(block)] will not be substituted.
By mistake, I added [(block)] and it still works. But why?
If you do a test like my-foreach x [1] [print x probe bind? 'x] the output of the bind? will show you that it is bound into the "global" user context.
Fundamentally, you don't have any MAKE OBJECT! or USE to create a new context to bind the body into. Hence all you could potentially be doing here would be stripping off any existing bindings in the code for x and making sure they are into the user context.
But originally you did have a USE, that you edited to remove. That was more on the right track:
bind-var: func [block word value /local qw] [
qw: load rejoin ["'" word]
do compose/deep [
use [(qw)] [
set (:qw) value
bind [(block)] (:qw)
[(block)] ; This shouldn't work? see Question 2
]
]
]
You're right to suspect something is askew with how you're binding. But the reason this works is because your BIND is only redoing the work that USE itself does. USE already deep walks to make sure any of the word bindings are adjusted. So you could omit the bind entirely:
do compose/deep [
use [(qw)] [
set (:qw) value
[(block)]
]
]
the bind operation is performed on a new block (created by the [(block)] expression), not the original one passed to my-foreach, with separate bindings
Let's adjust your code by taking out the deep-walking USE to demonstrate the problem you thought you had. We'll use a simple MAKE OBJECT! instead:
bind-var: func [block word value /local obj qw] [
do compose/deep [
obj: make object! [(to-set-word word) none]
qw: bind (to-lit-word word) obj
set :qw value
bind [(block)] :qw
[(block)] ; This shouldn't work? see Question 2
]
]
Now if you try my-foreach x [1 2 3] [print x]you'll get what you suspected... "x has no value" (assuming you don't have some latent global definition of x it picks up, which would just print that same latent value 3 times).
But to make you sufficiently sorry you asked :-), I'll mention that my-foreach x [1 2 3] [loop 1 [print x]] actually works. That's because while you were right to say a bind in the past shouldn't affect a new block, this COMPOSE only creates one new BLOCK!. The topmost level is new, any "deeper" embedded blocks referenced in the source material will be aliases of the original material:
>> original: [outer [inner]]
== [outer [inner]]
>> composed: compose [<a> (original) <b>]
== [<a> outer [inner] <b>]
>> append original/2 "mutation"
== [inner "mutation"]
>> composed
== [<a> outer [inner "mutation"] <b>]
Hence if you do a mutating BIND on the composed result, it can deeply affect some of your source.
until [
do bind-var block word first s
s: next s
tail? s
]
On a general note of efficiency, you're running COMPOSE and BIND operations on each iteration of your loop. No matter how creative new solutions to these kinds of problems get (there's a LOT of new tech in Ren-C affecting your kind of problem), you're still probably going to want to do it only once and reuse it on the iterations.

Squeak Smalltalk: Game loop

In many languages you can do something like the following:
while true:
handle events like keyboard input
update game world
draw screen
(optional: delay execution)
while this is far from optimal it should suffice for simple games.
How do you do this in Squeak Smalltalk?
I can read keyboard input and react to it as described on wiki.squeak.org. But if I try to execute something like
1 to: 10 do: [ :i | game updateAndDraw ]
all the events are only ever handled after the loop has executed.
Morphic already provides that main loop. It's in MorphicProject class>>spawnNewProcess:
uiProcess := [
[ world doOneCycle. Processor yield ] repeat.
] newProcess ...
And if you dig into doOneCycle you will find it
(optionally) does a delay (interCyclePause:)
checks for screen resize
processes events
processes step methods
re-displays the world
Your code should hook into these phases by adding mouse/keyboard event handlers, step methods for animation, and draw methods for redisplaying. All of these should be methods in your own game morph. You can find examples throughout the system.
To perform an action a fixed number of times:
10 timesRepeat: [game updateAndDraw]
To use while semantics:
i := 5
[i > 0] whileTrue: [
i printNl.
i := i - 1.
]
To create a perpetual loop using while semantics,
[true] whileTrue: [something do]
You should be able to take advantage of the Morphic event loop by using the Object >> #when:send:to: message.

Seaside - clear form on re-render?

Is there a way to reset all of the text inputs for a page when it's re-rendered? The page keeps loading with the text from the previous rendering still in the inputs.
That depends very much on the way you render those inputs. If you use Seaside components, then you might implement you own logic within the callback:
html textInput
callback: [ :value | self setOrResetMyInputWith: value ]
with: 'my input'.
#setOrResetMyInputWith: might then look like this:
setOrResetMyInputWith: aString
myInputValue := self allCriteriaMet
ifTrue: [ aString ]
ifFalse: [ nil ]
Keep in mind that you cannot predict the order in which the callbacks will be evaluated. Therefore, it might be easier to do the check before rendering:
renderContentOn: html
self checkMyInputs.
"continue rendering process"
...
You could then simply reset your instance variables if the criteria are not satisfied.
That's for components. If you use Magritte, than Magritte's verification mechanism should take care of this. All you need to do is to enable verification in the respective descriptions.

How to create a custom mouse cursor in Matplotlib

I am interested in creating a custom mouse cursor, so that during drag and pick events on certain lines or points, the mouse changes from an arrow to a hand (or other symbol).
What is the best method of doing this?
I assume this is possible since the mouse cursor changes to a small cross hair during zoom operations. If possible, a solution using the PyQt/PySide backend would be preferable.
What you need is mpl_canvas. Follow this tutorial to set one up.
With an mpl_canvas, you can then set up events that get triggered.
fig = matplotlib.figure.Figure()
cid = fig.canvas.mpl_connect('button_press_event', your_method)
There are several kinds of signals under here (listed under Events).
With your signal set up, your_method gets called, with an event parameter. So do something like:
def your_method(event):
print('Your x and y mouse positions are ', event.xdata, event.ydata)
Click on the corrosponding Class and description links to see what exactly is in event. for a specific mpl_canvas Event.
In your specific case, to change how the mouse looks your_method should look something like:
def your_method(event):
#changes cursor to +
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))