Page 1 of 1

pseudocode "put the name of the intersected button....&

Posted: Tue Apr 21, 2009 5:14 pm
by gyroscope
Hi, still working on my Script Collector. SparkOut wrote some excellent code for me to help swap buttons but I have two columns of buttons and trying to amend SparkOut's code for that has defeated me.

So I thought I'd try a different tack to see if I could solve it a different way (as well as using code closer to my learning level at the moment): I found some code for moving any button in two rows within a rectangular area; so the limits are fine, no probs there.

If I drag a button and it overlaps (intersects) another button, in a mouseUp handler I'd like to get the name of the button which is intersected. That way I can get the loc of the button and swap it with the button intersecting it:

Code: Select all

local PosOldA, PosOldB, PosNewA, PosNewB, tNameB
on mouseDown
put item 1 of the loc of me into PosOldA
put item 2 of the loc of me into PosOldB
end mouseDown

on mouseUp
------- here's the pseudocode I'd like to replace with real code:
put the name of the intersected button into tNameB
------------------------------------------------------------
put item 1 of the loc of button tNameB into PosNewA
put item 2 of the loc of button tNameB into PosNewB
set the loc of me to PosNewA,PosNewB
set the loc of button tNameB to PosOldA,PosOldB
end mouseUp
I'm certain this would be successful if only I could get the location of the button being intersected, in a quick and straightforward way. Is this possible please :?:

Re: pseudocode "put the name of the intersected button.

Posted: Tue Apr 21, 2009 6:16 pm
by sturgis
Not sure how to do what you want with a drag, thats one of the learning areas I've neglected so far. But if all you want is a easy method to swap buttons you could try something like this.

Code: Select all

global gFirstButton,gFirstRect
on mouseDoubleDown
   if gFirstButton is empty then
      put the short name of me into gFirstButton
      put the rect of me into gFirstRect
   else
      put the rect of me into oldButtonPos
      set the rect of me to gFirstRect
      set the rect of button gFirstButton to oldButtonPos
      put empty into gFirstButton
      put empty into gFirstRect
   end if
end mouseDoubleDown
If you set this up on a button as a behavior *parent script* and link all your buttons to it, then to swap buttons double click the first, double click the second, and its done.

You would of course want to flesh this out because as it sits its hard to know if the first button has been double clicked etc. but that part shouldn't be too bad. Change the button color or text color of a button that you are going to swap so you know your state. (all kinds of options for that)

I'm sure there are other things that would need to be tweaked to make it work just like you want, but for a quick and dirty method to swap it works ok.
gyroscope wrote:Hi, still working on my Script Collector. SparkOut wrote some excellent code for me to help swap buttons but I have two columns of buttons and trying to amend SparkOut's code for that has defeated me.

So I thought I'd try a different tack to see if I could solve it a different way (as well as using code closer to my learning level at the moment): I found some code for moving any button in two rows within a rectangular area; so the limits are fine, no probs there.

If I drag a button and it overlaps (intersects) another button, in a mouseUp handler I'd like to get the name of the button which is intersected. That way I can get the loc of the button and swap it with the button intersecting it:

Code: Select all

local PosOldA, PosOldB, PosNewA, PosNewB, tNameB
on mouseDown
put item 1 of the loc of me into PosOldA
put item 2 of the loc of me into PosOldB
end mouseDown

on mouseUp
------- here's the pseudocode I'd like to replace with real code:
put the name of the intersected button into tNameB
------------------------------------------------------------
put item 1 of the loc of button tNameB into PosNewA
put item 2 of the loc of button tNameB into PosNewB
set the loc of me to PosNewA,PosNewB
set the loc of button tNameB to PosOldA,PosOldB
end mouseUp
I'm certain this would be successful if only I could get the location of the button being intersected, in a quick and straightforward way. Is this possible please :?:

Posted: Tue Apr 21, 2009 7:23 pm
by gyroscope
Hi sturgis

Terrific, thank you! I like that neat code. Clicking two buttons to swap will do the job just as well as dragging to swap. I'll amend it to be when the option/alt key is down and on a single mouseDown, I'm sure that should work.

I like the straightforwardness of this; I'll be applying it to another project in the future where groups are swapped; I'm certain it'll be just right for that also.

:)

Posted: Tue Apr 21, 2009 9:46 pm
by bn
gyroscope,

try this as a litte different approach:

Code: Select all

local tmyOrigLoc, tTrackOn

on mouseUp
    put false into tTrackOn
    -- here rest of on mouseUp if any
end mouseUp

on mouseDown
    -- here is your optinKey
    -- if the optionkey is down then
    put true into tTrackOn
    put the loc of me into tmyOrigLoc
    -- move it to the front so it is alway visible 
    set the layer of me to (the number of controls)
    send trackMe to me in 1 milliseconds
    -- end if
end mouseDown

on trackMe
    if not tTrackOn then
        put the loc of me into tCurrentLoc
        put "" into tMyNewLoc
        put false into tFoundOne
        put the short id of me into tmyID
        repeat with i = 1 to the number of buttons
            put the short id of button i into tanID
            if tanId <> tmyId then
                if intersect(button id tmyID, button id tanId) then 
                    put the loc of button i into tMyNewLoc
                    put true into tFoundOne
                    exit repeat
                end if
            end if
        end repeat
        if tFoundOne then 
            -- a little animation 
            move button id tanID from tMyNewLoc to tmyOrigLoc without waiting
            move me from the mouseloc to tMyNewLoc without waiting
        else
            put the number of of me into tmyNumber
            move me from tCurrentLoc to tmyOrigLoc 
        end if
    else 
        set the loc of me to the mouseloc
        send trackMe to me in 5 milliseconds
    end if
end trackMe
you either put it into the script of the relevant buttons or you put it into the script of behavior button (restricting the use to Rev > 3.5) and set the behavior of the relevant buttons to this behavior button. It animates the shifting of buttons and thus gives the user a little feedback of what is happening. I dont like it if things move around when I click on them, except in rare cases (puzzle comes to mind) or you got one that I dont know. It confuses me like Word used to have preferences in multilayered tabs. As soon as you clicked on one in the back layers it came to the front and I was always confused.
But I liked the problem of moving the buttons around, so I gave it a shot.
regards
Bernd

Posted: Tue Apr 21, 2009 11:08 pm
by bn
gyroscope,

try this instead of the previous post, it moves more naturally, no jumping buttons to the mouseloc.

Code: Select all

local tmyOrigLoc, tTrackOn

on mouseUp 
    -- rest of mouseUp stuff here if any
    if tTrackOn then
        put false into tTrackOn
        send trackMe to me in 2 milliseconds
    end if
end mouseUp

on mouseDown 
    -- here is your optinKey
    -- if the optionkey is down then
    put the loc of me into tmyOrigLoc
    put true into tTrackOn
    -- move it to the front so it is alway visible 
    set the layer of me to (the number of controls)
    grab me
    -- end if
end mouseDown

on trackMe
    if not tTrackOn then
        put the loc of me into tCurrentLoc
        put "" into tMyNewLoc
        put false into tFoundOne
        put the short id of me into tmyID
        repeat with i = 1 to the number of buttons
            put the short id of button i into tanID
            if tanId <> tmyId then
                if intersect(button id tmyID, button id tanId) then 
                    put the loc of button id tanID into tMyNewLoc
                    put true into tFoundOne
                    exit repeat
                end if
            end if
        end repeat
        if tFoundOne then 
            -- a little animation 
            move button id tanID from tMyNewLoc to tmyOrigLoc without waiting
            move me from tCurrentLoc to tMyNewLoc without waiting
        else
            move me from tCurrentLoc to tmyOrigLoc 
        end if
    else 
        set the loc of me to the mouseloc
    end if
end trackMe
regards
Bernd

Posted: Wed Apr 22, 2009 12:16 am
by gyroscope
I think that your code is rather elegant, Bernd; thank you very much for your help again, such an excellent solution. :)

I wish there was a way of limiting movement of "drag me" controls within a graphic rectangle though. I've been trying to do this to replace the following code I found by Tactile Media:

Code: Select all

# STORE SOME SPECS TO REFERENCE IN THE MOUSEMOVE HANDLER:
local allowDrag,CX,CY,W,H,boxL,boxR,boxT,boxB
on mouseDown
  # THE CLICK POSITION
  put (the mouseH - left of me) into CX
  put (the mouseV - top of me) into CY
  # WIDTH & HEIGHT OF THIS OBJECT
  put width of me into W
  put height of me into H
  # RECT OF THE CONSTRAINING BOX
  put item 1 of rect of grc boxlimit into boxL
  put item 3 of rect of grc boxlimit into boxR
  put item 2 of rect of grc boxlimit into boxT
  put item 4 of rect of grc boxlimit into boxB
  put true into allowDrag
end mouseDown

on mouseMove x,y
  if not allowDrag then exit mouseMove
  # DRAG ME
  set topLeft of me to \
      min(boxR - W,max(boxL,(x - CX))) & "," & min(boxB - H,max(boxT,(y - CY)))
end mouseMove

on mouseUp
  put empty into fld status
  put false into allowDrag
end mouseUp

on mouseRelease
  mouseUp
end mouseRelease
The solution utilizes aspects of the above code I'm certain but I can't quite work it out yet.

Has anyone any ideas how to constrain the buttons within a rectangle utilizing "grab me" please :?:

Posted: Wed Apr 22, 2009 10:31 am
by bn
magice,
I did not try to modify the grab, so its back to the first version, adapted to a constraining rect.

Code: Select all

local tmyOrigLoc, tTrackOn, tHorzOffset, tVertOffset, tConstrainRect

on mouseUp
    if tTrackOn then put false into tTrackOn
    -- rest of mouseUp here, if any
end mouseUp

on mouseRelease 
    mouseUp
end mouseRelease

on mouseDown
    -- here is your optinKey
    -- if the optionkey is down then
    put true into tTrackOn
    put the loc of me into tmyOrigLoc
    put the clickloc into tClick
    -- define offsets: difference between the loc and the clickloc
    -- makes for smother movement
    put item 1 of tmyOrigLoc - item 1 of tClick into tHorzOffset
    put item 2 of tmyOrigLoc - item 2 of tClick into tVertOffset
    
    -- here you define your rect, could also be: put "12,50,150,200" into tConstrainrect
    put the rect of graphic 1 into tConstrainRect
    -- move me to the front so I am alway visible 
    set the layer of me to (the number of controls)
    send trackMe to me in 1 milliseconds
    -- end if
end mouseDown

on trackMe
    -- get location and add offsets
    put the mouseloc into tMLoc
    
    -- here you constrain the movement of the buttons to a rect
    if not  (tMLoc is within tConstrainRect) and (tTrackOn) then
        send trackMe to me in 5 milliseconds
    exit trackMe
    end if
    
    -- take care of the offsets
    add tHorzOffset to item 1 of tMLoc
    add tVertOffset to item 2 of tMLoc
    
    if not tTrackOn then
        put "" into tMyNewLoc
        put false into tFoundOne
        put the short id of me into tmyID
        repeat with i = 1 to the number of buttons
            put the short id of button i into tanID
            if tanId <> tmyId then
                if intersect(button id tmyID, button id tanId) then 
                    put the loc of button i into tMyNewLoc
                    put true into tFoundOne
                    exit repeat
                end if
            end if
        end repeat
        
        if tFoundOne then 
            -- a little animation 
            move button id tanID from tMyNewLoc to tmyOrigLoc without messages
            move me from tMLoc to tMyNewLoc  without messages 
        else
            move me from the loc of me to tmyOrigLoc without messages
        end if
    else 
        set the loc of me to  tMLoc
        send trackMe to me in 3 milliseconds
    end if
end trackMe
edit: this works in a behavior button as well as in the relevant buttons. I start to like behavior buttons, it is so much easier to maintain code and debug it, even if you later put the code into the controls. Just name your stack before you link the controls to a behavior button otherwise your pointers will break. Do not rename the stack. You can rename the file but dont change the name of the stack.
edit 2: added without messages to move command since when clicking very fast during movement one could lock the button in a new location.
edit 3: it is either without waiting or without messages, not both, so -> I changed that
regards
Bernd

Posted: Wed Apr 22, 2009 4:20 pm
by gyroscope
Thank you muchly Bernd, that works well. You really have helped me a great deal: the majority of the coding in my My Script Collector is written by you; and I'm most grateful.
I did not try to modify the grab,...
For interest, I wonder if that's not possible anyhow, i.e to constrain a grab object?
this works in a behavior button as well as in the relevant buttons.

I'm still slightly confused concerning Behaviours, to be honest. When I see a few examples hopefully I'll understand the principle, so I'll stick with putting the script as a custom handler in the Stack or Card script and have the buttons call it up.

:)

Posted: Wed Apr 22, 2009 7:14 pm
by bn
gyroscope,
I'm still slightly confused concerning Behaviours, to be honest. When I see a few examples hopefully I'll understand the principle, so I'll stick with putting the script as a custom handler in the Stack or Card script and have the buttons call it up.
try this an see how easy it is:
make a new stack. NAME it. Save this stack. Make a button with the following script:

Code: Select all

on mouseUp
put the long id of me
end mouseUp
make, lets say three buttons (give them names just to be able to tell them apart) and one graphic rectangle place the graphic around the three buttons. The rectangle is not opaque.
In the message box you have the long id of the button you created first if you click at it once. You copy this long id from the message box. In the inspector for the three buttons for each in the basic properties at the bottom you paste the long id into the field behavior.

Now you take the script that I put up here (the last version) and paste that into the script of the first button, replacing the short script that is there.
Now click at on of the three buttons, hold the mouse down and move the button then releas the button. -> the button will move back to where it was if it does not intersect with another of the three buttons. These three buttons dont have a script for themselves, they use the script of the behavior button.
Try this, it shows how simple it is to use a behavior button.

BTW thinking of what you want: do you want to restrain the movement for the buttons to just move vertically? Or just horizontally? Or within a rect?

try behavior, it is worth a try.
regards
bernd

Posted: Wed Apr 22, 2009 10:59 pm
by gyroscope
I understand the principle of Behaviours now Bernd, thank you. In a way it's akin to putting the script as custom handlers in one script and have all others call them up; but deals with it in a more straightforward fashion. And now I think of it, Lingo in Macromind Director introduced something similar in the nineties.
BTW thinking of what you want: do you want to restrain the movement for the buttons to just move vertically? Or just horizontally? Or within a rect?
I would want the user to be able to move a button in any direction to certain up, down, left and right limits. My thinking was if there was a way to script this behaviour using "grab me" then a graphic rectangle wouldn't be needed.

For a future project, I'll be wanting to swap groups by moving and swapping groups of controls in the same way as the button swaps but when a restraining limit is reached, for the group (or button) to slidealong the inside of the restraining area.

Edit: For your interest Bernd, I've amalgamated your code with the constraining code I originally found and it works just fine as well.

Code: Select all

local allowDrag,CX,CY,W,H,boxL,boxR,boxT,boxB
local tmyOrigLoc, tTrackOn 

on mouseDown  
      put the loc of me into tmyOrigLoc 
    put true into tTrackOn 
    -- move it to the front so it is alway visible 
    set the layer of me to (the number of controls) 
  
# THE CLICK POSITION
  put (the mouseH - left of me) into CX
  put (the mouseV - top of me) into CY
  # WIDTH & HEIGHT OF THIS OBJECT
  put width of me into W
  put height of me into H
  # RECT OF THE CONSTRAINING BOX
  put item 1 of rect of grc boxlimit into boxL
  put item 3 of rect of grc boxlimit into boxR
  put item 2 of rect of grc boxlimit into boxT
  put item 4 of rect of grc boxlimit into boxB
  put true into allowDrag
end mouseDown

on mouseMove x,y
  if not allowDrag then exit mouseMove
  # DRAG ME
  set topLeft of me to \
      min(boxR - W,max(boxL,(x - CX))) & "," & min(boxB - H,max(boxT,(y - CY)))
 
end mouseMove

on mouseUp
  put false into allowDrag
  
     if tTrackOn then 
        put false into tTrackOn 
        send trackMe to me in 2 milliseconds 
    end if 
end mouseUp

on mouseRelease
  mouseUp
end mouseRelease

on trackMe 
    if not tTrackOn then 
        put the loc of me into tCurrentLoc 
        put "" into tMyNewLoc 
        put false into tFoundOne 
        put the short id of me into tmyID 
        repeat with i = 1 to the number of buttons 
            put the short id of button i into tanID 
            if tanId <> tmyId then 
                if intersect(button id tmyID, button id tanId) then 
                    put the loc of button id tanID into tMyNewLoc 
                    put true into tFoundOne 
                    exit repeat 
                end if 
            end if 
        end repeat 
        if tFoundOne then 
            -- a little animation 
            move button id tanID from tMyNewLoc to tmyOrigLoc without waiting 
            move me from tCurrentLoc to tMyNewLoc without waiting 
        else 
            move me from tCurrentLoc to tmyOrigLoc 
        end if 
    else 
        set the loc of me to the mouseloc 
    end if 
end trackMe
:)

Posted: Thu Apr 23, 2009 11:45 am
by bn
gyroscope,
I've amalgamated your code with the constraining code I originally found and it works just fine as well
That is cool. That is the way to go, find code and adapt it. Just before I was posting a revised version of my script that also made use of Scott Rossi's solution to constrain the movement of the button I saw your edit. Scott's solution is a lot sleeker then what I was up to. But then it is THE Scott. I often marvel at his visual effects.
One caveat with my script: The way you set it up now there is a flaw I introduced earlier. If a user clicks very fast into a moving button he might activate the script and permanently alter the location of the button.
The solution is to change all 'move' commands to 'move....without messages'. Without waiting makes for a synchronous movement, without messages locks the buttons from receiving mouseDown etc while they are moving. You might want to change that.

regards
Bernd

Posted: Thu Apr 23, 2009 6:10 pm
by gyroscope
...it is THE Scott. I often marvel at his visual effects.
As do I; Scott Rossi is a superb designer in my opinion. It didn't click though that it was the same person who wrote the particular bit of code I used...
The solution is to change all 'move' commands to 'move....without messages'.
Whoops! forgot that.

Thank you again for all of your help, Bernd.

:)