So, played around with getMousePosition and setLabelReleaseCallback some more and built a sort of basic framework that lets you create draggable/resizable windows that have the complicated parts already baked in.
Here is the framework:
--testDWin
dwins = dwins or {}
dwinFuncs = dwinFuncs or {}
function createDWin(args)
local winName = args.name or "unknown"
local x = args.x or 300
local y = args.y or 200
local width = args.width or 300
local height = args.height or 200
local borderWidth = args.borderWidth or 3
-- if dwins[winName] then return end
local oldRef = dwins[winName] or {}
dwins[winName] = {}
dwins[winName].name = winName
dwins[winName].x = oldRef.x or x
dwins[winName].y = oldRef.y or y
dwins[winName].width = oldRef.width or width
dwins[winName].height = oldRef.height or height
dwins[winName].borderWidth = borderWidth
local bw = dwins[winName].borderWidth
dwins[winName].border = Geyser.Label:new({
name=winName .. "_border",
x=dwins[winName].x, y=dwins[winName].y,
width=dwins[winName].width, height=dwins[winName].height,
})
dwins[winName].title = Geyser.Label:new({
name=winName .. "_title",
x=dwins[winName].x+bw, y=dwins[winName].y+bw,
width=dwins[winName].width-(bw*2), height=15,
})
-- dwins[winName].main = Geyser.Label:new({
dwins[winName].main = Geyser.MiniConsole:new({
name=winName,
x=dwins[winName].x+bw, y=dwins[winName].y+15+bw,
width=dwins[winName].width-(bw*2), height=dwins[winName].height-15-(bw*2),
})
dwins[winName].border:setColor("|c999999")
dwins[winName].title:setColor("|c668866")
dwins[winName].main:setColor("|c111111")
dwins[winName].titleClick = function ()
dwins[winName].dragging = true
dwinDragCheck(winName)
end
-- local funcName = [[dwins["]]..winName..[["].titleClick]]
dwins[winName].titleRelease = function ()
dwins[winName].dragging = false
end
dwins[winName].borderClick = function ()
local mx, my = getMousePosition()
local edge = ""
if my < dwins[winName].y + dwins[winName].borderWidth then
edge = "north"
elseif my >= dwins[winName].y + dwins[winName].height - dwins[winName].borderWidth then
edge = "south"
else
edge = ""
end
if mx < dwins[winName].x + dwins[winName].borderWidth then
edge = edge .. "west"
elseif mx >= dwins[winName].x + dwins[winName].width - dwins[winName].borderWidth then
edge = edge .. "east"
else
edge = edge .. ""
end
-- echo(string.format("x: %i, y: %i == mx: %i, my: %i\n", dwins[winName].x, dwins[winName].y, mx, my))
-- echo("Dragging the " .. edge .. " edge.\n")
dwins[winName].edgeDragging = true
dwins[winName].edge = edge
dwinEdgeDragCheck(winName)
end
dwins[winName].borderRelease = function ()
dwins[winName].edgeDragging = false
dwins[winName].edge = nil
end
dwins[winName].title:setClickCallback("dwins." .. winName .. ".titleClick")
setLabelReleaseCallback(winName .. "_title", "dwins." .. winName .. ".titleRelease", winName .. "_title")
dwins[winName].border:setClickCallback("dwins." .. winName .. ".borderClick")
setLabelReleaseCallback(winName .. "_border", "dwins." .. winName .. ".borderRelease", winName .. "_border")
return dwins[winName]
end
function dwinDragCheck(winName)
if not dwins[winName].dragging then
dwins[winName].mx = nil
dwins[winName].my = nil
return
end
local mx, my = getMousePosition()
if dwins[winName].mx and dwins[winName].my and (dwins[winName].mx ~= mx or dwins[winName].my ~= my) then
dwins[winName].x = dwins[winName].x + (mx-dwins[winName].mx)
if dwins[winName].x < 0 then dwins[winName].x = 0 end
dwins[winName].y = dwins[winName].y + (my-dwins[winName].my)
if dwins[winName].y < 0 then dwins[winName].y = 0 end
dwinRedraw(winName)
end
dwins[winName].mx, dwins[winName].my = mx, my
tempTimer(0.03, [[dwinDragCheck("]] .. winName .. [[")]])
end
function dwinEdgeDragCheck(winName)
if not dwins[winName].edgeDragging then
dwins[winName].mx = nil
dwins[winName].my = nil
return
end
local mx, my = getMousePosition()
if dwins[winName].mx and dwins[winName].my and (dwins[winName].mx ~= mx or dwins[winName].my ~= my) then
if dwins[winName].x >= 0 and mx >= 0 then
if dwins[winName].edge:match("west") then
dwins[winName].x = dwins[winName].x + (mx-dwins[winName].mx)
dwins[winName].width = dwins[winName].width - (mx-dwins[winName].mx)
elseif dwins[winName].edge:match("east") then
-- dwins[winName].x = dwins[winName].x - (mx-dwins[winName].mx)
dwins[winName].width = dwins[winName].width + (mx-dwins[winName].mx)
end
end
if dwins[winName].y >= 0 and my >= 0 then
if dwins[winName].edge:match("north") then
dwins[winName].y = dwins[winName].y + (my-dwins[winName].my)
dwins[winName].height = dwins[winName].height - (my-dwins[winName].my)
elseif dwins[winName].edge:match("south") then
-- dwins[winName].y = dwins[winName].y + (my-dwins[winName].my)
dwins[winName].height = dwins[winName].height + (my-dwins[winName].my)
end
end
dwinRedraw(winName)
end
dwins[winName].mx, dwins[winName].my = mx, my
tempTimer(0.03, [[dwinEdgeDragCheck("]] .. winName .. [[")]])
end
function dwinRedraw(winName)
dwins[winName].border:move(dwins[winName].x, dwins[winName].y)
dwins[winName].border:resize(dwins[winName].width, dwins[winName].height)
dwins[winName].title:move(dwins[winName].x+dwins[winName].borderWidth, dwins[winName].y+dwins[winName].borderWidth)
dwins[winName].title:resize(dwins[winName].width-(dwins[winName].borderWidth*2), dwins[winName].height-15)
dwins[winName].main:move(dwins[winName].x+dwins[winName].borderWidth, dwins[winName].y+15+dwins[winName].borderWidth)
dwins[winName].main:resize(dwins[winName].width-(dwins[winName].borderWidth*2), dwins[winName].height-15-(dwins[winName].borderWidth*2))
end
function hideDWin(winName)
dwins[winName].border:hide()
dwins[winName].title:hide()
dwins[winName].main:hide()
end
function showDWin(winName)
dwins[winName].border:show()
dwins[winName].title:show()
dwins[winName].main:show()
end
Here is the code that generated the windows in this example:
statBox = createDWin({name = "statBox", x = 300, y = 300, width = 300, height = 200, borderWidth = 10})
statBox.title:echo("Stats", nil, "cb")
statBox.main:cecho("<green>Blah!\nBlah!")
inventoryBox = createDWin({name = "inventoryBox", x = 700, y = 300, width = 300, height = 200, borderWidth = 2})
inventoryBox.title:echo("Inventory", nil, "cb")
inventoryBox.main:hecho("|cffaaffItem 1\n|caabb34Item 2\n|c5555ffItem 3")
testBox = createDWin({name = "testBox", x = 500, y = 300, width = 300, height = 200, borderWidth = 5})
dirBox = createDWin({name = "dirBox", x = 200, y = 200, width = 200, height = 150, borderWidth = 5})
A screenshot of an arrangement of those windows I did with nothing but the mouse(yes, the borderWidth of 10 on one of those is ugly):
And here's a video of me showing off the drag-moving and drag-resizing properties of those windows:
https://vimeo.com/189117740
With a little bit of polish and some more optional initialization arguments like title color, title text, wrapping, possibly allowing anchoring of them to %'s instead of actual pixel numbers so you could set up windows that displayed properly at other resolutions(like when I unplug my monitor and change from 1920 x 1080 to 1366 x 780 or something), and other things about this system fleshed out, I'll likely start moving all my code into working with those windows. Fun. =D