Button Trees

BlitzMax Forums/BlitzMax Programming/Button Trees

Hi guys, just me again having trouble. I'm after this kind of effect (see the menu on the left hand side: http://www.eve-online.com/itemdatabase/ships/ or something like this:

I'm just having trouble imagining the code.

if each button has a list of children and there is a root button to begin from how would it work if you clicked on the root button or button C? I'm confused.

How would work what?
You check which button was clicked and execute the code bound to it ...
(using CollideRect with a mousepointer)

(using CollideRect with a mousepointer)


Or avoid the overhead of that with...

Function MouseOver( x, y, w, h )
		Local mx,my
		mx = MouseX( )
		my = MouseY( )
		Return ( mx >= x And mx <= x + w And my >= y And my <= y + h )
	End Function


a little bit of messing,
Type TButton
	Field X:Int
	Field Y:Int
	Field Width:Int
	Field Height:Int
	Field Caption:String
	Field Parent:TButton = Null
	Field SubItems:TButton[]
	Field Expanded:Int = False
	Field TotalHeight:Int
	
	'events
	Field OnClick(Sender:TButton)
	
	'returns true if the mouse is within the bounds of the control
	Method MouseOver:Int()
		If (MouseX() < X + Width) And (MouseX()>X) Then
			If (MouseY() < Y + Height) And (MouseY()> Y) Then
				Return True
			EndIf
		EndIf
		Return False
	End Method
	
	Method Update()
		If MouseHit(1) And MouseOver() Then 
			If OnClick<>Null Then OnClick(Self)
		EndIf
		draw()		
		If expanded Then 
			For Local item:TButton = EachIn SubItems
				item.update()
			Next
		EndIf
	End Method
	
	
	Method draw()
		Local YOffset : Int
		If Parent <> Null Then
			YOffset = Parent.TotalHeight+Parent.Y
		EndIf
		SetColor(0,0,255)
		DrawRect(X, Y+YOffset, Width, Height)
		SetColor(255,255,255)
		DrawText(Caption, X+2,Y+YOffset+2)
	End Method
	
	
	Method AddItem(Item:TButton)
		Item.Parent = Self
		Item.X = X + Item.X
		Item.Y = Y+Height+(Len(SubItems)*Height)
		Item.Height = Height
		SubItems = SubItems[..Len(SubItems)+1]
		SubItems[Len(SubItems)-1] = Item
	End Method
	
	Function Create:TButton(X,Y,W,H, Caption:String)
		Local tempButton : TButton =  New TButton
			tempButton.X = X
			tempButton.Y = Y
			tempButton.Width = W
			tempButton.Height = H
			tempButton.Caption = Caption
		'	tempButton.SubItems = New TList
		Return tempButton
	End Function
End Type


Graphics 800,600,0,0

Global myButton:TButton = TButton.Create(10,10,100,20,"Menu Item 1")
		mybutton.AddItem(TButton.Create(10,10,100,20,"Sub Item 1"))
		mybutton.AddItem(TButton.Create(10,10,100,20,"Sub Item 2"))
		mybutton.OnClick = myButton_OnClick
		myButton.SubItems[0].AddItem(TButton.Create(10,10,100,20,"Sub Item 1"))
		myButton.SubItems[0].AddItem(TButton.Create(10,10,100,20,"Sub Item 2"))
		mybutton.SubItems[0].OnClick = myButton_OnClick
While Not KeyDown(KEY_ESCAPE)
	Cls
	
	myButton.Update()
	
	Flip
Wend
End

Function myButton_OnClick(Sender:TButton)
	Sender.expanded = Not Sender.expanded
	If expanded Then Sender.TotalHeight = Sender.Height*(Len(Sender.SubItems)+1) Else Sender.TotalHeight = Height
End Function


needs tidied up a lot

damn homie that's exactly what I needed. thanks very much you guys!!

That's one great thing about the Blitz community. These guys are more friendly and helpful than just about any other coding community I've ever seen. Using Blitz is worth it just for the community support (plus, it's a good language)...

wait wait.. no, I'm getting confused again. check out my code:

Basically I want it so that I can add a load of buttons to a particular parent. When the parent is closed the children are hidden. when the parent is open the children are shown. The now visible children push the other buttons down too, like this:


Frankly I don't know what the hell I'm doing.
Global root:button


Type button
	Field x,y,txt$,dy
	Field children:TList
	Field parent:button
	Field over,open,height
	
	Function create:button(x,y,txt$)
		Local f:button=New button
		f.x=x;f.y=y;f.txt=txt
		Return f
	End Function
	
	Method update()		
		If open
			If children<>Null
				For Local i:button=EachIn children
					i.update()
				Next
			EndIf
		EndIf
		draw()
	End Method			
		
	Method draw()
		Local yoff=0
		Local xoff=0
		
		If parent<>Null
			If open And parent.open
				yoff=parent.height+parent.y+(17*q)
				xoff=parent.x+15
			Else
				yoff=0
				xoff=parent.x+15
			EndIf
		Else
			yoff=0
			xoff=0
		EndIf

		over=mouseIn(x+xoff,y+yoff,222,17)
		If over And MouseHit(1)
			open=1-open
			If open
				If children<>Null Then height=(children.count()+1)*17							
			Else
				height=0
			EndIf
		EndIf			
				
		SetColor 155,155,155
		SetAlpha 0.9
		'DrawImage panelImage,x+xoff,y+yoff
		DrawRect x+xoff,y+yoff,222,17
		
		SetAlpha 1.0;SetColor 255,255,255
		DrawText Upper(txt)+" Open: "+open,x+5+xoff,y+3+yoff
		
		' draw some extra info about children ie: (3)				
		If children<>Null' And txt<>""
			Local t$="("+Upper(children.count())+") h:"+height
			DrawText t,x+(222-TextWidth(t))-5+xoff,y+3+yoff		
		EndIf

	End Method
	
	Method addChild(t:button)
		If t.txt="" Then t.open=True
		t.parent=Self
		If children=Null
			children=CreateList()	
		EndIf
		t.x=x
		t.y=y+17
		ListAddLast(children,t)			
	End Method
End Type


Function mouseIn(x,y,w,h)
	Local mx=MouseX()
	Local my=MouseY()
	
	If mx>x And mx<x+w
		If my>y And my<y+h
			Return True
		EndIf
	EndIf	
	Return False
End Function


' --------------------------------------

	root:button=button.create(50,50,"")
		
	Local p:button=button.create(0,0,"AAAAAAA")
	root.addChild(p)	
		p.addChild(button.create(0,0,"1 A"))
		p.addChild(button.create(0,0,"1 B"))
		p.addChild(button.create(0,0,"1 C"))
	
	Local p2:button=button.create(0,0,"BBBBBBB")
	root.addChild(p2)	
		p2.addChild(button.create(0,0,"2 A"))
		p2.addChild(button.create(0,0,"2 B"))
		p2.addChild(button.create(0,0,"2 C"))

	Local p3:button=button.create(0,0,"CCCCCCC")
	root.addChild(p3)	
		p3.addChild(button.create(0,0,"3 A"))
		p3.addChild(button.create(0,0,"3 B"))
		p3.addChild(button.create(0,0,"3 C"))

Graphics 640,480,0,60

While KeyHit(KEY_ESCAPE)=0
	Cls
	
		root.update()
	
	Flip
Wend
End


Oh boy, I did it. I knew there was something I was missing and it was a previous pointer. When you know the previous buttons coords and how many children they have you can set your own coords if you're after, like B when A is open and showing A1 and A2. I won't supply the code because it truly is terrible. But thanks for all the help guys.