[REQ] Control selection during browse mode

LiveCode is the premier environment for creating multi-platform solutions for all major operating systems - Windows, Mac OS X, Linux, the Web, Server environments and Mobile platforms. Brand new to LiveCode? Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: [REQ] Control selection during browse mode

Post by dunbarx » Thu Dec 15, 2022 3:54 pm

Emily.

I uploaded the wrong version of the stack.

This one supports both the upperLeft and lowerRight corners. Can you add the other two?

Craig
noPointerTool.livecode.zip
(1.68 KiB) Downloaded 174 times

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7389
Joined: Sat Apr 08, 2006 8:31 pm
Contact:

Re: [REQ] Control selection during browse mode

Post by jacque » Thu Dec 15, 2022 7:32 pm

dunbarx wrote:
Wed Dec 14, 2022 6:08 pm
In any case, neither of those require that the control be selected. Or am I missing something?
How would the app know which control to rename or edit without selecting it first? The selection handles also provide feedback for the user.

I suspect Emily isn't a beginner and just needs some general direction. I recall some pretty sophisticated answers in previous topics.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: [REQ] Control selection during browse mode

Post by dunbarx » Thu Dec 15, 2022 8:00 pm

Jacque.

Emily wants only the browse tool.

If you select a control under script, er, control, the handles that appear do not allow the browse tool any interaction at all. The control is indeed selected, but not modifiable.

You may make a point that without selecting, the user only knows which control is in play by virtue of the proximity of the cursor. That is something that may well need to be addressed. Emily?

I do not know what experience Emily has. But with LC I believe she is a newbie.

Emily?

Craig

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10043
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: [REQ] Control selection during browse mode

Post by FourthWorld » Thu Dec 15, 2022 8:41 pm

dunbarx wrote:
Thu Dec 15, 2022 8:00 pm
Emily wants only the browse tool.
What she wants is to make a custom layout environment.

What she needs is two tool modes, Browse and Pointer, available at the same time depending on mouse location. If you've read her posts in the past, she's quite facile and very experienced in other languages and development in general. Given her demonstrated experience I feel confident that her priority here is more about finding an efficient solution than any personal preference for how to go about getting it.

With LC's limitation of having the tool property be only global (as opposed to assignable by group; see BZ#234), this requires us to decide whether we want the global property to be Browse with custom handling to allow Pointer behavior, or the other way around.

In my discussions on this with Dr Raney in '99 (I had freshly moved from SuperCard, where I made a LOT of custom layout environments, including an updated SampleDraw app they included in the package, like MacDraw but with more features), I had requested how Emily-Elizabeth initially conceptualized this: the global tool is Browse, with Pointer behavior somehow affecting only the drawing region.

What we got instead was the opposite, where we can use Pointer as the global tool mode, with any regions (groups or discrete controls) we like specifiable as delivering Browse tool behavior, by setting the cantSelect for those Browse regions to true.

While this is a bit less intuitive and much less convenient, I trust Dr Raney had good reason for making this implementation choice (sometimes what the engine needs to do to keep track of messaging is more complex than we want to know).

Regardless how it was arrived at, it is the solution the engine provides for mixing Browse and Pointer tool modes within a given window, and as such has been the recommended solution for most UIs of this type since it was introduced so long ago.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: [REQ] Control selection during browse mode

Post by dunbarx » Thu Dec 15, 2022 9:11 pm

@Richard, Jacque.

So I did a little research into Emily's posts here, and though having only 30, she does indeed seem to know a bit about LC. Further, the topics she is involved in are hardly beginners ones.

@Emily.
I owe you yet another apology.

That said, since the issues we are having here are UI issues, as opposed to strictly LC issues, where do we stand with getting this built and not breaking every protocol in the Apple HIG? :wink:

Craig

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: [REQ] Control selection during browse mode

Post by dunbarx » Thu Dec 15, 2022 9:16 pm

Richard.
What she needs is two tool modes, Browse and Pointer, available at the same time depending on mouse location
I think, assuming the scope does not increase dramatically, that all can be done with the browse tool. A simple click can bring up a dialog to change the text of the target, dragging near a corner can nicely resize, and clicking and dragging can set the loc.

Whether that is grown-up behavior is another story. But that sort of thing suits me just fine.

Craig

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: [REQ] Control selection during browse mode

Post by dunbarx » Thu Dec 15, 2022 11:08 pm

Just playing around, here is the latest stack using only the browse tool.

It resizes, moves and can set the text of the two fields present. It has nothing to do with the right way to do what it does.

Craig

Deleted, needed tiny upgrade...

And slightly updated:
noPointerTool.livecode.zip
(1.77 KiB) Downloaded 179 times
Last edited by dunbarx on Fri Dec 16, 2022 3:56 pm, edited 1 time in total.

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10043
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: [REQ] Control selection during browse mode

Post by FourthWorld » Fri Dec 16, 2022 1:57 am

dunbarx wrote:
Thu Dec 15, 2022 9:16 pm
Richard.
What she needs is two tool modes, Browse and Pointer, available at the same time depending on mouse location
I think, assuming the scope does not increase dramatically, that all can be done with the browse tool. A simple click can bring up a dialog to change the text of the target, dragging near a corner can nicely resize, and clicking and dragging can set the loc.
...and then there's the selection marquee, selection handles, etc.

If you need to ship something that does this you're free to do it however you like. I've shipped commercial products using the method the engine inventor provided for me.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

Emily-Elizabeth
Posts: 101
Joined: Mon Jan 03, 2022 7:10 pm

Re: [REQ] Control selection during browse mode

Post by Emily-Elizabeth » Fri Dec 16, 2022 4:41 am

Craig, thank you for all the work you have done, but as has been mentioned in this thread this is a "kludge" and it feels like it (no offence to your code, it's just the way it feels in LiveCode). Seeing as I wanted exactly what the pointer tool does, I kludged that in to doing what I needed it to do (also mentioned in this thread).

I appreciate everyone's hard work and discussion on the topic :-)

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: [REQ] Control selection during browse mode

Post by dunbarx » Fri Dec 16, 2022 4:55 am

Emily.

I like kludges because they are not in any box.

I do what I did for you strictly for fun and to push the borders.

But if you do now accept the pointer tool, what "kludge" did you need to, er, kludge something together?

Craig

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: [REQ] Control selection during browse mode

Post by dunbarx » Fri Dec 16, 2022 5:09 am

Emily and Richard. Possible Jacque.

I agree that a common process such as resizing ought to show some sort of indication as to the control of interest. My stack gadgetry does not, but recall that I am simply playing with the original restrictions set forth in the very title of this thread.

We already know that selecting objects under script control shows handles on those objects, though those handles are for show only, not accessible to the cursor for resizing. Who cares? Select as you will, and use my kludge to resize anyway.

Recall that I am doing this for fun and exercise; my guiding principle was no pointers. I am the one who mentioned kludges.

Emily, why did you decide to restrict the environment to the browse tool in the first place? You must have had some vision that set you down that path.

Craig

stam
Posts: 3061
Joined: Sun Jun 04, 2006 9:39 pm

Re: [REQ] Control selection during browse mode

Post by stam » Fri Dec 16, 2022 5:11 pm

I too have this requirement - to provide endusers with the possibility of creating custom cards/layouts, so have a vested interest in this.

I think I largely succeeded in emulating many aspects of the edit mode, but in browse mode. This is a first attempt and no doubt can be improved further but I'm happy that so far you can do the following in a more intuitive way (from the user's point of view):
- Click an object to select it, click the card to deselect
- grab the object to move it around
- grab any of the 8 drag markers to deform it in the chosen vector (ie topLeft, top, topRight, left, right, etc)
- change the cursor to reflect that you can either drag or resize if over a drag handle

The only thing I haven't yet done is to provide for multiple selections but think I'll have that done in the next day or so (actual real work permitting)

My setup has 4 components:
- a custom property on the card that informs whether or not we want to resize/reposition objects (the editControls of the card)
- a custom property on each object to identify it as something that can/should be resizable if the card is set to that mode (the isEditable of the object)
- a short card script that deselects all objects that may be selected; and also prepares fields to be selected (in default state these cannot be)
- a behaviour script that is assigned to the behaviour of any object we want to treat as resizeable - this is the meat of it.

the behaviour script basically checks to see if the clickLoc is within 4 pixels of any of the 8 drag handles or if it's in the 'body' of the object, changes cursor appropriately to give visual feedback of potential actions and either grabs or resizes according to which drag handle is dragged.

Code: Select all

local sRect, sClickAreasA, sClickedArea
/* clickareas array - clicking a drag handle will assign one of elements 1-8 to sClickedArea:
1: topLeft, 2: topCentre, 3: topRight
4: midLeft, 5: midRight
6: bottomLeft, 7: bottomCentre, 8: bottomRight
if the clickLoc is in none of the above then sClickedArea is 'grab' 
*/

on mouseDown
    if the editControls of this card then
        setClickable true
        put getClickLocation(the clickLoc) into sClickedArea
    end if
    if sClickedArea = "grab" then grab me
end mouseDown

command setClickable pMode // bool
    if pMode = true then
        if the uSelected of me then exit setClickable
        send "unSelectAll" to this card
        setCursor
        select me
        set the uSelected of me to true
    else
        if not the uSelected of me then exit setClickable
        resetCursor
        set the uSelected of me to false
    end if
end setClickable

command clearClickAreas // reset drag handle rect definitions
    put empty into sClickAreasA
end clearClickAreas

command setClickAreas // get a 9 pixel rect around each of the 8 drag handles
    lock screen
    set the rect of the templateGraphic to "0,0,9,9"
    set the style of the templateGraphic to "rectangle"
    set the visible of the templateGraphic to false
    create graphic "temp"
    reset the templateGraphic
    // 1 -  topleft
    set the loc of graphic "temp" to the topleft of me
    put the rect of graphic "temp" into sClickAreasA[1]
    // 2 - topCentre
    set the loc of graphic "temp" to item 1 of the loc of me, the top of me
    put the rect of graphic "temp" into sClickAreasA[2]
    // 3 - topRight
    set the loc of graphic "temp" to the topRight of me
    put the rect of graphic "temp" into sClickAreasA[3]
    // 4 - midLeft
    set the loc of graphic "temp" to the left of me, item 2 of the loc of me
    put the rect of graphic "temp" into sClickAreasA[4]
    // 5 - midRight
    set the loc of graphic "temp" to the right of me, item 2 of the loc of me
    put the rect of graphic "temp" into sClickAreasA[5]
    // 6 - bottomLeft
    set the loc of graphic "temp" to the bottomLeft of me
    put the rect of graphic "temp" into sClickAreasA[6]
    // 7 - bottomCentre
    set the loc of graphic "temp" to item 1 of the loc of me, the bottom of me
    put the rect of graphic "temp" into sClickAreasA[7]
    // 8 - bottomRight
    set the loc of graphic "temp" to the bottomRight of me
    put the rect of graphic "temp" into sClickAreasA[8]
    //
    delete graphic "temp"
end setClickAreas

function getClickLocation pClickLocation // define which drag handle is clicked
    local tLocation
    if pClickLocation is within sClickAreasA[1] then
        return "topLeft"
    else if pClickLocation is within sClickAreasA[2] then 
        return "topCentre"
    else if pClickLocation is within sClickAreasA[3] then
        return "topRight"
    else if pClickLocation is within sClickAreasA[4] then
        return "midLeft"
    else if pClickLocation is within  sClickAreasA[5] then
        return "midRight"
    else if pClickLocation is within sClickAreasA[6] then
        return "bottomLeft"
    else if pClickLocation is within sClickAreasA[7] then
        return "bottomCentre"
    else if pClickLocation is within sClickAreasA[8] then
        return "bottomRight"
    else
        return "grab"
    end if
end getClickLocation

on mouseEnter
    setClickAreas
    setCursor
end mouseEnter

command setCursor
    if not the editControls of this card then 
        resetcursor
        exit setCursor
    end if
    set the lockCursor to true
    set the cursor to hand
    repeat with x = 1 to 8
        if the mouseLoc is within sClickAreasA[x] and the uSelected of me then
            set the cursor to cross
            exit  repeat
        end if
        set the cursor to hand
    end repeat
end setCursor

command resetCursor
    set the lockCursor to false
    set the cursor to arrow
end resetCursor

on mouseMove
    setCursor
    if the mouse is down then
        local tRect
        lock screen
        put the rect of me into tRect
        if sClickedArea = "grab" then pass mouseMove
        switch sClickedArea
            case "topLeft"
                put item 1 of the mouseLoc into item 1 of tRect
                put item 2 of the mouseLoc into item 2 of tRect
                break
            case "topCentre"
                put item 2 of the mouseLoc into item 2 of tRect
                break
            case "topRight"
                put item 1 of the mouseLoc into item 3 of tRect
                put item 2 of the mouseLoc into item 2 of tRect
                break
            case "midleft"
                put item 1 of the mouseLoc into item 1 of tRect
                break
            case "midRight"
                put item 1 of the mouseLoc into item 3 of tRect
                break
            case "bottomLeft"
                put item 1 of the mouseLoc into item 1 of tRect
                put item 2 of the mouseLoc into item 4 of tRect
                break
            case "bottomCentre" 
                put item 2 of the mouseLoc into item 4 of tRect
                break
            case "bottomRight"
                put item 1 of the mouseLoc into item 3 of tRect
                put item 2 of the mouseLoc into item 4 of tRect
                break
        end switch
        set the rect of me to tRect
    end if
end mouseMove

on mouseLeave
   resetCursor
end mouseLeave
The card script has a command to deselect all objects and to prepare fields for selection as in browse mode you have to lock the text etc to make it selectable on click:

Code: Select all

on mouseDown
    unSelectAll
end mouseDown

command unSelectAll
    repeat with x = 1 to the number of controls of this card
        if the isEditable of control x of this card then
            dispatch "setClickable" to control x of this card with false
        end if
    end repeat
    select empty
end unSelectAll

command prepFields
    repeat with x = 1 to the number of fields
        if the isEditable of field x then
            set the traversalOn of field x to not the editControls of me
            set the lockText of field x to the editControls of me
        end if
    end repeat
end prepFields
Finally I have a toggle on the card to change it from non-editable to editable mode:

Code: Select all

on hiliteChanged
    set the editControls of this card to the hilite of me
    unselectAll
    prepFields
end hiliteChanged
Should be a minor change to allow shift-click for multiple selections. Seems to work well this far, but not very extensively tested...
test stack attached, the behaviour script is the script of a substack. Any object added to the card, and that should be resizeable needs to be given a custom property isEditable = true and be assigned the behaviour script, then should be editable directly in browse mode. No doubt this can be refactored further...

Regards
Stam
Attachments
editableControls.jpg
editableControls.livecode.zip
(2.8 KiB) Downloaded 172 times
Last edited by stam on Fri Dec 16, 2022 6:43 pm, edited 1 time in total.

Emily-Elizabeth
Posts: 101
Joined: Mon Jan 03, 2022 7:10 pm

Re: [REQ] Control selection during browse mode

Post by Emily-Elizabeth » Fri Dec 16, 2022 5:41 pm

Stam, nicely done :)

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10043
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: [REQ] Control selection during browse mode

Post by FourthWorld » Fri Dec 16, 2022 7:32 pm

It's possible to reproduce many engine-provided behaviors in a custom scripted implementation. We can also write our own amortization functions, craft our own HTTP handlers using sockets directly, and even create buttons from images if we like.

And I've done all of those. But rarely.

In each case I've asked myself what is the compelling benefit of taking on the expense of rolling my own rather than just using what's provided in the box for the purpose.

It varies from app to app. Most of the time I generally avoid reinventing provided wheels. But there are times when I've had to increase costs by choosing to craft a custom implementation because of some nuance not provided in the engine-based solution. I weigh such decisions very carefully, having been in this biz long enough to know the protracted cost of technical debt.

In this discussion of emulating built-in tool modes that have been a foundational part of xTalks since HC 1.0, it may be worth reviewing one of the more complete implementations I've ever seen in our community, Ken Ray's Stykz:

https://www.stykz.net

I was in touch with Ken throughout much of that development process, and can answer many questions about how he pulled it off, and why. And for anything I can't answer I can see if he can spare a moment to drop in here if needed.

For the WHY of his pointer tool implementation, at the heart of that decision was inverse kinematics. Stykz makes stick figure animations, and doing so efficiently requires the underlying code to maintain relationships between the parts of a figure (forearm connected to upper arm, shoulder to torso, etc.). When moving a selected part of a figure, app-specific intelligence is needed to maintain the figure's functional integrity.

Obviously that's far beyond what the humble Pointer tool does, since the built-in tool mode was designed to provide only behaviors of the sort we commonly see in drawing apps like MacDraw, Illustrator, Inkscape, etc.

So given the highly specialized needs of his app, Ken bit the bullet hard, and crafted one of the finest Pointer tool emulations I've ever seen.

For the HOW of it, he maintains multiple groups for each control. Some include the parts of the stick figure itself, grouped in ways that make the logic of linking their kinematics manageable.

Another set of groups is used to maintain the selection handles, one set of handles per object, where each handle is a graphic object. These are within a master group both to show/hide them easily, but mostly to keep the handles on top in the layer order, so that no figure element obscures use of a handle.

The selection marquee is done as you'd expect, a rectangle graphic object shown when the mouse is down outside of any control and moved beyond a reasonable slop rect to distinguish drags from clicks. When the mouse is eventually released, the code compares the rect of the marquee graphic to every user-made object to determine intersection, and then shows the selection handle group for that object (or set of objects, since many things users interact with in Stykz as a single object are implementated under the hood as a collection of objects in a group).

There are other details, but this at least provides an overview of the sort of things we will encounter when we choose to reproduce engine-provided behavior in bespoke script.

Given the level of effort needed to meet user expectations for something as common as a Pointer tool mode, maybe the most valuable part of this outline is the depth he explored first before attempting this. Only when all engine-provided solutions were identified as insufficient for the needs of this specific app did he decide to undertake the considerable effort to reproduce in script what the engine team worked so hard for so long to provide for us.

Ken and I sometimes joke about making t-shirts that read:

Know the engine.
Trust the engine.
Use the engine.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

stam
Posts: 3061
Joined: Sun Jun 04, 2006 9:39 pm

Re: [REQ] Control selection during browse mode

Post by stam » Fri Dec 16, 2022 9:18 pm

Thanks Richard - always enjoy your insights and anecdotes.

But now I’m confused - is it possible to use the pointer tool in standalone? If that’s the case I definitely would use that and not bother rolling my own!

It never crossed my mind to try using pointer tool in a standalone as it always appeared to be a IDE tool to me, but will definitely try that if you say that’s possible!

S.

Post Reply