reordering lists ( a bit long, sorry)
Martin Baxter
martin at atwork.bdx.co.uk
Wed Feb 27 12:13:00 EST 2002
After investigation I conclude that, it is setting the hilitedline[s] from
a script that has the side effect of vertically centering the line.
The transcript dictionary doesn't mention it affecting the scroll at all
never mind this 'eccentric centering' behaviour (if one can say such a
thing), which is a shame as it would have saved me at least half a day of
headscratching and futile workarounds had I reallised that to begin with.
Incidentally, the HC compatible "select line x of ..." construct, doesn't
exhibit this centering behaviour, instead, if necessaary it scrolls so that
the selected line is the first or last visible line, exactly what I would
ordinarily expect.
The transcript dictionary pleads with us to use the hilitedline instead,
but doesn't point out that the behaviour of the two constructs is
functionally different.
---
Why would I care? The short answer to that question would most likely only
generate more questions so bear with me if you please, and Consider...
I want to make a list field that allows me to reorder single lines by
dragging them from place to place with the mouse. I want the drag to be
constrained to that field only, - not field to field. Is this an
unreasonable desire ? I don't think so, no, it's commonly done and I don't
know any other way to reorder lists apart from clicky buttons, which are a
bit too "eighties darling" for my liking, i.e. perhaps they were
appropriate back in the days when our computers ran at the speed of treacle.
This "dragreorderable list" behaviour is not provided for in the product at
present, so I take what looks like the nearest available interface element
and try to script it so it does what I want.
---
What is supposed to happen? -- (please skip this if you already know)
1) mousedown on a list line, it hilites
2) drag the mouse - the originally clicked line remains hilited, other
lines remain unhilited. - a graphic looking like a peeled off selection
appears and follows the mouse pointer, with the graphic's movement
constrained to the visible area of the field and the vertical axis.
3) If the mouse pointer goes outside the field boudary, the field scrolls
to bring any invisible lines into view, leaving the line hiliting alone of
course.
4) when the mouse is released, the graphics disappear, the originally
clicked line is moved to between the list lines where the mouse release
occurred and the original line is deleted.
5) the newly inserted line is left hilited, and in the same place it was
when the mouse button was released.
---
And what does happen when you try to achieve this?
(or: "a day or 2 in the life of Mr. Average-scripter-guy")
1) OK, so far so so good
2) you drag the mouse. You've written a mousemove handler that displays
your graphics, that's fine. But dragging the mouse also changes the
hilitedline of course, which is not what you want.
So you think ok, I'll just reset the hilitedline back to the original line
every time I get a mousemove.
This is OK I suppose except that you discover that setting the hilitedline
insists on scrolling scroll the field for you, so that the line you have
just re-hilited is vertically centred, even if the line in question was
already visible.
So you think OK I'll reset the scroll as well after I set the hilitedline.
You gnash your teeth though because it occurs to you that if setting the
hilitedline only affected the scroll when the affected line was actually
invisible, it would be much less of a problem because you would at least be
able to test whether the originally clicked line is currently visible or
not, and skip setting its hilite if doing so would also cause a scroll to
bring it back into view.
The resulting fight between the component and the script looks flickery and
feels odd to use, though it's not yet actually disastrous.
3) then the mouse pointer is dragged beyond the field boundary. Probably
because the hilitedline is not next to the field boundary, the listfield
perceives no need to scroll itself in response to the mouse leaving its
rect, and sits there stubbornly doing nothing.
So you start to script the field scrolling as well, at which point you are:
setting the scroll, and sometimes setting the hilitedline as well, which of
course wants to set the scroll according to its own assumptions of what is
reasonable to do. Apparently what I'm trying to do is unreasonable.
4) After some tense mouse moves, you get the pointer where you want it and
release the mouse. Sadly you move the mouse ever so slightly as you do so,
triggering a change of the hilitedline, and therefore a dramatic
re-scrolling of the field so that your moved line ends up being put in
entirely the wrong place.
5) the new line is set to be the hilitedline which of course scrolls it to
be at the vertical centre of the field, appearing to the user to spring
away from his/her mousepointer as if stung. They think to themselves "did I
do something wrong?"
As you can see, most of the above is about trying to script a way around
the automatic behaviour of a listfield, because the interface behaviour I
want doesn't seem to have been allowed for in the design of the components
available to me.
---
So OK, it doesn't work, try another approach then.
It occurs to me that the hypercard syntax surely didn't work like that, and
if it is truly compatible here, it should work the same - right? Right! -
so now I know a way to hilite a listline without causing it to always
scroll to centre, even though I'm warned that using it is naughty, and
personally I'm all in favour of migrating from deprecated constructs, it's
just that currently I'm not in the mood to care.
Also I reflect that I've gone way beyond just scripting a behaviour, I'm
also scripting a way around a preset behaviour that's undesirable to me.
Can't I turn off the preset behaviour?
Well yes, I can turn off listbehaviour and autohiliting, but then I don't
get the full-width hilite of a selected list-line any more, plus I would
have to work out the clickline and clicktext for myself as well. which is
all a bit depressing.
---
Finally I conceive a way to (just about) achieve what I want, I'd hesitate
to distribute it to others, but it works OK for "home use" at least. Maybe
it'll get worked on and improved.
1) mousedown - get the clickline and clicktext - display a hidden field
that "looks like" the selected line, in the position of the actual listline
- set the hilitedline to 0 and then turn off autohiliting and therefore
listbehavior.
2) mousemove - draw the graphics, scroll the field, move the fake selected
line in sync with the field scroll and hide it when the selected line
scrolls out of view
3) mouseup/mouserelease - move the dragged line if appropriate - hide all
the graphics - turn autohiliting and listbehavior back on - use "select
line x of field..." to hilite the moved line, without having it leap to
field centre. Feel smug, after all I beat the house.
Basically, the listbehavior helps me click and select a particular line in
the fashion of a list, but thereafter its just in the way of what I want to
do, so I have to turn it off, and resort to a nasty kludge to preserve the
'appearance' of a selected listline. Not so revolutionary, eh?
---
what would have made life easier ? - Well, my uninformed and maybe also
naive 2 pesetas worth of suggestions would be:
a) A listfield that could be configured to do this all by itself. - that
would be nice.
b) A way to configure a listfield so that you could hilite and click a
visible line in the usual manner of a list, but which either: ignored mouse
drags, and therefore would only scroll if you used its scrollbar or
scripted it, like a sort of locked textfield with 'list field like'
line-hiliting and click selecting i guess, or which: could be drag-scrolled
without losing the originally selected line (i.e. the line that was under
mousedown).
c) setting the hilitedline worked in the exact same way that: "select line
x of field y" does.
d) an additional parameter to "set the hilitedline of field x to n" such
as: "without scroll" - the result would be a hilitedline that might perhaps
be out of view, such as 'appears to happen' when you use the scrollbar.
While this is perhaps trivial, even superficially pointless, had it been
possible it wouldn't have taken me 3 days to reinvent this 'drag-reordered
list' wheel.
Sorry again for such a long post,
martin baxter
More information about the use-livecode
mailing list