NS BASIC Tech Note 46 April 21, 1998
How to control draggable widgets
---------------------------------------------------------------------------------
[Note: This tech note was contributed by
Valentino Kyriakides
Universitaet Hamburg, FB. Informatik
Arbeitsbereich Softwaretechnik
E-Mail: 1kyriaki© informatik.uni-hamburg.de (ASCII, MIME)
NeXTmail: Valentino_Kyriakides© public.uni-hamburg.de]
[Note: This could probably be adapted to NewtCard as well - if you do so, let us know so we can update this document!]
After endless tryouts and pitfalls I think I have a working solution for the
NSBASIC drag or tap. My main solution is included at the end of this email.
First I tried using viewChangedScript('viewBounds,self) to solve the
problem, since I finally got reply from Stephen Blessing and he explained
me the viewChangedScript stuff. But this NS function seems only to be
recognized by the NSB "text"-widget and is not usable for plain NSB windows,
textbuttons and other widgets.
Here are two poor textwidget examples:
Note: these seem to work only for text-widgets
10 LET winSpec := {goto:70, text: "Drag or Tap this text window!"}
20 FUNCTION dragOrTap(unit) BEGIN :drag(unit,nil); local sb := StrokeBounds(unit); U.moved := (max(abs(sb.bottom - sb.top), abs(sb.right - sb.left)) > 2); :viewChangedScript('viewBounds,self); return nil; END
40 window w1, winSpec, "TEXT"
50 LET winSpec.viewClickScript:=dragOrTap
60 SHOW w1
65 wait -1
70 REM if the user only tapped the window finish, otherwise keep drag state
80 if moved then goto 50 else print "...got just a tap!..."
90 hide w1
100 end
Here is the second example to distinguish between a drag or tap:
0001 LET appSpec={goto:'endProgram,title:"Test"}
0002 window app,appSpec,"APP"
0003 show app
0010 LET winSpec := {gosub:70, text: "Drag or Tap!"}
0030 function myCheck(unit) begin :drag(unit,nil);local sb :=StrokeBounds(unit); U.moved := (max(abs(sb.bottom-sb.top),abs(sb.right-sb.left))>2);:viewChangedScript('viewFlags,self);return nil;end
0040 window w1,winSpec,"text"
0050 LET winSpec.viewClickScript:=myCheck
0060 SHOW w1
0065 wait -1
0070 REM handles either a drag or a tap
0080 if moved then print "dragged" else print "tapped"
0090 return
9000 endProgram: rem
9010 hide
9020 end
Now since all the above wasn't the solution I had in mind (since I wanted
to find a solution which works for every widget), I went back to the idea of
reusing the inherited viewClickScript method. - So far my main working solution
looks like this:
10 LET winSpec := {goto:70, text: "Drag or Tap this window!"}
20 FUNCTION dragOrTap(unit) BEGIN :drag(unit,nil); local sb := StrokeBounds(unit); U.moved := (max(abs(sb.bottom - sb.top), abs(sb.right - sb.left)) > 2); if not U.moved then begin U.winSpec.viewClickScript:= inherited:?viewClickScript(unit); END; END
40 window w1, winSpec
50 LET winSpec.viewClickScript:=dragOrTap
60 SHOW w1
65 wait -1
70 REM User only tapped the window
80 if moved then print "The moved drag state should never reach this point!" else wprint w1, "I've recognized just a tap!"
85 wait 1000
90 hide w1
100 end
It also works with "text" and "textbuttons", but so far I haven't tested other widget types!
Here I've put everything into one dragOrTap function, which (depending on a drag or
tap) sets a NSB boolean moved variable. Then I test if the moved var is FALSE, if this
is the case I set the winSpec.viewClickScript to the inherited viewClickScript method.
One improvement would be to find a better more general way (replacement)
in dragOrTap for the
"U.winSpec.viewClickScript := ..."
so that the dragOrTap function would be independent from a special widget and could
be used by more than one widget in a program.
Here is a little improvement of the dragOrTap function, it seems to even works without
the U.winSpec.viewClickScript:= inherited:?viewClickScript(unit); assignment when we
just call inherited:?viewClickScript(unit) for plain window or textbutton widgets!
10 LET winSpec := {goto:70, text: "Drag or Tap this window!"}
20 FUNCTION dragOrTap(unit) BEGIN :drag(unit,nil); local sb := StrokeBounds(unit); U.moved := (max(abs(sb.bottom - sb.top), abs(sb.right - sb.left)) > 2); if not U.moved then begin inherited:?viewClickScript(unit); END; END
40 window w1, winSpec, "scroller"
50 LET winSpec.viewClickScript:=dragOrTap
60 SHOW w1
65 wait -1
70 REM User only tapped the window
80 if moved then print "The moved drag state should never reach this point!" else wprint w1, "I've recognized just a tap!"
85 wait 1000
90 hide w1
100 end
Note: when using for line 40 ----> window w1, winSpec, "text" the strange thing is that I got:
"The moved drag state should never reach this point!". So just tapping don't work for the
text-widgets. Also note that when using a scroller-widget neither dragging nor tapping works!