Divider gadget?

BlitzMax Forums/BlitzMax GUI Programming/Divider gadget?

Any idea how I can make a divider? Is there an actual windows control for this, or are they always hacks? I'd prefer not to use a canvas to handle this, since I think that's a cheesy method.

See the bottom of this image:


Hi,

You can use the divider style (LABEL_SEPARATOR) of the Label gadget, see the MaxGUI documentation... Example:

' createlabel.bmx

Strict 

Local window:TGadget

window=CreateWindow("My Window",30,20,320,480)

CreateLabel("",10,220,280,54,window,LABEL_SEPARATOR)

While WaitEvent()<>EVENT_WINDOWCLOSE
Wend


Seb

Thanks, I just found the LABEL_SEPARATOR flag.

I added a tweak to get a 2-pixel-high divider, instead of the default box:
Strict 

Local window:TGadget
Local label:TGadget
Local hwnd

window=CreateWindow("My Window",30,20,320,480)

label=CreateLabel("",10,220,280,54,window,LABEL_SEPARATOR)

hwnd=QueryGadget(label,QUERY_HWND)
SetWindowPos hwnd,0,0,0,label.width,2,SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE

While WaitEvent()<>EVENT_WINDOWCLOSE
Wend


Hmmmmm...as soon as the user resizes the window, Blitz resizes the divider to make a box, even if the layout is set to the top-left corner. How can I make the divider remain the height I want it? Adding a hook and putting all my dividers into a list seems a little excessive for something this simple.

I can also create a parent panel 2 pixels high, and create the separator in this panel, so only the top 2 pixels are visible. Kind of a hack, but it works for now.

You can use SetGadgetLayout to lock the gadget dimensions (or have it scale when the window resizes, etc.)

Hmmmmm...as soon as the user resizes the window, Blitz resizes the divider to make a box, even if the layout is set to the top-left corner.


SetGadgetLayout uses a combination of 4 sides, anchored or averaged, the maxide source features a splitter which demonstrates. By no means my finest hour but i remember a lot of fiddling to get them right, you add the splitter to the same parent as your two panels, it resizes them filling the parent client area with a combination of the three chidren gadgets in total. The flip option reverses the sides of the two panels (navbar on left option in maxide).

Strict 

Local window:TGadget
Local panel1:TGadget
Local panel2:TGadget
Local group:TGadget

window=CreateWindow("My Window",40,40,320,240)

panel1=CreatePanel(0,0,0,0,window,PANEL_ACTIVE)
panel1.SetColor(160,55,160)
panel2=CreatePanel(0,0,0,0,window,PANEL_ACTIVE)
panel2.SetColor(160,255,160)

Local split:TSplitter

'split=TSplitter.Create(TSplitter.VERTICAL,100,0,panel1,panel2)
split=TSplitter.Create(TSplitter.HORIZONTAL,100,0,panel1,panel2)


While True
	WaitEvent 
	Print CurrentEvent.ToString()
	If EventSource()=split.panel
		split.OnEvent
		Continue
	EndIf
	Select EventID()
		Case EVENT_WINDOWCLOSE
			End
	End Select
Wend

Const SPLITWIDTH=2

Type TSplitter 
	Const	HORIZONTAL=0
	Const	VERTICAL=1

	Field	axis,gadget0:TGadget,gadget1:TGadget,group:TGadget
	Field	panel:TGadget,pos,flipped,snap,oldpos,oldsize
	
	Method Position(p)
		Move p-pos
	End Method
		
	Method Move(d)
		Local	w,h,p
		pos:+d
		w=ClientWidth(group)
		h=ClientHeight(group)
		If pos<0 pos=0
		If axis=VERTICAL
			If pos>w-SPLITWIDTH pos=w-SPLITWIDTH
			If (d<0)~flipped
				SetGadgetShape gadget0,0,0,pos-SPLITWIDTH,h
				SetGadgetShape panel,pos-SPLITWIDTH,0,SPLITWIDTH*2,h
				SetGadgetShape gadget1,pos+SPLITWIDTH,0,w-(pos+SPLITWIDTH),h
			Else
				SetGadgetShape gadget1,pos+SPLITWIDTH,0,w-(pos+SPLITWIDTH),h
				SetGadgetShape panel,pos-SPLITWIDTH,0,SPLITWIDTH*2,h
				SetGadgetShape gadget0,0,0,pos-SPLITWIDTH,h
			EndIf
		Else
			If pos>h-SPLITWIDTH pos=h-SPLITWIDTH
			If (d<0)~flipped
				SetGadgetShape gadget0,0,0,w,pos-SPLITWIDTH
				SetGadgetShape panel,0,pos-SPLITWIDTH,w,SPLITWIDTH*2
				SetGadgetShape gadget1,0,pos+SPLITWIDTH,w,h-(pos+SPLITWIDTH)
			Else
				SetGadgetShape gadget1,0,pos+SPLITWIDTH,w,h-(pos+SPLITWIDTH)
				SetGadgetShape panel,0,pos-SPLITWIDTH,w,SPLITWIDTH*2
				SetGadgetShape gadget0,0,0,w,pos-SPLITWIDTH
			EndIf
		EndIf
	End Method
	
	Method Resize()
		If axis=VERTICAL
			pos=GadgetX(panel)+SPLITWIDTH
			If pos<0 Or pos>ClientWidth(group) move(0)
		Else
			pos=GadgetY(panel)+SPLITWIDTH
			If pos<0 Or pos>ClientHeight(group) move(0)
		EndIf
	End Method		
	
	Method OnEvent()
		If EventSource()<>panel Return
		Select EventID()
			Case EVENT_MOUSEDOWN
				snap=True
				If axis
					oldpos=EventX()
				Else
					oldpos=EventY()
				EndIf				
			Case EVENT_MOUSEENTER
				If axis
					SetPointer POINTER_SIZEWE
				Else
					SetPointer POINTER_SIZENS
				EndIf
			Case EVENT_MOUSELEAVE
				SetPointer POINTER_DEFAULT
			Case EVENT_MOUSEUP
				snap=False
			Case EVENT_MOUSEMOVE
				If axis
					SetPointer POINTER_SIZEWE
				Else
					SetPointer POINTER_SIZENS
				EndIf	
				If snap
					If axis
						Move EventX()-oldpos
					Else
						Move EventY()-oldpos
					EndIf
				EndIf							
		End Select
	End Method
	
	Method SetFlip(f,init=True)
		Local	t:TGadget
		If f<>flipped
			flipped=f
			t=gadget0;gadget0=gadget1;gadget1=t
			If init 
				If axis=VERTICAL
					pos=ClientWidth(group)-pos-1
				Else
					pos=ClientHeight(group)-pos-1
				EndIf
			EndIf
		EndIf			
		If axis
			If flipped
				SetGadgetLayout gadget0,1,0,1,1
				SetGadgetLayout gadget1,1,1,1,1
				SetGadgetLayout panel,1,0,1,1
			Else
				SetGadgetLayout gadget0,1,1,1,1
				SetGadgetLayout gadget1,0,1,1,1
				SetGadgetLayout panel,0,1,1,1
			EndIf
		Else
			If flipped
				SetGadgetLayout gadget0,1,1,1,0
				SetGadgetLayout gadget1,1,1,1,1
				SetGadgetLayout panel,1,1,1,0
			Else
				SetGadgetLayout gadget0,1,1,1,1
				SetGadgetLayout gadget1,1,1,0,1
				SetGadgetLayout panel,1,1,0,1
			EndIf
		EndIf
		Position pos
	End Method

	Function Create:TSplitter(axis,pos,flipped,gadget0:TGadget,gadget1:TGadget)
		Local	s:TSplitter		
		s=New TSplitter
		s.axis=axis
		s.gadget0=gadget0
		s.gadget1=gadget1
		s.group=GadgetGroup(gadget0)
		s.panel=CreatePanel(0,0,0,0,s.group,PANEL_ACTIVE)'|PANEL_BORDER)
		s.pos=pos
		s.setflip flipped,False
		Return s
	End Function
End Type


That wasn't what I was asking about, but nice splitter!

I guess this is the problem :
void Win32Label::setShape( int x,int y,int w,int h ){
	if ((GetWindowLong(_gadget.hwnd(),GWL_STYLE)&SS_TYPEMASK)==SS_ETCHEDFRAME) h=4;
	_gadget.setShape(x,y,w,h);
	BBLabel::setShape(x,y,w,h); 
}

...where it sets height to 4. Changing it to 2 makes it work properly on my win2k box. However it might depend on the theme in use.

Thanks Skidracer, that splitter code is just what I was looking for,

Im putting it in now!

Just paste'd the code in, now I have a splitter

Skidracer, thanks for the splitter code.