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!