Moving and expanding Text Field Objects

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

Post Reply
cdev007
Posts: 11
Joined: Sun Oct 04, 2020 7:41 pm

Moving and expanding Text Field Objects

Post by cdev007 » Sun Oct 04, 2020 7:57 pm

I am wanting to be able to move around some text fields and/or resize them then depending on where they are, snap into place. I have a bunch of vertical lines (whose left edge is in an array called vertsepleft) which designate the areas where the text fields need to be bounded by. The problem is that after moving around a field and then resizing it, it will sometimes randomly move part of the way across the stack to either the left or right or shrink really small. This is frustrating as I cannot figure out why it is doing this.

Here is my code (I have several fields which are grouped together into group "LettersinFields" and where this code resides.

(I'm going to add code to make it so the fields cannot overlap and so the bottom of them line up but haven't done so yet. Also I've added a little unnecessary code in efforts to try and figure out what's wrong).



global rleft
global rright
global rwidth
global rchangepos
global lchangepos
global fldname
global itsgrabbed
global clickedonfld
global vertsepleft


on mousedown
if the first word of the name of the target = "field" then
put true into clickedonfld
put the name of the target into fldname
put the left of fldname into rleft
put the right of fldname into rright
put the width of fldname into rwidth
if rright - (item 1 of the mouseloc) < 33 then
put true into rchangepos
end if
if (item 1 of the mouseloc) - rleft < 33 then
put true into lchangepos
end if
if rright - (item 1 of the mouseloc) > 33 and (item 1 of the mouseloc) - rleft > 33 then
grab the target
put true into itsgrabbed
end if
end if
end mousedown


on mousemove
if rchangepos or lchangepos then
put item 1 of the mouseloc into tmouseloc
if rchangepos then
put tmouseloc - rright into newpos
set the width of fldname to rwidth + newpos
set the left of fldname to rleft
end if
if lchangepos then
put rleft - tmouseloc into newpos
set the width of fldname to rwidth + newpos
set the right of fldname to rright
end if
end if
end mousemove

on mouseup
makegoodwidth
end mouseup


on mouserelease
makegoodwidth
end mouserelease


on makegoodwidth
if clickedonfld then
put false into rchangepos
put false into lchangepos
put false into clickedonfld
put false into itsgrabbed
put empty into snapfield
put empty into stayleft
if the width of fldname <= 50 then
set the width of fldname to 74
end if
repeat with i = 1 to the number of lines in the keys of vertsepleft
put abs(item 1 of the mouseloc - vertsepleft) & "," after snapfield
end repeat
put itemoffset(min(snapfield),snapfield) into sdfsdf
put vertsepleft[sdfsdf] + 2 into stayleft
set the left of fldname to stayleft
repeat with i = 1 to the number of lines in the keys of vertsepleft
put abs(the right of fldname - vertsepleft) & "," after snapfield1
put vertsepleft - the right of fldname & "," after snapfield2
end repeat
set the width of fldname to the width of fldname + item (itemoffset(min(snapfield1),snapfield1)) of snapfield2
set the left of fldname to stayleft
end if
end makegoodwidth

richmond62
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 9386
Joined: Fri Feb 19, 2010 10:17 am
Location: Bulgaria

Re: Moving and expanding Text Field Objects

Post by richmond62 » Sun Oct 04, 2020 8:05 pm

That's very difficult to understand outwith the context of the stack.

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9663
Joined: Wed May 06, 2009 2:28 pm
Location: New York, NY

Re: Moving and expanding Text Field Objects

Post by dunbarx » Sun Oct 04, 2020 11:37 pm

What Richmond said.

The good news is that your handlers do not throw an error, but there is no way to help you without that context.

The symptoms you describe do not happen on their own. This could simply be the order in which you do things. For example, if you set the location of a control adjacent to one of those reference lines you mentioned, and then resize it, the control will expand or shrink, but still centered around the original loc. This will move it "off" of the reference line. That sort of thing.

You obviously have a good grasp of LC. Your code is verbose, but that is to be expected with new users. This is not a criticism; you will write much more compactly as you learn LC. If we can work through your current offering, I bet we can cut in half the number of required lines, and get rid of those globals. I am not being glib. That also was not a criticism. Really.

Also, please enclose your code inside the code tags ("</>"). It makes them so much more readable and accessible.

Craig

jiml
Posts: 336
Joined: Sat Dec 09, 2006 1:27 am
Location: Los Angeles

Re: Moving and expanding Text Field Objects

Post by jiml » Mon Oct 05, 2020 7:49 pm

would you supply us with an example of the data in array vertsepleft?

Xero
Posts: 152
Joined: Sat Jun 23, 2018 2:22 pm

Re: Moving and expanding Text Field Objects

Post by Xero » Tue Oct 06, 2020 6:39 am

I have had a load of trouble with objects of all kinds when moving AND resizing.
What Craig says holds true.
The object (field) is moved by it's anchor point unless you tell it otherwise. Objects are resized around their anchor point. The left, right, top and bottom will move when resizing, so you need to resize then set the location. It looks like you're doing this in your code, but you end up doing it twice in your final code when you say:

Code: Select all

set the left of fldname to stayleft

This happens twice in the same piece of code. I am sure there is a much easier way of working out where the left and right edges should be (set the width to this value, then set the left, top, whatever- to what it needs to be.
Resize, then move...
So I would check the order too.
XdM

AxWald
Posts: 578
Joined: Thu Mar 06, 2014 2:57 pm

Re: Moving and expanding Text Field Objects

Post by AxWald » Tue Oct 06, 2020 12:49 pm

Hi,

as Xero said. It's essential to do things in the correct order:
  1. Set the dimensions (using height & width)
  2. Determine horizontal & vertical location (using whatever suits you)
  3. Set horizontal location (using left or right), and vertical location (using top or bottom)
Besides, your code looks unnecessarily convoluted. I just happen to have a stack handy where I do a rather similar task - I adjust draggable buttons to a grid.
This grid I create at first use, save it to a custom property, and use from there.
The "moving code" of my buttons is in a behavior button shared by all moving buttons.
Still, each of them has its own "realMouseUp" handler ;-)

It's very simple - no collision detection, no size change, always adjusts to left/ top. I wrote it once to get my head wrapped around the principles - but it's well commented & may give you some ideas.
(If it doesn't work, use the "Set Behav.!" button to renew the behaviors!)

Have fun!
Attachments
awaGridDrag.zip
drag around the grid ...
(2.27 KiB) Downloaded 152 times
All code published by me here was created with Community Editions of LC (thus is GPLv3).
If you use it in closed source projects, or for the Apple AppStore, or with XCode
you'll violate some license terms - read your relevant EULAs & Licenses!

cdev007
Posts: 11
Joined: Sun Oct 04, 2020 7:41 pm

Re: Moving and expanding Text Field Objects

Post by cdev007 » Wed Oct 07, 2020 11:42 pm

Wow thanks everyone!

And thanks AxWald! Unfortunately this forum said that I didn't have permission to view the file you posted. Is there another way for me to get this?

I'm going to see if I can get AxWald's stack, so you no need to reply more in case you want my global vertsepleft variable, here it is.

</>
put 48 into vertsepleft[1]
put 122 into vertsepleft[2]
put 269 into vertsepleft[3]
put 343 into vertsepleft[4]
put 196 into vertsepleft[5]
put 417 into vertsepleft[6]
put 491 into vertsepleft[7]
put 564 into vertsepleft[8]
put 638 into vertsepleft[9]
put 712 into vertsepleft[10]
put 786 into vertsepleft[11]
put 859 into vertsepleft[12]
put 933 into vertsepleft[13]
put 1007 into vertsepleft[14]
</>




[edit]

I just realized that one reason it may be doing that is because I didn't have it sort my numbers from lowest to highest before putting them into an array. vertsepleft[5] is way out of order.

AxWald
Posts: 578
Joined: Thu Mar 06, 2014 2:57 pm

Re: Moving and expanding Text Field Objects

Post by AxWald » Thu Oct 08, 2020 12:12 pm

Hmm,

I can DL the demo stack w/o problems. Anyways, it's quite simple, here's the code & how to make:

I created a stack, and 1 button (You may have more btns, too ;-)) )
Script of the card:

Code: Select all

constant kHGrid = 20                                                       --  measurements of grid
constant kVGrid = 20

function calcNewLoc theRect
   --  at first, calculate size as you desire it
   --     I don't do anything here, too lazy :) 
   put (item 3 of theRect) - (item 1 of theRect) into myWidth                  --  loading variables
   put (item 4 of theRect) - (item 2 of theRect) into myHeight
   put item 1 of theRect into myLeft
   put item 2 of theRect into myTop
   
   put the cGridArr of this cd into myGridArr                                           -- load array
   --  now we check for a suitable left:
   --     I'm fitting the object to the grid using
   --     left-to-right/ top-to-bottom orientation
   repeat with i = 1 to the number of items of myGridArr["HVals"]           -- calculate horizontal
      if item i of myGridArr["HVals"] > myLeft then
         put item i -1 of myGridArr["HVals"] into myH
         exit repeat
      end if
   end repeat
   --  now myH is the next grid to the left
   
   repeat with i = 1 to the number of items of myGridArr["VVals"]              -- calculate vertical
      if item i of myGridArr["VVals"] > myTop then
         put item i -1 of myGridArr["VVals"] into myV
         exit repeat
      end if
   end repeat
   --  now myV is the next grid above
   --  and we adjust the new rect:
   return myH & comma & myV & comma & \                                    -- return resulting rect
   myH + myWidth & comma & myV + myHeight
end calcNewLoc

on makeGridArr                                                            --  create the basic grid
   put 0 into myH
   put 0 into myV
   
   repeat                                                                      --  horizontal values
      if the controlKey is down then exit repeat
      put myH + kHGrid into myVar
      if myVar > the width of this cd then exit repeat
      put myVar & comma after myHGrid
      put myVar into myH
   end repeat
   put 0 & comma before myHGrid
   delete char -1 of of myHGrid
   --  you may want to add [the right of this cd] for
   --  horizontal right-to-left orientation ...
   
   repeat
      if the controlKey is down then exit repeat                                --  vertical values
      put myV + kVGrid into myVar
      if myVar > the height of this cd then exit repeat
      put myVar & comma after myVGrid
      put myVar into myV
   end repeat
   put 0 & comma before myVGrid
   delete char -1 of of myVGrid
   --  you may want to add [the bottom of this cd] for
   --  vertical bottom-to-top orientation ...
   
   --  Or you may even want to add 2 more entries for
   --  nice right-to-left/ bottom-to-top orientation ...
   
   put myHGrid into myGridArr["HVals"]
   put myVGrid into myGridArr["VVals"]
   set the cGridArr of this cd to myGridArr                  -- create array & stash it in a cProp
end makeGridArr
Here are 2 constants (kHGrid & kVGrid) - these are used to calculate the horizontal & vertical grid lines. This is done with "on makeGridArr", a handler that creates a simple grid based on the constants & the measures of the card.
The result is an array in a customProp "the cGridArr of this cd". The array has 2 keys (HVals & VVals), each a sorted list of points (0,20,40,60 ...).
"CalcNewLoc" is explained below.

The handlers in the button(s):

Code: Select all

local lastLoc, isMove
constant kMinMove = 20                                             -- how far to move to register?

on mouseDown
   put the loc of me into lastLoc                                               --  start monitoring
   put true into isMove
   set the loc of me to the mouseLoc
end mouseDown

on mouseMove
   if isMove then
      set the loc of me to the mouseLoc                                                    -- move it!
   else
      pass mouseMove
   end if
end mouseMove

on mouseUp
   put false into isMove                                                          -- reset monitoring
   put the loc of me into myLoc
   if the cGridArr of this cd is empty then makeGridArr              -- make sure we have the grid!
   
   if not (the mouseLoc is within the rect of this cd) then \            -- released outside cd rect
      set the loc of me to lastLoc                                                      -- so reset it
   else if ((abs(item 1 of lastLoc - item 1 of myLoc) > kMinMove) OR \         -- dragged sufficient
   (abs(item 2 of lastLoc - item 2 of myLoc) > kMinMove)) then                   -- width, so a drag
      set the rect of me to CalcNewLoc(the rect of me)                       -- thus ask for new loc
   else                                                                  --  must be a real mouseUp!
      dispatch "realMouseUp" to the target                                      -- so tell it about!
      set the loc of me to lastLoc                                                   -- and reset loc
   end if
end mouseUp

on realmouseUp
   answer "I'm button '" & the short name of me & "', and you clicked me!"
end realmouseUp
Another constant, "kMinMove" - this is how far we need to drag that it is considered a valid drag. The script local variables are used in the code. Then:

"MouseDown" starts the tracking, "MouseMove" moves it, "MouseUp" does more:
  • Stops the tracking
  • creates the grid if there isn't one yet
  • checks if we're within the card (else resets the btn pos)
  • checks if we dragged wide enough (else resets btn pos)
  • calls function "CalcNewLoc(the rect of me)" to get the new position
  • sets the new position
  • and if we haven't moved, determines its a real mouseUp & calls "realMouseUp" ;-)))
In "CalcNewLoc()" the actual positioning is done. Would I need to adjust the size, I'd do it at the very beginning of it. Then I load some variables (myWidth, myHeight, myLeft, myTop) as well as the GridArray, and calculate first the horizontal, then the vertical position. And return the resulting rect.

In my demo stack I had the btn code in a behavior, thus the buttons itself had no code of their own. If you don't do this, just copy the code into anything that needs dragging ;-)
This works with (locked!) fields as well, btw.

Have fun!
All code published by me here was created with Community Editions of LC (thus is GPLv3).
If you use it in closed source projects, or for the Apple AppStore, or with XCode
you'll violate some license terms - read your relevant EULAs & Licenses!

Post Reply

Return to “Getting Started with LiveCode - Complete Beginners”