Nestable Labels

Share your scripts and packages with other Mudlet users.
User avatar
chris
Posts: 493
Joined: Fri Jun 17, 2011 5:39 am

Nestable Labels

Post by chris »

Here's a work in progress of labels that can be nested within eachother. It makes use of the mouseover labels I have in my github, so if you aren't on that fork get rid of the SetOnEnter in the label assignment. I use this for taking care of the favorites from my cmud map, and other similar things. Scrolling also is somewhat limited (to scroll if the list is too large to fit, click the More... buttons) to a single nested element at a time.
Code: [show] | [select all] lua
nl = {}
--THIS DOESN'T NEED TO BE TOUCHED
nl.dirMap = {["R"]={1,0}, ["L"]={-1,0}, ["T"]={0,-1}, ["B"]={0,1}}
nl.reverseDir = {["R"]="L", ["L"]="R", ["T"]="B", ["B"]="T"}
nl.scrolls = {"RScroll", "LScroll", "TScroll", "BScroll"}
nl.nestLevel = 0
nl.incrementMap = {["R"]=0, ["L"]=0, ["T"]=0, ["B"]=0}
nl.hiddenLabels = {}
nl.lastNest = ""
nl.orientMap = {["V"]={0,1}, ["H"]={1,0}}
nl.container = {}
nl.labels = {}
nl.scrollStart = 0
nl.widgetPositions = {}
--USER CONFIGURATION--
--each entry takes three, optionally four values.
--nl.widgets is a table of tables, each table specifies:
--Name(what we see), orientation, and parent
--orientation is like: UH, for upper horizontal, meaning the label will open above
--directions are: U(upper), B(below), R(right), L(left)
--layout directions are: V(vertical), H(horizontal).  So combos are: UV,UH, BV, etc
--the prior label, and each subsequent label will be added horizontally within that nest
--here's an example:
nl.widgets = {{"Menu One", "UH", nil}, {"Two", "BH", "Menu One"}, {"Three", "BH", "Menu One"}, {"Four", "BH", "Three"}, {"Five", "BH", "Three"}, {"Six", "BH", "Four"}, {"Seven", "RH", "Six"}}
--for the nested widgets, do we want them to fly out when they're moused over?
nl.flyNests = true
--there is no dynamic sizing
nl.widgetHeight = 25
nl.widgetWidth = 100
--all you need to set here is the x,y position, the width/height are irrelevant
nl.container = Geyser.Container:new({
    fontSize = 8,
    x="-150c",
    y="30c",
    width="100",
    height="25",
    name="NestLabel",
  })

function getWidget(name)
	for i,v in pairs(nl.widgets) do
		if v[1] == name then
			return v
		end
	end
end

function getNestLevels()
	nl.nestLevels = {}
	for i,v in pairs(nl.widgets) do
		local parent = v[3]
		local iter = 0
		while parent do
			parent = getWidget(parent)[3]
			iter = iter+1
		end
		nl.nestLevels[v[1]] = iter
	end
end

function nestScroll(direction)
	local sDir = string.sub(direction, 1,1)
	nl.scrollStart = nl.scrollStart+nl.incrementMap[sDir]
	if nl.scrollStart < 0 then
		nl.scrollStart = 0
	elseif nl.scrollStart > table.getn(nl.widgets) then
		nl.scrollStart = 0
	end
	displayNestedElements(nl.lastNest)
	if (direction == "RScroll") then
	elseif (direction == "LScroll") then
	elseif (direction == "TScroll") then
	elseif (direction == "BScroll") then
	end
end

function setupScrolling()
	for i,v in pairs(nl.scrolls) do
			nl.labels[v] = Geyser.Label:new({
	      name=string.format("label%s", v),
			x=0,
			y=0,
			width=nl.widgetWidth,
	   	   height=nl.widgetHeight,
		    }, nl.container)
	  nl.labels[v]:echo("More..", "white", "c")
	  nl.labels[v]:setColor(50,50,50)
	  nl.labels[v]:setClickCallback("nestScroll", v)
	  nl.labels[v]:hide()
	end
end

function layoutNests()
	nl.labels = {}
	local itemNum = 1
--setup scrolling labels
	setupScrolling()
	for i,v in pairs(nl.widgets) do
		--setup parent widgets
		local name, orient, parent = v[1], v[2], v[3]
		local layoutDir = string.sub(orient, 2,2)
			nl.labels[name] = Geyser.Label:new({
	      name=string.format("label%s", name),
			x=nl.orientMap[layoutDir][1]*itemNum*nl.widgetWidth,
			y=nl.orientMap[layoutDir][2]*itemNum*nl.widgetHeight,
			width=nl.widgetWidth,
	   	   height=nl.widgetHeight,
		    }, nl.container)
		    nl.labels[name]:echo(name, "white", "c")
		    nl.labels[name]:setColor(50,50,50)
		    nl.labels[name]:setClickCallback("buttonClick", name)
		if parent then
			nl.labels[name]:hide()
			nl.hiddenLabels[name] = true
			if nl.flyNests then
			    nl.labels[name]:setOnEnter("OnEnter", name)
			end
		end
		itemNum = itemNum+1
	end
	getNestLevels()
end

function OnEnter(win)
	if displayNestedElements(win) then
		nl.lastNest = win
	end
--	displayNestedElements(win)
end

function displayNestedElements(win, fly)
	local newX, newY = nl.labels[win]:get_x(), nl.labels[win]:get_y()
	local maxX, maxY = getMainWindowSize()
	local foundNest = nil
	local itemNum = 0
	local itemNests = {}
	local reverse=1
	if nl.widgetPositions[win] then
		newX, newY = nl.widgetPositions[win][1],nl.widgetPositions[win][2]
	end
	for i,v in pairs(nl.widgets) do
		local name, orient, parent = v[1], v[2], v[3]
		if parent and parent == win then
			itemNum = itemNum + 1
			local noSpaceParent = string.gsub(parent," ","")
			if not itemNests[noSpaceParent] then
				itemNests[noSpaceParent] = 0
			end
			if itemNum > nl.scrollStart then
			local widgetX, widgetY=newX,newY
			local flyDir = string.sub(orient, 1,1)
			local layoutDir = string.sub(orient, 2,2)
--this is our new base starting position
			widgetX = widgetX+nl.dirMap[flyDir][1]*nl.widgetWidth
			widgetY = widgetY+nl.dirMap[flyDir][2]*nl.widgetHeight
--this offsets us correctly from this new base in the V(vertical) or H(horizontal orientation)
			widgetX = widgetX+nl.orientMap[layoutDir][1]*nl.widgetWidth*itemNests[noSpaceParent]*reverse
			widgetY = widgetY+nl.orientMap[layoutDir][2]*nl.widgetHeight*itemNests[noSpaceParent]*reverse
			if widgetX > maxX-nl.widgetWidth*2 or widgetY > maxY-nl.widgetHeight*2 or widgetX < nl.widgetWidth*2 or widgetY < nl.widgetHeight*2 then	
				if reverse==1 then
					local scrollLabel = flyDir.."Scroll"
					moveWindow("label"..scrollLabel, widgetX, widgetY)
					nl.labels[scrollLabel]:show()
					nl.incrementMap[flyDir]=reverse
					reverse=-1
		    		itemNests[noSpaceParent]	= 1
				else
					local scrollLabel = nl.reverseDir[flyDir].."Scroll"
					moveWindow("label"..scrollLabel, widgetX, widgetY)
					nl.incrementMap[nl.reverseDir[flyDir]]=reverse
					nl.labels[scrollLabel]:show()
				end
			else
			nl.widgetPositions[name] = {widgetX, widgetY}
			moveWindow("label"..name, widgetX, widgetY)
			nl.labels[name]:show()
			if nl.hiddenLabels[name] then
				nl.hiddenLabels[name] = false
				foundNest = 1
			end
    		itemNests[noSpaceParent]	= itemNests[noSpaceParent]+1
			end
		end
		end
	end
	if not foundNest then
		return nil
	end
	nl.nestLevel = nl.nestLevel+1
	return 1
end

function buttonClick(win)
	nl.lastNest = win
	if not displayNestedElements(win) then
		nl.nestLevel = 0
		nestAll()
	end
end

function nestAll()
	nl.widgetPositions = {}
	nl.scrollStart = 0
	nl.incrementMap = {["R"]=0, ["L"]=0, ["T"]=0, ["B"]=0}
	setupScrolling()
	for i,v in pairs(nl.widgets) do
		if v[3] then
			nl.labels[v[1]]:hide()
			nl.hiddenLabels[v[1]] = true
		end
	end
end

layoutNests()

User avatar
Omni
Posts: 131
Joined: Fri Feb 12, 2010 10:26 am

Re: Nestable Labels

Post by Omni »

Mind posting a screenshot?

User avatar
chris
Posts: 493
Joined: Fri Jun 17, 2011 5:39 am

Re: Nestable Labels

Post by chris »

Sure, though it does no justice to how it actually interacts :). On the flyout thing,you can also just set nl.flyNests = false(or maybe nil) to disable it.

http://imgur.com/a/hhJPl

User avatar
Vadi
Posts: 5042
Joined: Sat Mar 14, 2009 3:13 pm

Re: Nestable Labels

Post by Vadi »

Looks interesting, I'll take a look. Also install liblua5.1-filesystem0

User avatar
Vadi
Posts: 5042
Joined: Sat Mar 14, 2009 3:13 pm

Re: Nestable Labels

Post by Vadi »

I really like this! For some reason the flyover isn't working for the first one though, is it considered separate? The labels should go away on leaving as well.

When you're finished with this, let's add it to Mudlet's Lua API - to do that, send a pull request to github.com/Beliaar/mudlet-lua.

User avatar
chris
Posts: 493
Joined: Fri Jun 17, 2011 5:39 am

Re: Nestable Labels

Post by chris »

The flyover is not enabled for the first one because I didn't want them flying out from just passing the mouse over them, though it's simple to add an option for flying out this layer as well. And yeah, I need to unnest if a new nest can pop out at a higher nest level, etc. In terms of adding to Mudlet's Lua API, do you mean a new Geyser class? Or just something to make the nitty gritty details of how it works hidden so the player just needs to set a few lines instead of copying/pasting a hard to decipher script :)

User avatar
Vadi
Posts: 5042
Joined: Sat Mar 14, 2009 3:13 pm

Re: Nestable Labels

Post by Vadi »

I think this would work as a new Geyser class, yeah.

User avatar
chris
Posts: 493
Joined: Fri Jun 17, 2011 5:39 am

Re: Nestable Labels

Post by chris »

I'll see what I can do about putting it more internally. I'm not too gung ho on learning how Geyser is setup though, so it may just go into luaGlobal(), since it is in essence an application of geyser rather than something new.

User avatar
Vadi
Posts: 5042
Joined: Sat Mar 14, 2009 3:13 pm

Re: Nestable Labels

Post by Vadi »

I'd like to think that it is a new Geyser class - what we have right now are mostly primitives, but that shouldn't restrict mode advanced classes.

Stuff is just loaded through https://github.com/Beliaar/mudlet-lua/b ... Global.lua, including Geyser.

User avatar
chris
Posts: 493
Joined: Fri Jun 17, 2011 5:39 am

Re: Nestable Labels

Post by chris »

See my github repo post for details on this. I expanded the Label class to allow nesting. The code isn't terribly pretty, but it works

Post Reply