[Closed] Help with spinner using "with undo"
Just putting together a little script that manipulates various properties of a selected camera and want to be able to undo changes made by the spinners.
Sample code:
on spn_TargetDist buttondown do with undo "Target distance" on
(
If currentcam.type == #target then Currentcam.targetdistance = spn_TargetDist.value
else Currentcam.target_distance = spn_TargetDist.value
)
On spn_TargetDist changed val do
(
If currentcam.type == #target then Currentcam.targetdistance = val
else Currentcam.target_distance = val
)
This works as expected if the value of spinner “spn_TargetDist” is changed by “Spinning” the spinner, however manually entering a value does not generate any undo blocks.
My next logical step was to put with undo into the changed val event.
on spn_TargetDist buttondown do with undo "Target distance" on
(
If currentcam.type == #target then Currentcam.targetdistance = spn_TargetDist.value
else Currentcam.target_distance = spn_TargetDist.value
)
On spn_TargetDist changed val do with undo "Target distance" on
(
If currentcam.type == #target then Currentcam.targetdistance = val
else Currentcam.target_distance = val
)
This fixed the manually entered values, however “spinning” the spinner will generate hundreds of undo blocks due to obviously the On changed event constantly updating while dragging the mouse.
I have tried using an on entered event but this only generates an undo block once the value has been inputted and user pressed enter.
Is there a simple workaround to this problem ? Many thanks in advance.
D.
Hi David,
Take a look into using theHold
You can call
if not thehold.holding() then thehold.begin()
in the spinner button down event,
and then in the spinner buttonup event –
TheHold.accept <Undo List string>
with this you can capture a block of code operations into one Undo entry.
try(destroydialog dialog) catch()
rollout dialog "" width:200
(
spinner sp "Target Distance: " fieldwidth:56 range:[0.0001,1e9,0]
local cam
fn setDistance value:sp.value = if iskindof cam Camera do (cam.targetdistance = value)
on sp buttondown do undo "Set Value" on setDistance value:cam.targetdistance
on sp changed v do setDistance()
on dialog open do
(
delete objects
cam = targetcamera target:(targetObject())
sp.value = cam.targetdistance = 100
gc() -- start new undo session
)
)
createdialog dialog
is it what you are looking for?
PS. using theHold is a good idea!
Thanks for all your suggestions, I wasn’t aware of the thehold feature so I am sure I can make good use of that in the future. I tried thehold in the buttondown/up events and this worked as a nice alternative for “spinning” the spinners however still hasn’t resolved manually entered values.
The source of the problem I can see is that clicking in the spinners dialog, to manually enter a value, doesn’t seem to constitute a buttondown event? Is there an event that can recognise when the user clicks in the spinners dialog pre entering a new value?
you do have an entered event, you could use the undo context for that event, and thehold to capture the multiple spinner ‘twiddle’, for want of a better word.
try(destroydialog dialog) catch()
rollout dialog "" width:200
(
spinner sp "Target Distance: " fieldwidth:56 range:[0.0001,1e9,0]
local cam
fn setDistance value:sp.value = if iskindof cam Camera do (cam.targetdistance = value)
on sp buttondown do undo "Set Value(spin)" on setDistance value:cam.targetdistance
on sp changed v do setDistance()
on sp entered spin cancel do undo "Set Value(enter)" on if not spin and not cancel do setDistance()
on dialog open do
(
delete objects
cam = targetcamera target:(targetObject())
sp.value = cam.targetdistance = 100
gc() -- start new undo session
)
)
createdialog dialog
does it solve the problem now?