Automatically Align and Resize Layout Objects

 

 

Automatically align and resize graphs and textboxes in layouts so that they match others in their class. Their class is defined as other objects of the same type that are near them in a given dimension (x or y) on the layout. Suppose you had a layout with 6 graphs arranged 3 rows x 2 columns and 6 textboxes "A" through "F" near each one. You don't want to fill the entire layout by tiling them using the Tile command; instead you want the behavior that you would get if you manually selected the two graphs in the first row, selected "Align Top Edges" and "Make Same Width and Height" form the Layout Menu, then repeated this for each of the other rows, and then repeated it for columns using "Align Left Edges', and then repeated it again for the 6 textboxes. This is tedious, and this function is meant to achieve this in one stroke. Note that this only works when your layout objects are roughly in the right positions; it is meant to clean them up with small adjustments, not to move them all the way across the layout.

 

 


function NiceLayout(rows,cols[,win])
	variable rows,cols // Desired number of rows and columns.  
	string win // Optional layout window name.  
	
	win=selectstring(!paramisdefault(win),winname(0,4),win)
	variable i=0,j,k,d
	string types="Graph;Textbox"
	make /free/t/n=(itemsinlist(types)) items=""
	
	// Make lists of the various items in the layout.  
	do
		string info=LayoutInfo(win,num2str(i))
		string type=stringbykey("TYPE",info)
		string name=stringbykey("NAME",info)
		variable typeNum=whichlistitem(type,types)
		if(typeNum>=0)
			items[typeNum]+=name+";"
		endif
		i+=1
	while(strlen(info))
	
	// Go through these lists.  
	for(i=0;i<itemsinlist(types);i+=1)
		type=stringfromlist(i,types)
		make /free/n=(1,itemsinlist(items[i]),1) yy=numberbykey("TOP",layoutinfo(win,stringfromlist(q,items[i])))
		string dimensions="xx;yy"
		for(d=0;d<itemsinlist(dimensions);d+=1)
			string dimension=stringfromlist(d,dimensions)
			strswitch(dimension)
				case "xx":
					string lefttop="LEFT"
					string widthheight="WIDTH"
					variable classes=cols+1
					break
				case "yy":
					lefttop="TOP"
					widthheight="HEIGHT"
					classes=rows+1
					break
			endswitch
			make /free/n=(1,itemsinlist(items[i]),1) locs=numberbykey(lefttop,layoutinfo(win,stringfromlist(q,items[i])))	
			variable minDispersion=Inf
			make /free/I/n=(itemsinlist(items[i])) membership=0
			
                        // Try clustering 100 times and take the best cluster assignments.  
                        for(j=0;j<100;j+=1)
				KMeans /CAN /NCLS=(classes) /OUT=2 /SEED=(abs(enoise(1000))) locs
				wave w_kmmembers,W_KMDispersion
				if(sum(w_kmdispersion)<minDispersion)
					membership=w_kmmembers
					minDispersion=sum(w_kmdispersion)
				endif
			endfor
			for(j=0;j<=wavemax(w_kmmembers);j+=1)
				extract /free/indx membership,members,membership==j
				variable leftTopNum=0, widthHeightNum=0
				for(k=0;k<numpnts(members);k+=1)
					leftTopNum+=numberbykey(leftTop,layoutinfo(win,stringfromlist(members[k],items[i])))
					widthHeightNum+=numberbykey(widthHeight,layoutinfo(win,stringfromlist(members[k],items[i])))
				endfor
				leftTopNum/=numpnts(members)
				widthHeightNum/=numpnts(members)
				for(k=0;k<numpnts(members);k+=1)
					name=stringfromlist(members[k],items[i])
					strswitch(dimension)
						case "xx":
							modifylayout /w=$win left($name)=leftTopNum, width($name)=widthHeightNum
							break
						case "yy":
							modifylayout /w=$win top($name)=leftTopNum, height($name)=widthHeightNum
							break
					endswitch
				endfor
			endfor
		endfor
	endfor
end

Forum

Support

Gallery

Igor Pro 10

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More