[Closed] Docking Dialogs
Hi
I wrote a tiny test script for docking dialogs and it works quite well, sometimes I get an infinite loop but this is no big deal.
How it works:
I create several dialogs and each time the user moved them, a function checks, if it is near another dialog, if so, it snaps the dragged dialog to them.
If the user snaps to the main dialog, he can drag all docked dialogs when moving it.
This all works quite promising, but the more dialogs you dock, the slower it gets
Is there a way to speed this up?
Here is the code:
try
(
for i = 1 to rolloutList.count do
try destroyDialog rolloutList[i].RO catch()
)
catch()
struct ROStruct
(
parent,
docked = false,
offsetPos = [0,0],
RO
)
global ROMOVING = false
function moveDockedRO =
(
global ROMOVING = true
try
(
for i = 1 to rolloutList.count do
(
local parentRO = getParentRO rolloutList[i].RO.name
if parentRO != undefined then
(
setDialogPos rolloutList[i].RO ((getDialogPos rolloutList[rolloutList.count].RO) + rolloutList[i].offsetPos)
)
)
)catch()
global ROMOVING = false
)
function getParentRO dialogName =
(
local thisRO = ""
for i = 1 to rolloutList.count do
if rolloutList[i].RO.name == dialogName then
thisRO = rolloutList[i]
if thisRO.docked == false then
return undefined
local tempParent = thisRO.parent
while tempParent.parent != undefined do
(
enableEscape = true
tempParent = tempParent.parent
)
if tempParent.RO.name == "mainRO" then
return tempParent
return undefined
)
function dockDialog dialogName =
(
if ROMOVING == true then
return undefined
local thisRO = ""
for i = 1 to rolloutList.count do
if rolloutList[i].RO.name == dialogName then
thisRO = rolloutList[i]
thisRO.docked = false
thisRO.parent = undefined
for i = 1 to rolloutList.count do
(
local thisPos = getDialogPos thisRO.RO
local ROPos = getDialogPos rolloutList[i].RO
local thisSize = getDialogSize thisRO.RO
local ROSize = getDialogSize rolloutList[i].RO
if rolloutList[i].RO.name != thisRO.RO.name then
(
--// dock left
--// left, right pos
if ((thisPos[1] + thisSize[1]) > ROPos[1] - 10) and ((thisPos[1] + thisSize[1]) < ROPos[1]) then
(
--// up, down pos
if ((thisPos[2] > ROPos[2] - 10) and (thisPos[2] < ROPos[2] + 10)) then
(
local newPos = ROPos
newPos[1] = ROPos[1] - thisSize[1] - 5
if rolloutList[i].RO.name == "mainRO" then
newPos[2] = ROPos[2] + 3
setDialogPos thisRO.RO newPos
thisRO.parent = rolloutList[i]
thisRO.docked = true
local parentRO = (getParentRO thisRO.RO.name)
if parentRO != undefined then
thisRO.offsetPos = (getDialogPos thisRO.RO) - (getDialogPos parentRO.RO)
else
thisRO.offsetPos = [0,0]
break
)
)
--// dock right
--// left, right pos
if (thisPos[1] > (ROPos[1] + ROSize[1] )) and (thisPos[1] < (ROPos[1] + ROSize[1] + 10)) then
(
--// up, down pos
if ((thisPos[2] > ROPos[2] - 10) and (thisPos[2] < ROPos[2] + 10)) then
(
local newPos = ROPos
newPos[1] = ROPos[1] + ROSize[1] + 5
if rolloutList[i].RO.name == "mainRO" then
newPos[2] = ROPos[2] + 3
setDialogPos thisRO.RO newPos
thisRO.parent = rolloutList[i]
thisRO.docked = true
local parentRO = (getParentRO thisRO.RO.name)
if parentRO != undefined then
thisRO.offsetPos = (getDialogPos thisRO.RO) - (getDialogPos parentRO.RO)
else
thisRO.offsetPos = [0,0]
break
)
)
--// dock up
--// left, right pos
if (thisPos[1] > ROPos[1] - 10) and ((thisPos[1] + thisSize[1]) < (ROPos[1] + ROSize[1] + 10)) then
(
--// up, down pos
if ((thisPos[2] + thisSize[2] > ROPos[2] - 25) and (thisPos[2] + thisSize[2] < ROPos[2] - 15)) then
(
local newPos = ROPos
if rolloutList[i].RO.name == "mainRO" then
newPos[2] = ROPos[2] - thisSize[2] - 20
else
newPos[2] = ROPos[2] - thisSize[2] - 24
if (thisPos[1] + thisSize[1]) < (ROPos[1] + ROSize[1] + 10) and thisPos[1] + thisSize[1] > (ROPos[1] + ROSize[1] - 10) then
newPos[1] = ROPos[1] + ROSize[1] - thisSize[1]
if (thisPos[1] >= ROPos[1] + 10) and ((thisPos[1] + thisSize[1]) <= (ROPos[1] + ROSize[1] - 10)) then
newPos[1] = thisPos[1]
setDialogPos thisRO.RO newPos
thisRO.parent = rolloutList[i]
thisRO.docked = true
local parentRO = (getParentRO thisRO.RO.name)
if parentRO != undefined then
thisRO.offsetPos = (getDialogPos thisRO.RO) - (getDialogPos parentRO.RO)
else
thisRO.offsetPos = [0,0]
break
)
)
--// dock down
--// left, right pos
if (thisPos[1] > ROPos[1] - 10) and ((thisPos[1] + thisSize[1]) < (ROPos[1] + ROSize[1] + 10)) then
(
--// up, down pos
if (thisPos[2] > (ROPos[2] + ROSize[2] + 20)) and (thisPos[2] < (ROPos[2] + ROSize[2] + 30)) then
(
local newPos = ROPos
if rolloutList[i].RO.name == "mainRO" then
newPos[2] = ROPos[2] + ROSize[2] + 26
else
newPos[2] = ROPos[2] + ROSize[2] + 24
if (thisPos[1] + thisSize[1]) < (ROPos[1] + ROSize[1] + 10) and thisPos[1] + thisSize[1] > (ROPos[1] + ROSize[1] - 10) then
newPos[1] = ROPos[1] + ROSize[1] - thisSize[1]
if (thisPos[1] >= ROPos[1] + 10) and ((thisPos[1] + thisSize[1]) <= (ROPos[1] + ROSize[1] - 10)) then
newPos[1] = thisPos[1]
setDialogPos thisRO.RO newPos
thisRO.parent = rolloutList[i]
thisRO.docked = true
local parentRO = (getParentRO thisRO.RO.name)
if parentRO != undefined then
thisRO.offsetPos = (getDialogPos thisRO.RO) - (getDialogPos parentRO.RO)
else
thisRO.offsetPos = [0,0]
break
)
)
)
)
)
global rolloutList = #()
rollout test1RO "UpperLeft"
(
label labDesc "UpperLeft"
on test1RO moved value do
(
dockDialog "test1RO"
)
)
rollout test2RO "UpperMiddle"
(
label labDesc "UpperMiddle"
on test2RO moved value do
(
dockDialog "test2RO"
)
)
rollout test3RO "UpperRight"
(
label labDesc "UpperRight"
on test3RO moved value do
(
dockDialog "test3RO"
)
)
rollout mainRO "mainRO"
(
on mainRO moved value do
(
moveDockedRO()
)
)
append rolloutList (ROStruct RO:test1RO)
append rolloutList (ROStruct RO:test2RO)
append rolloutList (ROStruct RO:test3RO)
append rolloutList (ROStruct RO:mainRO)
for i = 1 to (rolloutList.count - 1) do
createDialog rolloutList[i].RO 100 100 style:#(#style_toolwindow, #style_sysmenu )
createDialog mainRO 310 0
cool
might have a scoping issue as it throws an error on first run:
-- Error occurred in dockDialog(); filename: ; position: 1393
-- Frame:
-- thisRO: ""
-- rolloutList: undefined
-- dialogName: "test3RO"
-- called in test3RO.moved(); filename: ; position: 6405
-- Frame:
-- value: [583,343]
>> MAXScript Rollout Handler Exception: -- Unknown property: "count" in undefined <<
-- Error occurred in dockDialog(); filename: ; position: 1393
-- Frame:
-- thisRO: ""
-- rolloutList: undefined
-- dialogName: "test3RO"
-- called in test3RO.moved(); filename: ; position: 6405
-- Frame:
-- value: [587,339]
>> MAXScript Rollout Handler Exception: -- Unknown property: "count" in undefined <<
Yeah, I think you need to evaluate it 2 times :S
Well, it is just for testings and there is absolutely no fine-tuning there ^^
The only problem I see is that it gets quite slow
well, one thing that should make it faster is to not have to loop over all of your dialogs when you don’t have to.
For example, when you move one dialog, you should only have to move its children. When you move those children, the ‘on <roll> moved’ event for them will trigger and they will take care of their own children (this could lead to an infinite loop if you dock things in a neat little circle). This does mean you have to assign a docked dialog to the parent dialog’s ‘children’ variable (you’ll have to make one), of course.
Also, I’m very confused by this little snippet of code (I admit I haven’t poked much further at your code, doing some timing tests today):
local tempParent = thisRO.parent
while tempParent.parent != undefined do
(
enableEscape = true
tempParent = tempParent.parent
)
[/cide]
That appears to be a potential infinite loop; is there any reason why tempParent.parent would suddenly -not- be undefined anymore? I.e. is there a parallel script or so that sets this value? That code above will easily peg the CPU (only 1 core, of course) so it seems iffy :)