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!