Code archives/BlitzPlus Gui/MaxIDE

This code has been declared by its author to be Public Domain code.

Download source code

MaxIDE by skidracer
(Posted 20 years ago)
Requires MaxGUI.
' maxide.bmx - blitzmax native integrated development environment

' released under the Blitz Shared Source Code License
' (c)2005 Blitz Research

' initial release version by simonarmstrong@blitzbasic.com

' v120d
' added external help option for linux users

' v120c
' add doc modules option to program menu and fixed syncmods so no restart required
' fixed wrong window activation ugliness in TRequester.Hide
' fixed TDebugTree.SetStack synchronization bug

' v120b
' added autobackup code to SaveSource method 
' fixed autoindent bug including tabs to the right of the cursor

' v120
' Ripped out isupdate stuff
' About requester now shows runtime BCC version

' v118
' Added file filter to SaveAs requester
' Edit method of TOpenCode now activates cursor and refreshes status
' TQuickHelp tokenizer now uses faster TToken map 
' ReadSource and WriteSource now use unicode LoadText and SaveText commands

' v112b
' added .doc file type to filters list
' added trycatch for bmxpath not found
' prepends bmx filenames loaded from help with "." to protect original source
' fixed unblanced quotes in wordatpos() stuffing up quick help 
' fixed exception when debugging function pointer values

' v112

' isupgrade - version check on ini file for ranlibdir and quick build disable
' debug step tools now respect cancontinue flag
' tidied up debug stdio buffers and flushing of process pipes
' linux defaults for closedocument-CtrlW nextdoc-AltRight prevdoc-AltLeft 
' end of lines converted to chr(13)+chr(10) for all saved source files 
' ReplaceAll uses locktextarea for speedup
' added print option for helppage
' filtering tab key in opencode for original block in/outdent
' removed vertical tabs from source
' added .bbdoc filetype to filters$
' fixed null href help tree entries (index node)
' new textareafilter code for the Ouput console emulator
' refreshes pointer in splitter on EVENT_MOUSEMOVE

' v111
' fixed open locked file not found at startup crash
' buildandrun continues from debugstop else kills task and rebuilds
' fixed bug on freshly loaded source being dirty
' fixed bug with options cancel
' MacOS specific hotkey bindings updated
' added .m to file FILTERS$
' adjusted GOTO and IDEOptions requesters

' v110
' DebugSource now calls ShowGadget on IDE window to bring debugger to front

' v109
' fixed WordAtPos to include underscore

' v108
' windows release version

' v107
' activate current panel when window receives focus
' fixed multiple lock build file bug
' fixed command highlighting for functions with # and ! return types
' sourcefile already open check now case insensitive
' block indent outdent now ctrl-[ and ctrl-]
' commandline args fixed

' v106b
' new defaults
' fixed replace all garbage
' removed extra endrem highlight

' v106
' added demo version support
' fixed delete / backspace undo redo issues
' added syntaxhighlight disable option
' fixed block indent / outdent highlighting issue
' added flushmem to replaceall loop
' set window title to full path of current document
' fixed double highlight for endrem

' v105c
' code view now includes labels etc. on first line
' textarea activated when panel open
' autohide output on exit now always returns to last active panel
' optimized code change algorithm
' like compiler, rem and endrem must be first code on line
' fixed up linux line spacing, font selection and code tree / create panel crashes
' new linux help system, style setting and popup menu support
 
' v105b
' added tabbing support in dialogs
' fixed pollsystem event debacle
' fixed lineselection out of view
' fixed highlighting for pasting code blocks
' fixed treeview memory leak and speedissues
' uses -x switch from bmk for build and run option
' debugging now opens source when stepping in

' v105
' activating window selects current panel
' fixed closing output window causing crash
' frees gadgets
' dirty flags now clears only if source=file and undobuffer=empty
' tidied up console window madness
' fixed gcc error check hang
' fixed label detection in code view
' fixed debugger crash with local block variable decls
' fixed codenode refresh with saveas

' v104
' fixed debug tree update and debugreset
' fixed incorrect navbar size for maximized window 
' added \ option
' notify gcc compiler errors in output

' v103
' navbar options left/right 
' added copy paste menu for output window
' added font color options for output and navbar windows
' fixed win32 paste from clipboard to use plain ascii
' stdio debugger handler
' save currentpanel, cursorpositions
' replace default "~\" requestfile path with a currentpath
' fixed pipe handling problem in quickhelp

' v102
' specify openfile from commandline 
' hides main window till all files openned
' checks window bounds against desktop size
' added deferred capitalizing cludge
' fixed rem/endrem updating problem
' fixed highlight / redraw noise
' drag&drop file support added
' dropdown menu in textarea added
' run with commandline arguments
' block indent/outdent
' fixed drag&drop text crash
' added escape handler to output window, removed autohide

Strict

Framework brl.maxgui

Import brl.win32maxgui
Import brl.cocoamaxgui
Import brl.fltkmaxgui

Import brl.standardio
Import brl.retro
Import brl.filesystem
Import brl.system
Import pub.freeprocess
Import brl.pngloader
Import brl.timer
Import brl.maxutil

?win32
Import "maxicons.o"
?

Incbin "icons.PNG"

Incbin "syncmodsblurb.txt"

Const IDE_VERSION$="1.20"
Global BCC_VERSION$="{unknown}"	'not valid until codeplay opened

Const EOL$="~n"
Const SPLITWIDTH=4

Const ABOUT$=..
"{bcc_version} - Copyright Blitz Research Ltd~n~n"+..
"Please visit www.blitzbasic.com for all your Blitz related needs!"

Const ABOUTDEMO$=..
"This demo features both the core BlitzMax package and optional MaxGUI module.~n~n"+..
"Please note that the MaxGUI module must be purchased separately."

Const FILTERS$="Code Files:bmx,bbdoc,txt,vp,doc,plist,bb,cpp,c,m,cxx,s,fs,vs,p,fp,glsl,h,hpp,html,htm,css,js,bat;All Files:*"

Const NodeFileTypes$="|bmx|bbdoc|cpp|cxx|c|m|h|s|fs|vs|p|fp|glsl|txt|html|js|css|bb|java|bat|ini|jpg|png|bmp|tga|wav|pl|doc|plist|"

Global MODOPTIONS$[]=["BRL","PUB","AXE"]		',"MAK","GMAN","BIRDIE"]
Global MODINFO$[]=["BlitzMax Core Modules","Public Domain Core Modules","User Contributed Modules"]	'"Mark Sibly's Module Collection","Simon Armstrong's Module Collection","Garrit Grandberg's Module Collection","Dave Bird's Module Collection"]

?MacOS
Const DEFAULTFONT$="Courier"
Const DEFAULTFONTSIZE=12
Const HOMEPAGE$="/doc/index.html"
?
?Win32
Const DEFAULTFONT$="Courier"
Const DEFAULTFONTSIZE=10
Const HOMEPAGE$="/doc/index.html"
?
?Linux
Const DEFAULTFONT$="Lucida"
Const DEFAULTFONTSIZE=12
Const HOMEPAGE$="/doc/index.html"
'Const HOMEPAGE$="/doc/home.html"
?

Const MENUNEW=1
Const MENUOPEN=2
Const MENUCLOSE=3
Const MENUSAVE=4
Const MENUSAVEAS=5
Const MENUSAVEALL=6
Const MENUPRINT=7
Const MENUQUIT=8

Const MENUUNDO=9
Const MENUREDO=10
Const MENUCUT=11
Const MENUCOPY=12
Const MENUPASTE=13
Const MENUSELECTALL=14
Const MENUGOTO=15
Const MENUINDENT=16
Const MENUOUTDENT=17
Const MENUFIND=18
Const MENUFINDNEXT=19
Const MENUREPLACE=20
Const MENUNEXT=21
Const MENUPREV=22
Const MENUBUILD=23
Const MENURUN=24

Const MENUSTEP=25
Const MENUSTEPIN=26
Const MENUSTEPOUT=27
Const MENUSTOP=28

Const MENULOCKBUILD=29
Const MENUUNLOCKBUILD=30
Const MENUBUILDMODULES=31
Const MENUBUILDALLMODULES=32

Const MENUQUICKENABLED=33
Const MENUDEBUGENABLED=34
Const MENUGUIENABLED=35

Const MENUCOMMANDLINE=36
Const MENUSYNCMODS=37
Const MENUIMPORTBB=38
Const MENUFINDINFILES=39
Const MENUPROJECTMANAGER=40
Const MENUSHOWCONSOLE=41
Const MENUOPTIONS=42

Const MENUHOME=43
Const MENUBACK=44
Const MENUFORWARD=45
Const MENUQUICKHELP=46
Const MENUABOUT=47

Const MENUNEWVIEW=48
Const MENUDOCMODS=49

Const MENUTRIGGERDOCMODS=50
Const MENUTRIGGERSYNCDOCS=51

Const MENUCLOSEALL=53

Const MENURECENT=256

Const TAB$=Chr(9)
Const QUOTES$=Chr(34)

Global TEMPCOUNT
Global is_demo
Global codeplay:TCodePlay

Function CheckDemo()
	If Not is_demo Return 1
	Notify "This feature is unavailable in the demo version of BlitzMax"
	Return 0
End Function

codeplay=New TCodePlay
codeplay.Initialize

While codeplay.running
	codeplay.poll
Wend

End

Function Quote$(a$)		'add quotes to arg if spaces found
	Local	p
	If a.length=0 Return
	If a[0]=34 Return a	'already quoted
	p=a.find(" ")
	If p=-1 Return a	'no spaces
	Return Chr(34)+a+Chr(34)		
End Function

Type TToken
	Field token$
	Field help$
	Field ref$	
	Method Create:TToken(t$,h$,r$)
		token=t
		help=h
		ref=r
		Return Self
	End Method
End Type

Type TQuickHelp
	Field map:TMap=New TMap	'key=lower(token) value=token:TToken
		
	Method AddCommand:TQuickHelp(t$,l$,a$)
		map.Insert Lower(t$),New TToken.Create(t$,l$,a$)
	End Method
	
	Method Token$(cmd$)
		Local t:TToken
		t=TToken(map.ValueForKey(cmd.toLower()))
		If t Return t.token
	End Method
	
	Method Help$(cmd$)
		Local t:TToken
		t=TToken(map.ValueForKey(cmd.toLower()))
		If t Return t.help
	End Method
	
	Method Link$(cmd$)
		Local t:TToken
		t=TToken(map.ValueForKey(cmd.toLower()))
		If t Return t.ref
	End Method
	
	Function LoadCommandsTxt:TQuickHelp(bmxpath$)
		Local	stream:TStream
		Local	qh:TQuickHelp
		Local	l$,c$,p,q
		Local	token$,help$,anchor$
		
		stream=ReadFile(bmxpath+"/doc/bmxmods/commands.txt")
		If stream=Null Return Null
		qh=New TQuickHelp
		While Not Eof(stream)
			l$=ReadLine(stream)
			Local i
			For i=0 Until l.length
				Local c=l[i]
				If c=Asc("_") Continue
				If c>=Asc("0") And c<=Asc("9") Continue
				If c>=Asc("a") And c<=Asc("z") Continue
				If c>=Asc("A") And c<=Asc("Z") Continue
				Exit
			Next
			token$=l[..i]
			help$=""
			anchor$=""
			q=l.find("|")
			If q
				help=l[..q]
				anchor=l[q+1..]
			EndIf			
			qh.AddCommand token,help,anchor
		Wend
		stream.Close
		Return qh
	End Function
End Type

Const TOOLSHOW=1
Const TOOLREFRESH=2
Const TOOLNEW=3
Const TOOLOPEN=4
Const TOOLCLOSE=5
Const TOOLSAVE=6
Const TOOLHELP=7
Const TOOLUNDO=8
Const TOOLREDO=9
Const TOOLCUT=10
Const TOOLCOPY=11
Const TOOLPASTE=12
Const TOOLQUICKSAVE=13
Const TOOLSAVEAS=14
Const TOOLGOTO=15
Const TOOLFIND=16
Const TOOLFINDNEXT=17
Const TOOLREPLACE=18
Const TOOLBUILD=19
Const TOOLRUN=20
Const TOOLLOCK=21
Const TOOLUNLOCK=22
Const TOOLSELECT=23
Const TOOLSELECTALL=24
Const TOOLINDENT=25
Const TOOLOUTDENT=26
Const TOOLACTIVATE=27
Const TOOLNAVIGATE=28
Const TOOLNEWVIEW=29
Const TOOLMENU=30
Const TOOLPRINT=31

Type TTool
	Method Invoke(command,argument:Object=Null)
	End Method
End Type

Type TRequester
	Field	host:TCodePlay
	Field	window:TGadget,ok:TGadget,cancel:TGadget
	Field	centered

	Method initrequester(owner:TCodeplay,label$,w=280,h=128,flags=3)
		host=owner
		window=CreateWindow(label,0,0,w,h,Null,1+64)
		If flags&1 cancel=CreateButton("Cancel",8,ClientHeight(window)-34,80,24,window,BUTTON_CANCEL)
		If flags&2 ok=CreateButton("OK",ClientWidth(window)-88,ClientHeight(window)-34,80,24,window,BUTTON_OK)
	End Method
	
	Method Show()
		Local	x,y,w,h,win:TGadget
		DisableGadget host.window
		If Not centered
			win=host.window		
			w=GadgetWidth(window)
			h=GadgetHeight(window)
			x=GadgetX(win)+(GadgetWidth(win)-w)/2
			y=GadgetY(win)+(GadgetHeight(win)-h)/2
			SetGadgetShape window,x,y,w,h
			centered=True
		EndIf
		ShowGadget window
		ActivateGadget window
		host.SetRequester Self
		PollSystem
	End Method
	
	Method Hide()
		EnableGadget host.window
		HideGadget window
		host.SetRequester Null
'		host.SelectPanel host.currentpanel
	End Method

	Method Poll()
	End Method
End Type

Type TProgressRequester Extends TRequester
	Field	message$,value
	Field	showing
	Field	label:TGadget
	Field	progbar:TGadget
	
	Method Show()	'returns false if cancelled
		showing=True
		Super.Show
	End Method
	
	Method Hide()
		showing=False
		Super.Hide()
	End Method
	
	Method Open(title$)
		SetGadgetText window,title
		Show
	End Method
	
	Method Update(msg$,val)
		If msg$<>message
			message=msg
			If label FreeGadget label
			label=CreateLabel(message,8,8,260,20,window)
		EndIf
		If showing And (val&$fc)<>(value&$fc)	'only update every 4 percent
			UpdateProgBar( progbar,val/100.0 )
			PollSystem
		EndIf
		value=val
	End Method
	
	Function Create:TProgressRequester(host:TCodePlay)
		Local	progress:TProgressRequester
		progress=New TProgressRequester
		progress.initrequester(host,"ProgressRequester",280,128,1)	'1 for cancel button
		progress.progbar=CreateProgBar( 8,32,260,20,progress.window )
		Return progress
	End Function
End Type

Type TPanelRequester Extends TRequester
	Field	tabber:TGadget
	Field	panels:TGadget[]
	Field	index
	
	Method InitPanelRequester(owner:TCodeplay,label$,w=280,h=128)		
		InitRequester owner,label,w,h
		w=ClientWidth(window)
		h=ClientHeight(window)-40
		tabber=CreateTabber(4,4,w-8,h-8,window)
		SetGadgetLayout tabber,1,1,1,1
	End Method

	Method SetPanelIndex(i)
		HideGadget panels[index]
		index=i
		ShowGadget panels[index]
		SelectGadgetItem tabber,index	
	End Method
	
	Method SetPanel(panel:TGadget)
		Local	p:TGadget,i
		For p=EachIn panels
			If p=panel SetPanelIndex i;Exit
			i:+1
		Next
	End Method
	
	Method AddPanel:TGadget(name$)
		Local	panel:TGadget
		panel=CreatePanel(0,0,ClientWidth(tabber),ClientHeight(tabber),tabber)
		SetGadgetLayout panel,1,1,1,1
		HideGadget panel
		AddGadgetItem tabber,name
		panels=panels[..panels.length+1]
		panels[panels.length-1]=panel
		Return panel
	End Method
	
	Method RemovePanel(panel)
	End Method
	
End Type

Type TCmdLineRequester Extends TRequester
	Field	label:TGadget,textfield:TGadget

	Method Poll()
		Local	id,data
		id=EventID()
		data=EventData()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				host.SetCommandLine TextFieldText(textfield)
				Hide				
			Case cancel
				SetGadgetText textfield,host.GetCommandLine()
				Hide
		End Select
	End Method
	
	Method Show()
		SetGadgetText textfield,host.GetCommandLine()
		Super.Show()
		ActivateGadget textfield
	End Method

	Function Create:TCmdLineRequester(host:TCodePlay)
		Local	cmd:TCmdLineRequester
		cmd=New TCmdLineRequester
		cmd.initrequester(host,"Program Command Line")
		cmd.label=CreateLabel("Program command line:",8,8,260,20,cmd.window)
		cmd.textfield=CreateTextField(8,32,260,20,cmd.window)
		Return cmd
	End Function
End Type

Type TGotoRequester Extends TRequester
	Field	linenumber:TGadget

	Method Show()
		Super.Show()
		ActivateGadget linenumber
	End Method

	Method Poll()
		Local	line,data
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				line=Int(TextFieldText(linenumber))
				Hide
				host.activepanel.Invoke TOOLGOTO,String(line)
			Case cancel
				Hide
		End Select
	End Method

	Function Create:TGotoRequester(host:TCodePlay)
		Local	seek:TGotoRequester
		seek=New TGotoRequester
		seek.initrequester(host,"Goto Line",260,128)
		CreateLabel("Line Number:",20,24,114,20,seek.window)
		seek.linenumber=CreateTextField(134,20,100,20,seek.window)
		Return seek
	End Function
End Type

Type TColor
	Field	red,green,blue

	Method Set(rgb)
		red=(rgb Shr 16)&255
		green=(rgb Shr 8)&255
		blue=rgb&255
	End Method

	Method ToString$()
		Return ""+red+","+green+","+blue
	End Method

	Method FromString(s$)
		Local	p,q
		p=s.Find(",")+1
		If Not p Return
		q=s.Find(",",p)+1
		If Not q Return
		red=Int(s[..p-1])
		green=Int(s[p..q-1])
		blue=Int(s[q..])
	End Method

	Method Request()
		If RequestColor(red,green,blue)
			red=RequestedRed()
			green=RequestedGreen()
			blue=RequestedBlue()
			Return True
		EndIf				
	End Method	
End Type

Type TTextStyle
	Field	label:TGadget,panel:TGadget,combo:TGadget
	Field	color:TColor
	Field	flags
	
	Method Set(rgb,bolditalic)
		color.set(rgb)
		flags=bolditalic
	End Method

	Method Format(textarea:TGadget,pos,length)
		FormatTextAreaText textarea,color.red,color.green,color.blue,flags,pos,length
	End Method

	Method ToString$()
		Return ""+color.red+","+color.green+","+color.blue+","+flags
	End Method

	Method FromString(s$)
		Local	p,q,r
		p=s.Find(",")+1;If Not p Return
		q=s.Find(",",p)+1;If Not q Return
		r=s.Find(",",q)+1;If Not r Return
		color.red=Int(s[..p-1])
		color.green=Int(s[p..q-1])
		color.blue=Int(s[q..r-1])
		flags=Int(s[r..])
	End Method

	Method Poll()
		Select EventSource()
			Case panel
				If EventID()=EVENT_MOUSEDOWN
					Return color.Request()
				EndIf
			Case combo
				flags=SelectedGadgetItem(combo)
				Return True
		End Select
	End Method
	
	Method Refresh()
		SetPanelColor panel,color.red,color.green,color.blue
		SelectGadgetItem combo,flags		
	End Method

	Function Create:TTextStyle(name$,xpos,ypos,window:TGadget)
		Local	s:TTextStyle
		s=New TTextStyle
		s.color=New TColor
		s.label=CreateLabel(name,xpos,ypos+4,80,24,window)
		s.panel=CreatePanel(xpos+84,ypos,24,24,window,PANEL_BORDER|PANEL_ACTIVE)
		SetPanelColor s.panel,255,255,0
		s.combo=CreateComboBox(xpos+112,ypos,96,24,window)
		AddGadgetItem s.combo,"Normal"
		AddGadgetItem s.combo,"Bold"
		AddGadgetItem s.combo,"Italic"
		AddGadgetItem s.combo,"Bold+Italic"
		Return s
	End Function
End Type

Type TGadgetStyle
	Field	label:TGadget,fpanel:TGadget,bpanel:TGadget,fbutton:TGadget
	Field	font_name$,font_size
	Field	fg:TColor
	Field	bg:TColor
	Field	font:TGUIFont

	Method Apply(gadget:TGadget)
		SetGadgetFont gadget,font
		SetGadgetColor gadget,bg.red,bg.green,bg.blue,True
		SetGadgetColor gadget,fg.red,fg.green,fg.blue,False
	End Method
	
	Method Set(fg_rgb,bg_rgb,fname$,fsize)
		fg.set(fg_rgb)
		bg.set(bg_rgb)
		font_name=fname
		font_size=fsize
	End Method

	Method ToString$()
		Return font_name+","+font_size+","+fg.ToString()+","+bg.ToString()
	End Method
	
	Function GetArg$(a$ Var)
		Local 	p,r$
		p=a.Find(",")+1
		If p=0 p=Len a$+1
		r$=a$[..p-1]
		a$=a$[p..]
		Return r$	
	End Function
	
	Method FromString(s$)		
		font_name=GetArg(s$)
		font_size=Int(GetArg(s$))
		fg.red=Int(GetArg(s$))
		fg.green=Int(GetArg(s$))
		fg.blue=Int(GetArg(s$))
		bg.red=Int(GetArg(s$))
		bg.green=Int(GetArg(s$))
		bg.blue=Int(GetArg(s$))
	End Method

	Method Poll()
		Local	f:TGUIFont
		Select EventSource()
			Case fpanel
				If EventID()=EVENT_MOUSEDOWN
					Return fg.Request()
				EndIf
			Case bpanel
				If EventID()=EVENT_MOUSEDOWN
					Return bg.Request()
				EndIf
			Case fbutton
				f=RequestFont(font)
				If f
					font_name=FontName(f)
					font_size=FontSize(f)
					Return True
				EndIf				
		End Select
	End Method
	
	Method Refresh()
		font=LoadGuiFont(font_name,font_size)
		SetPanelColor fpanel,fg.red,fg.green,fg.blue
		SetPanelColor bpanel,bg.red,bg.green,bg.blue
		SetGadgetText fbutton,font_name+":"+font_size
	End Method

	Function Create:TGadgetStyle(name$,xpos,ypos,window:TGadget)
		Local	s:TGadgetStyle
		s=New TGadgetStyle
		s.fg=New TColor
		s.bg=New TColor
		s.label=CreateLabel(name,xpos,ypos+4,56,24,window)
		s.fpanel=CreatePanel(xpos+58,ypos,24,24,window,PANEL_BORDER|PANEL_ACTIVE)
		s.bpanel=CreatePanel(xpos+86,ypos,24,24,window,PANEL_BORDER|PANEL_ACTIVE)
		s.fbutton=CreateButton("..",xpos+112,ypos,180,24,window)
		Return s
	End Function
End Type

Const NORMAL=0
Const COMMENT=1
Const QUOTED=2
Const KEYWORD=3

Type TOptionsRequester Extends TPanelRequester
' panels
	Field	optionspanel:TGadget,editorpanel:TGadget,toolpanel:TGadget
' settings
	Field	showtoolbar,restoreopenfiles,autocapitalize,syntaxhighlight,autobackup,autoindent,hideoutput,externalhelp
	Field	tabsize
	Field	editfontname$,editfontsize,editcolor:TColor
	Field	outputfontname$,outputfontsize,outputcolor:TColor
' states
	Field	editfont:TGUIFont
' gadgets
	Field	tabbutton:TGadget
	Field	editpanel:TGadget,editbutton:TGadget
	Field	buttons:TGadget[9]
	Field	styles:TTextStyle[4]
	Field	textarea:TGadget
	Field	outputstyle:TGadgetStyle
	Field	navstyle:TGadgetStyle
	Field	navswapbutton:TGadget,navswap
	Field	dirty
	Field	undo:TBank
	
	Method Snapshot()
		If Not undo undo=CreateBank(8192)
		Local stream:TStream=CreateBankStream(undo)
		write stream
		stream.close
	End Method
	
	Method Restore()
		If Not undo Return
		Local stream:TStream=CreateBankStream(undo)
		Read stream
		stream.close
	End Method

	Method SetDefaults()
		showtoolbar=True
		restoreopenfiles=True
		autocapitalize=True
		syntaxhighlight=True
		autobackup=True
		autoindent=True
		tabsize=4
		editfontname$=DEFAULTFONT
		editfontsize=DEFAULTFONTSIZE
		editcolor.set($01516b)
		styles[NORMAL].set($ffffff,0)
		styles[COMMENT].set($b1e7eb,0)
		styles[QUOTED].set($ff66,0)
		styles[KEYWORD].set($ffff00,0)
		outputstyle.set(0,-1,DEFAULTFONT,DEFAULTFONTSIZE)
		navstyle.set(0,-1,DEFAULTFONT,DEFAULTFONTSIZE)
		navswap=0
		RefreshGadgets
	End Method

	Method Write(stream:TStream)
		Local i
		stream.WriteLine "[Options]"
		stream.WriteLine "showtoolbar="+showtoolbar
		stream.WriteLine "restoreopenfiles="+restoreopenfiles
		stream.WriteLine "autocapitalize="+autocapitalize
		stream.WriteLine "syntaxhighlight="+syntaxhighlight
		stream.WriteLine "autobackup="+autobackup		
		stream.WriteLine "autoindent="+autoindent		
		stream.WriteLine "tabsize="+tabsize
		stream.WriteLine "editfontname="+editfontname		
		stream.WriteLine "editfontsize="+editfontsize		
		stream.WriteLine "editcolor="+editcolor.ToString()		
		stream.WriteLine "normal_style="+styles[0].ToString()		
		stream.WriteLine "comment_style="+styles[1].ToString()		
		stream.WriteLine "quote_style="+styles[2].ToString()		
		stream.WriteLine "keyword_style="+styles[3].ToString()		
		stream.WriteLine "output_style="+outputstyle.ToString()
		stream.WriteLine "nav_style="+navstyle.ToString()
		stream.WriteLine "nav_swap="+navswap
		stream.WriteLine "hide_output="+hideoutput
		stream.WriteLine "external_help="+externalhelp
	End Method

	Method Read(stream:TStream)
		Local	f$,p,a$,b$,t
		While Not stream.Eof()
			f$=stream.ReadLine()
			If f$="" Or (f$[..1]="[" And f$<>"[Options]") Exit
			p=f.find("=")
			a$=f[..p]
			b$=f[p+1..]
			t=Int(b)
			Select a$
				Case "showtoolbar" showtoolbar=t
				Case "restoreopenfiles" restoreopenfiles=t
				Case "autocapitalize" autocapitalize=t
				Case "syntaxhighlight" syntaxhighlight=t
				Case "autobackup" autobackup=t
				Case "autoindent" autoindent=t
				Case "tabsize" tabsize=t		
				Case "editfontname" editfontname=b
				Case "editfontsize" editfontsize=t
				Case "editcolor" editcolor.FromString(b)		
				Case "normal_style" styles[0].FromString(b)
				Case "comment_style" styles[1].FromString(b)
				Case "quote_style" styles[2].FromString(b)
				Case "keyword_style" styles[3].FromString(b)
				Case "output_style" outputstyle.FromString(b)
				Case "nav_style" navstyle.FromString(b)
				Case "nav_swap" navswap=t
				Case "hide_output" hideoutput=t
				Case "external_help" externalhelp=t
			End Select
		Wend		
		RefreshGadgets
	End Method
	
	Method RefreshGadgets()
		Local	i,rgb:TColor
		editfont=LoadGuiFont(editfontname,editfontsize)
		SetButtonState buttons[0],showtoolbar
		SetButtonState buttons[1],restoreopenfiles
		SetButtonState buttons[2],autocapitalize
		SetButtonState buttons[3],syntaxhighlight
		SetButtonState buttons[4],autobackup
		SetButtonState buttons[5],autoindent
		SetButtonState buttons[6],hideoutput
		SetButtonState buttons[7],externalhelp
		SelectGadgetItem tabbutton,Min(Max(tabsize/2-1,0),7)
		SetPanelColor editpanel,editcolor.red,editcolor.green,editcolor.blue
		SetGadgetText editbutton,editfontname+":"+editfontsize
		For i=0 To 3
			styles[i].Refresh
		Next
		LockTextArea textarea
		SetTextAreaColor textarea,editcolor.red,editcolor.green,editcolor.blue,True
		SetGadgetFont textarea,editfont
		styles[0].format(textarea,0,-1)
		styles[1].format(textarea,0,17)
		styles[2].format(textarea,26,8)
		styles[3].format(textarea,36,5)
		UnlockTextArea textarea
		outputstyle.Refresh
		navstyle.Refresh
		SelectGadgetItem navswapbutton,Min(Max(navswap,0),1)
		dirty=True
	End Method

	Method Poll()
		Local	i,font:TGUIFont,refresh
		For i=0 To 3
			refresh=refresh|styles[i].Poll()
		Next
		refresh=refresh|outputstyle.Poll()
		refresh=refresh|navstyle.Poll()
		If EventSource()=buttons[0] showtoolbar=ButtonState(buttons[0]);dirty=True
		If EventSource()=buttons[1] restoreopenfiles=ButtonState(buttons[1])
		If EventSource()=buttons[2] autocapitalize=ButtonState(buttons[2]);dirty=True
		If EventSource()=buttons[3] syntaxhighlight=ButtonState(buttons[3]);dirty=True
		If EventSource()=buttons[4] autobackup=ButtonState(buttons[4])
		If EventSource()=buttons[5] autoindent=ButtonState(buttons[5])
		If EventSource()=buttons[6] hideoutput=ButtonState(buttons[6])
		If EventSource()=buttons[7] externalhelp=ButtonState(buttons[7])
		Select EventSource()
			Case tabber
				SetPanelIndex SelectedGadgetItem(tabber)
			Case ok
				Hide
				If dirty host.RefreshAll
				dirty=False
				SnapShot
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Restore
					dirty=False
					Hide
				EndIf
			Case cancel
				Restore
				dirty=False
				Hide
			Case tabbutton
				tabsize=(SelectedGadgetItem(tabbutton)+1)*2
				refresh=True
			Case editpanel
				If EventID()=EVENT_MOUSEDOWN
					refresh=editcolor.Request()
				EndIf
			Case editbutton
				font=RequestFont(editfont)
				If font
					editfontname=FontName(font)
					editfontsize=FontSize(font)
					refresh=True
				EndIf
			Case navswapbutton
				navswap=SelectedGadgetItem(navswapbutton)
				refresh=True
		End Select
		If refresh RefreshGadgets
	End Method
	
	Method InitOptionsRequester(host:TCodePlay)		
		Local	w:TGadget
'		o=New TOptionsRequester
		InitPanelRequester(host,"Options",320,440)
' init values
		editcolor=New TColor
' init gadgets
		optionspanel=AddPanel("Options")
		editorpanel=AddPanel("Editor")
		toolpanel=AddPanel("Tools")

		w=optionspanel
		buttons[0]=CreateButton("Show ToolBar",10,10,280,24,w,2)
		buttons[1]=CreateButton("Open Files At Startup",10,34,280,24,w,2)
		buttons[2]=CreateButton("Auto Capitalize",10,58,280,24,w,2)
		buttons[3]=CreateButton("Syntax Highlighting",10,82,280,24,w,2)
		buttons[4]=CreateButton("Auto Backup",10,106,280,24,w,2)
		buttons[5]=CreateButton("Auto Indent",10,130,280,24,w,2)
		buttons[6]=CreateButton("Hide Output When Process Complete",10,154,280,24,w,2)
		buttons[7]=CreateButton("Use External Help Browser",10,178,280,24,w,2)

		w=editorpanel
		CreateLabel("Background",4,12+4,80,24,w)
		editpanel=CreatePanel(88,12,24,24,w,PANEL_BORDER|PANEL_ACTIVE)
		editbutton=CreateButton("..",116,12,180,24,w)

		styles=New TTextStyle[4]
		styles[0]=TTextStyle.Create("PlainText:",4,40,w)
		styles[1]=TTextStyle.Create("Remarks:",4,68,w)
		styles[2]=TTextStyle.Create("Strings:",4,96,w)
		styles[3]=TTextStyle.Create("KeyWords:",4,124,w)		
		
		tabbutton=CreateComboBox(20,180,128,24,w)
		For Local i=1 To 8
			AddGadgetItem tabbutton,"TabSize="+(i*2)
		Next
		
		textarea=CreateTextArea(10,220,ClientWidth(w)-20,140,w,TEXTAREA_READONLY)
		SetTextAreaText textarea,"' Example Listing~n~nname$=~qBlitzMax~q~nPrint name$~n"

		w=toolpanel
		outputstyle=TGadgetStyle.Create("Output",4,12,w)
		navstyle=TGadgetStyle.Create("Navbar",4,40,w)

		navswapbutton=CreateComboBox(20,66,128,24,w)
		AddGadgetItem navswapbutton,"Navbar on right"
		AddGadgetItem navswapbutton,"Navbar on left"

		SetDefaults()
		SetPanel optionspanel
		
		SnapShot
	End Method
	
	Function Create:TOptionsRequester(host:TCodePlay)
		Local	o:TOptionsRequester
		o=New TOptionsRequester
		o.InitOptionsRequester host
		Return o
	End Function
	
End Type

Type TFindRequester Extends TRequester
	Field	findterm:TGadget
	
	Method ShowFind(term$="")
		If term SetGadgetText(findterm,term)
		Super.Show()
		ActivateGadget findterm
	End Method

	Method Poll()
		Local	find$,data		
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf				
			Case ok
				find=TextFieldText(findterm)
				Hide
				PollSystem
				host.activepanel.Invoke TOOLFINDNEXT,find
			Case cancel
				Hide
		End Select
	End Method

	Function Create:TFindRequester(host:TCodePlay)
		Local	seek:TFindRequester
		seek=New TFindRequester
		seek.initrequester(host,"Find",280,128)
		CreateLabel("Find What",8,16,80,24,seek.window)
		seek.findterm=CreateTextField(88,12,180,20,seek.window)
		Return seek
	End Function
End Type

Type TReplaceRequester Extends TRequester
	Field	findterm:TGadget,replaceterm:TGadget
	Field	findnext:TGadget,replaceit:TGadget,replaceall:TGadget
	
	Method Show()
		Super.Show()
		ActivateGadget findterm
	End Method

	Method Poll()
		Local	find$,Replace$
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				Hide
			Case cancel
				Hide
			Case findnext
				find=TextFieldText(findterm)
				host.activepanel.Invoke TOOLFINDNEXT,find
			Case replaceit
				Replace=TextFieldText(replaceterm)
				If host.activepanel.Invoke(TOOLREPLACE,Replace)
					host.activepanel.Invoke TOOLFINDNEXT,find
				EndIf				
			Case replaceall
				find=TextFieldText(findterm)
				Replace=TextFieldText(replaceterm)
				host.activepanel.Invoke TOOLREPLACE,find+Chr(0)+Replace
		End Select
	End Method

	Function Create:TReplaceRequester(host:TCodePlay)
		Local x,y
		Local	seek:TReplaceRequester
		seek=New TReplaceRequester
		seek.initrequester(host,"Find and Replace",380,200)
		
		y=14
		CreateLabel( "Find What",8,y+4,88,24,seek.window )
		seek.findterm=CreateTextField( 96,y,168,20,seek.window )

		y:+32		
		CreateLabel( "Replace With",8,y+4,88,24,seek.window )
		seek.replaceterm=CreateTextField( 96,y,168,20,seek.window )

		x=ClientWidth(seek.window)-104
		y=12
		seek.findnext=CreateButton("Find Next",x,y,96,24,seek.window)
		seek.replaceit=CreateButton("Replace",x,y+32,96,24,seek.window)
		seek.replaceall=CreateButton("Replace All",x,y+64,96,24,seek.window)
		Return seek
	End Function
End Type

Type TSyncModsRequester Extends TRequester
	Field	label:TGadget,user:TGadget,password:TGadget,proxy:TGadget
	Field	options:TGadget[]

	Method SyncMods()
		Local	u$,p$,x$,cmd$,i,n
		u$=quote(TextFieldText(user))
		p$=quote(TextFieldText(password))
		x$=TextFieldText(proxy)
		cmd$=quote(host.bmxpath+"/bin/syncmods")
		cmd$:+" -u "+u$+" -p "+p$
		If x cmd$:+" -y "+x
		n=MODOPTIONS.length
		For Local i=0 Until n
			If ButtonState(options[i]) cmd$:+" "+MODOPTIONS[i]
		Next			
		Hide
		host.execute cmd,"Synchronize Modules"',MENUTRIGGERDOCMODS
	End Method
	
	Method Poll()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				SyncMods
			Case cancel
				Hide
		End Select
	End Method
	
	Method Show()
		Super.Show()
		ActivateGadget user
	End Method

	Function Create:TSyncModsRequester(host:TCodePlay)
		Local	sync:TSyncModsRequester
		Local m$
		
		m$=LoadString("incbin::syncmodsblurb.txt")
		
		sync=New TSyncModsRequester
		sync.initrequester(host,"Synchronize modules",420,420)

'		sync.label=CreateLabel(m$,8,20,380,160,sync.window)
		sync.label=CreateTextArea(8,8,400,160,sync.window,TEXTAREA_READONLY|TEXTAREA_WORDWRAP)
		SetGadgetText sync.label,m$
		
		Local i,n,y

		y=180
		
		CreateLabel("Username",20,y+4,80,24,sync.window)
		sync.user=CreateTextField(108,y,160,20,sync.window)
		y:+30

		CreateLabel("Password",20,y+4,80,24,sync.window)
		sync.password=CreateTextField(108,y,160,20,sync.window,TEXTFIELD_PASSWORD)		
		y:+30

		CreateLabel("Proxy Server",20,y+4,80,24,sync.window)
		sync.proxy=CreateTextField(108,y,160,20,sync.window)		
		y:+30
		
		n=MODOPTIONS.length
		sync.options=New TGadget[n]
		For Local i=0 Until n
			sync.options[i]=CreateButton(MODOPTIONS[i],20,y,60,24,sync.window,BUTTON_CHECKBOX)
			If i<2 
				SetButtonState sync.options[i],True
				DisableGadget sync.options[i]
			EndIf
			CreateLabel MODINFO[i],80,y+4,220,24,sync.window
			y:+26
		Next
				
		Return sync
	End Function
	
	Function GetArg$(a$ Var)
		Local 	p,r$
		p=a.Find(",")+1
		If p=0 p=Len a$+1
		r$=a$[..p-1]
		a$=a$[p..]
		Return r$	
	End Function

	Function Crypt$(a$)
		Local b$,c:Byte,i
		For i=0 Until Len a
			c=a[i]
			If c>63 And c<192 c:~(i*-41)&63
			b:+Chr(c)
		Next
		Return b
	End Function
			
	Method FromString(s$)
		Local a$,i,n	
		SetGadgetText user,GetArg(s$)
		SetGadgetText password,Crypt(GetArg(s$))
		SetGadgetText proxy,GetArg(s$)
		n=MODOPTIONS.length
		While s$
			a$=GetArg(s$)
			For Local i=2 Until n
				If a$=MODOPTIONS[i] SetButtonState options[i],True
			Next
		Wend
	End Method
	
	Method ToString$()
		Local sync$,i,n
		sync=TextFieldText(user)
		sync:+","+Crypt(TextFieldText(password))
		sync:+","+TextFieldText(proxy)
		n=MODOPTIONS.length
		For Local i=2 Until n
			If ButtonState(options[i]) sync:+","+MODOPTIONS[i]
		Next
		Return sync
	End Method
End Type

Type TEventHandler Extends TTool
	Method OnEvent() Abstract
End Type

Type TSplitter Extends TEventHandler
	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

Type TToolPanel Extends TEventHandler
	Field	name$,path$
	Field	panel:TGadget
	Field	index
	Field	active
	
	Method Show()
	End Method
End Type

Type TView
	Field	node:TGadget,state
End Type

Type TNode Extends TTool
	Const	HIDESTATE=0
	Const	CLOSEDSTATE=1
	Const	OPENSTATE=2

	Field	name$,sortname$
	Field	parent:TNode
	Field	kids:TList=New TList
	Field	views:TView[]
' activate program	
	Field	target:TTool
	Field	action
	Field	argument:Object

	Method SortKids( ascending=True )
		Local term:TLink=kids._head
		Repeat
			Local link:TLink=kids._head._succ
			Local sorted=True
			Repeat
				Local succ:TLink=link._succ
				If succ=term Exit
				Local cc=TNode(link._value).sortname.Compare( TNode(succ._value).sortname )
				If (cc>0 And ascending) Or (cc<0 And Not ascending)
					Local link_pred:TLink=link._pred
					Local succ_succ:TLink=succ._succ
					link_pred._succ=succ
					succ._succ=link
					succ._pred=link_pred
					link._succ=succ_succ
					link._pred=succ
					succ_succ._pred=link
					sorted=False
				Else
					link=succ
				EndIf
			Forever
			If sorted Return
			term=link
		Forever
	End Method

	Method FindArgument:TNode(arg:Object)
		Local	n:TNode,r:TNode,a$
		If arg.Compare(argument)=0 Return Self
		a$=(String(arg)).ToLower()
		If a And a=(String(argument)).toLower() Return Self
		For n=EachIn kids
			r=n.FindArgument(arg)
			If r Return r
		Next
	End Method
	
	Method Dump(indent$="")
		Local	n:TNode		
		Print indent+name
		indent:+"~t"
		For n=EachIn kids
			n.Dump indent
		Next
	End Method		
	
	Method IsHidden()
		Local	v:TView
		If Not parent Return False
		For v=EachIn parent.views
			If v.state=OPENSTATE Return False
		Next
		Return True
	End Method
	
	Method SetAction(tool:TTool,cmd,arg:Object=Null)
		target=tool
		action=cmd
		argument=arg
	End Method

	Method Hide(v:TView=Null)	'null means hide in all views
		Local	n:TNode
		For n=EachIn kids
			n.hide v
		Next
		If v
			If v.node FreeTreeViewNode v.node;v.node=Null
		Else
			For v=EachIn views
				If v.node FreeTreeViewNode v.node;v.node=Null
			Next
		EndIf
	End Method
	
	Method Detach()
		Hide
		If parent parent.kids.remove Self
		parent=Null
	End Method

	Method FreeKids()
		Local	n:TNode		
		For n=EachIn kids
			n.free
		Next
	End Method
			
	Method Free()
		Local	n:TNode		
		For n=EachIn kids
			n.free
		Next
		Detach		'Hide()
		views=Null
	End Method
	
	Method Invoke(command,arg:Object=Null)
		Select command
		Case TOOLACTIVATE 
			If target Return target.Invoke(action,argument)
		End Select
	End Method
	
	Method Find:TNode(treeviewnode:TGadget,view=0)
		Local	n:TNode,r:TNode
		Local	v:TView
		v=getview(view)
		If v And v.node=treeviewnode Return Self
		For n=EachIn kids
			r=n.Find(treeviewnode,view)
			If r Return r
		Next
	End Method
	
	Method SetNode(treeviewnode:TGadget,view=0)
		Local	v:TView
		v=getview(view)
		v.node=treeviewnode
		open view
	End Method
	
	Method HighLight(view=-1)
		Local	v:TView
		If view=-1
			For view=0 To views.length
				HighLight view
			Next
			Return
		EndIf
		v=GetView(view)
		If v.node SelectTreeViewNode v.node
	End Method
	
	Method Open(view=-1)
		Local	v:TView
		If view=-1
			For view=0 To views.length
				Open view
			Next
			Return
		EndIf
		v=GetView(view)
		If v.state<>OPENSTATE
			v.state=OPENSTATE
			RefreshView view
'			if v.node ExpandTreeViewNode v.node
		EndIf
	End Method
	
	Method Close(view=0)
		Local	v:TView
		v=GetView(view)
		If v.state<>CLOSEDSTATE
			v.state=CLOSEDSTATE
'			if v.node CollapseTreeViewNode v.node
		EndIf
	End Method
	
	Method GetState(view=0)
		Local	v:TView
		v=GetView(view)
		Return v.state
	End Method

	Method GetView:TView(view=0)
		If view>=views.length 
			views=views[..view+1]
			views[view]=New TView
		EndIf
		If views[view]=Null views[view]=New TView
		Return views[view]
	End Method
	
	Method GetIndex()
		Local	node:TNode
		Local	i		
		If parent
			For node=EachIn parent.kids
				If node=Self Return i
				i:+1
			Next
		EndIf
	End Method
	
	Method Refresh()
		Local	i
		For i=0 To views.length-1
			RefreshView i
		Next
	End Method
	
	Method RefreshView(view=0)
		Local	n:TNode,quick
		Local	v:TView,vv:TView
		Local	node
		If parent And parent.getstate(view)=CLOSEDSTATE quick=True		
		v=getview(view)
		If v.node And parent
			ModifyTreeViewNode v.node,name
		Else
			If parent And name
				vv=parent.getview(view)
				If vv.node
'					v.node=AddTreeViewNode(name,vv.node)
					v.node=InsertTreeViewNode(GetIndex(),name,vv.node)
					If v.state=HIDESTATE v.state=CLOSEDSTATE					
					If vv.state=OPENSTATE ExpandTreeViewNode vv.node
					quick=False
				EndIf
			EndIf
		EndIf
		If quick Return
		If Not kids Return
		For n=EachIn kids
			n.RefreshView view
		Next
	End Method

	Method NodeAfter:TNode(node:TNode)
		Local	link:TLink
		If node	link=kids.FindLink(node)
		If link link=link.NextLink()
		If link Return TNode(link.Value())	
	End Method

	Method Sync(snap:TNode)
		Local	snapkid:TNode
		Local	currentkid:TNode
		Local	kid:TNode
		Local	t:TNode
		Local	link:TLink

		If snap.name<>name Return
		If kids.Count() currentkid=TNode(kids.First())
		For snapkid=EachIn snap.kids
' if same name in list 
			kid=currentkid
			While kid
				If kid.name=snapkid.name Exit
				kid=NodeAfter(kid)
			Wend
' then remove entries in front			
			If kid
				While currentkid<>kid
					t=currentkid
					currentkid=NodeAfter(currentkid)			
					t.free()
				Wend
			EndIf
' if same name sync else insert 
			If currentkid And currentkid.name=snapkid.name	'merge values if same name 
				currentkid.Sync snapkid
				currentkid=NodeAfter(currentkid)
			Else
				snapkid.detach
				If currentkid
					link=kids.FindLink(currentkid)
					kids.InsertBeforeLink snapkid,link
				Else
					kids.AddLast snapkid
				EndIf
				snapkid.parent=Self
			EndIf
		Next
' remove any entries at end
		While currentkid
			t=currentkid
			currentkid=NodeAfter(currentkid)			
			t.free()
		Wend
		Refresh()
	End Method

	Method SetName(n$)
		name=n
	End Method
		
	Method AddNode:TNode(name$)
		Local	v:TNode
		v=New TNode
		v.setname name
		Append v
		Return v
	End Method
	
	Method Append(v:TNode)
		v.parent=Self
		kids.AddLast v
	End Method	
	
	Function Create:TNode(name$)
		Local	node:TNode
		node=New TNode
		node.setname name
		Return node
	End Function		
End Type

Type THelpPanel Extends TToolPanel

	Field	host:TCodePlay
	Field	htmlview:TGadget
	Field root:TNode
	Field user:TNode
	Field  lang:TNode
	Field mods:TNode

	Method AddLink:TNode(parent:TNode,name$,href$)
		Local	n:TNode
		n=parent.AddNode(name)
		If href href=RealPath(href)
		n.SetAction(Self,TOOLNAVIGATE,href)
		Return n
	End Method
	
	Method ImportLinks(root:TNode,path$)
		Local	stream:TStream
		Local	c$,l$,p,q,a$,n$,cat
		Local	node:TNode
		
		stream=ReadFile(path)
		If Not stream Return
		path=ExtractDir(path)
		node=root
		While Not Eof(stream)
			c=ReadLine(stream)
			If c="" Continue
			If c.Find("Alphabetic index")<>-1
				node=AddLink(root,"Index","")
				Continue
			EndIf
			l=c.ToLower()
			l=l.Replace(QUOTES$,"'")
			p=l.Find("<a")
			If p=-1 Continue
			a$=""
			q=l.find("href=",p)+1
			If q
				If l[q+4]=39	'"'"
					p=q+5
					q=l.find("'",p)
				Else
					p=q+4
					q=l.find(" ",p)
				EndIf
				If q>p 
					a$=path+"/"+c[p..q]
				EndIf
			EndIf
			p=c.Find(">",q)+1
			If p And c[p]=60 p=c.Find(">",p)+1
			q=c.Find("<",p)
			If q<=p Continue
			n$=c[p..q]
'			print n$
			If l.find("onclick=toggle")<>-1
				node=AddLink(root,n$,a$)
			Else
				AddLink(node,n$,a$)
			EndIf
		Wend
		stream.Close
	End Method
	
	Method SyncDocs()
		mods.FreeKids
		AddLink(mods,"Welcome",host.bmxpath+"/doc/bmxmods/welcome.html")
		ImportLinks mods,host.bmxpath+"/doc/bmxmods/navbar.html"
		mods.Refresh
	End Method

	Method BuildTree()
		root=host.helproot
		user=root.AddNode("UserGuide")
		ImportLinks user,host.bmxpath+"/doc/bmxuser/navbar.html"
		lang=root.AddNode("Language")
		ImportLinks lang,host.bmxpath+"/doc/bmxlang/navbar.html"
		mods=root.AddNode("Modules")
		SyncDocs
		AddLink root,"Samples",host.bmxpath+"/samples/index.html"
		root.refresh
	End Method

	Method Invoke(command,argument:Object=Null)
		Local	href$
		If Not htmlview Return
		Select command
			Case TOOLCUT
				GadgetCut htmlview
			Case TOOLCOPY
				GadgetCopy htmlview
			Case TOOLPASTE
				GadgetPaste htmlview
			Case TOOLSHOW 
				ActivateGadget htmlview	
				host.SetTitle
			Case TOOLNAVIGATE
				href$=String(argument)
				If href Go href
			Case TOOLPRINT
				GadgetPrint htmlview
		End Select
	End Method

	Method OnEvent()
		Local	url$,p,t$
		If EventSource()=htmlview
			Select EventID()			
				Case EVENT_GADGETACTION				'NAVIGATEREQUEST
					url$=String( EventExtra() )
					If url[..5]="http:"
						OpenURL url
					Else
						p=url.findlast(".")
						If p>-1
							t$=url[p..].tolower()
							If t$=".bmx"
								If url.Find( "file://" )=0
									url=url[7..]
									?Win32
									url=url[1..]
									?
								EndIf 
								url=url.replace("%20"," ")
								Local source:TOpenCode=host.OpenSource(url)
								If source source.MakePathTemp
							Else 
								url=url.Replace("\","/")
								url=url.Replace("user/index","user/welcome")
								url=url.Replace("lang/index","lang/welcome")
								url=url.Replace("mods/index","mods/welcome")
								Go url$
							EndIf
						EndIf
					EndIf
			End Select			
		EndIf
	End Method
	
	Method Go(url$,internal=False)
		Local	node:TNode

		If host.options.externalhelp And Not internal
			PollSystem
			OpenURL url
			MinimizeWindow host.window
			PollSystem
			Return
		EndIf

		HtmlViewGo htmlview,url$
		host.SelectPanel Self
		node=host.helproot.FindArgument(RealPath(url))
		If node
			node.Highlight
		Else
'			print "node not found"
		EndIf		
		ActivateGadget htmlview			
	End Method
	
	Method Home()
		Go host.bmxpath+HOMEPAGE,True
	End Method
	
	Method Forward()
		HtmlViewForward htmlview
	End Method

	Method Back()
		HtmlViewBack htmlview
	End Method

	Function Create:THelpPanel(host:TCodePlay)
		Local	p:THelpPanel
		Local	root,style		
		p=New THelpPanel
		p.host=host
		p.name="Help"
		codeplay.addpanel(p)
		style=HTMLVIEW_NONAVIGATE		'HTMLVIEW_NOCONTEXTMENU
		p.htmlview=CreateHTMLView(0,0,ClientWidth(p.panel),ClientHeight(p.panel),p.panel,style)		
		SetGadgetLayout p.htmlview,1,1,1,1
'		p.Home
		p.buildtree
		Return p
	End Function

End Type

Type TSearchRequester Extends TRequester
	Field	findbox:TGadget,typebox:TGadget,pathbox:TGadget,pathbutton:TGadget

	Method Poll()
		Local	id,data,index
		id=EventID()
		data=EventData()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				Hide				
			Case cancel
				Hide
		End Select
	End Method

	Function Create:TSearchRequester(host:TCodePlay)
		Local	search:TSearchRequester
		search=New TSearchRequester
		search.initrequester(host,"Find In Files",400,256)

		CreateLabel("Find What",6,18,80,24,search.window)
		search.findbox=CreateTextField(88,14,180,20,search.window)

		CreateLabel("File Types",6,48,80,24,search.window)
		search.typebox=CreateTextField(88,44,180,20,search.window)

		CreateLabel("Search Path",6,78,80,24,search.window)
		search.pathbox=CreateTextField(88,74,180,20,search.window)

		Return search
	End Function
End Type

Type TProjectRequester Extends TRequester
	Field	projects:TProjects
	Field	listbox:TGadget,add:TGadget,remove:TGadget,props:TGadget

	Method Invoke(command,arg:Object=Null)
		Select command
		Case TOOLACTIVATE 
			Refresh
		End Select
	End Method

	Method Poll()
		Local	id,data,index
		id=EventID()
		data=EventData()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case add
				projects.AddProject
				Refresh
			Case remove
				projects.RemoveProject SelectedGadgetItem(listbox)
				Refresh
			Case ok
				Hide				
			Case cancel
				Hide
		End Select
	End Method

	Method Refresh()
		Local	node:TNode
		
		ClearGadgetItems listbox
		For node=EachIn projects.kids
			If TFolderNode(node)'node.argument
				AddGadgetItem listbox,node.name
			EndIf
		Next
	End Method
	
	Method Open(projnode:TProjects)
		projects=projnode
		Refresh
		Show
	End Method
	
	Function Create:TProjectRequester(host:TCodePlay)
		Local x,y
		Local	proj:TProjectRequester
		proj=New TProjectRequester
	
		proj.initrequester(host,"Project Manager",400,256)
		proj.listbox=CreateListBox( 8,8,248,184,proj.window )
		
		x=ClientWidth(proj.window)-136
		proj.add=CreateButton("Add Project",x,8,128,24,proj.window)
		proj.remove=CreateButton("Remove Project",x,40,128,24,proj.window)
		proj.props=CreateButton("Properties",x,72,128,24,proj.window)
		DisableGadget proj.props 
		Return proj
	End Function
End Type


Type TFolderNode Extends TNode
	Field	path$
	Field	scanned
	Field	owner:TNode

	Method Open(view=-1)
		If Not scanned
			ScanKids		'Path name,path
		EndIf
		Super.Open view
	End Method

	Method AddFileNode:TNode(file$)
		Local	n:TNode
		Local 	ext$
		
		If NodeFileTypes.find("|"+ExtractExt(file).toLower()+"|")<0 Return
		n=AddNode(StripDir(file))
		n.SetAction(owner,TOOLOPEN,file)
		ext=ExtractExt(file$).ToLower()
		n.sortname=ext+n.name
		Return n
	End Method

	Method AddFolderNode:TNode(path$)
		Local	n:TNode
		n=TFolderNode.Create(path)
		n.sortname=" "+n.name
		Append n
		Return n
	End Method

	Method Scan(o:TNode)
		Local	flist:TList
		Local	dir,f$,p$,t	
		owner=o
		flist=New TList
		dir=ReadDir(path)
		If dir
			Repeat
				f$=NextFile(dir)
				If f$="" Exit
				If f[..1]="." Continue
				p$=path+"/"+f
				Select FileType(p$)
				Case FILETYPE_FILE
					AddFileNode p$
				Case FILETYPE_DIR
					AddFolderNode p$
				End Select				
			Forever
			CloseDir dir
		EndIf
		SortKids
	End Method
	
	Method ScanKids()
		Local	f:TFolderNode		
		If scanned Return
		For f=EachIn kids
			f.Scan owner
		Next
		scanned=True
	End Method

	Function Create:TFolderNode(path$)
		Local	n:TFolderNode
'		print "create foldernode "+path
		n=New TFolderNode
		n.setname StripDir(path)
		n.path=path
		Return n
	End Function
End Type

Type TProjects Extends TNode
	Field	host:TCodePlay
	Field	addproj:TNode
	
	Method RemoveProject(index)
		Local	node:TNode
		If index<0 Or index>=kids.Count() Return
		node=TNode(kids.ValueAtIndex(index))
		If node node.Free
		Refresh
	End Method			
	
	Method AddProject()
		Local	path$,name$,stream:TStream
		path=RequestDir("Select the project folder")
		If Not path Return
		Add path,path
'		addproj.Detach
'		Append TFolderNode.Create(path)		
'		name=StripDir(path)		
'		If Not ScanPath(Self,name,path)	
'			If Confirm("No source files found, create "+name+".bmx?")
'				stream=WriteStream(path+"/"+name+".bmx")
'				If stream CloseStream stream
'				ScanPath(Self,name,path)
'			EndIf
'		EndIf
'		Append addproj
'		Refresh
	End Method

	Method Add(name$,path$)
		Local folder:TFolderNode
		addproj.Detach
		folder=TFolderNode.Create(path)
		folder.Scan Self
		Append folder
		Append addproj
		Refresh
	End Method

	Method Write(stream:TStream)
		Local	project:TFolderNode
		For project=EachIn kids
			stream.WriteLine "proj_node="+project.name+"|"+project.path'node.argument.ToString()
		Next
	End Method

	Method Invoke(command,argument:Object=Null)
		Select command
		Case TOOLNEW
			AddProject
		Case TOOLOPEN
			host.OpenSource String(argument)
		End Select
	End Method
			
	Function CreateProjects:TProjects(host:TCodePlay)
		Local	p:TProjects
		p=New TProjects
		p.SetName("Projects")
		p.host=host
		p.addproj=p.AddNode("Add Project")
		p.addproj.SetAction p,TOOLNEW
		Return p
	End Function
End Type

Type TByteBuffer Extends TStream
	Field	bytes:Byte[]
	Field	readpointer

	Method Read( buf:Byte Ptr,count )
		If count>readpointer count=readpointer
		If count=0 Return
		MemCopy buf,bytes,count
		readpointer:-count
		If readpointer MemMove bytes,Varptr bytes[count],readpointer
		Return count 
	End Method

	Method Write( buf:Byte Ptr,count )
		Local	n,m
		n=readpointer+count
		If n>bytes.length
			m=Max(bytes.length*1.5,n)
			bytes=bytes[..m]
		EndIf
		MemCopy Varptr bytes[readpointer],buf,count
		readpointer=n
		Return count
	End Method	
	
	Method LineAvail()
		Local	i
		For i=0 Until readpointer
			If bytes[i]=10 Return True
		Next
	End Method

	Method FlushBytes:Byte[]()
		Local res:Byte[]=bytes[..readpointer]
		readpointer=0
		Return res
	End Method
End Type

Type TObj
	Field	addr$,sync,refs
End Type

Type TVar Extends TNode

	Field	owner:TDebugTree
	Field	obj:Object

	Method Free()
		If obj owner.RemoveObj obj
		obj=Null
		Super.Free()
	End Method

	Method SetVarName(n$)
		Local	p
		name=n
' if object ref set addr$ field	
		If name.find("$=")=-1 And name.find(")=$")=-1
			p=name.find("=$")
			If p<>-1
				TDebugTree.RemoveObj obj
				obj=TDebugTree.AddObj(name[p+2..])
			EndIf
			p=name.find("=Null")
			If p<>-1
				FreeKids
				TDebugTree.RemoveObj obj
				obj=Null
			EndIf
		EndIf
	End Method
	
	Method AddVar(name$)
		Local	v:TVar
		v=New TVar
		v.setvarname name
		v.owner=owner
		Append v
	End Method
	
	Method SetValue(val:TVar)
		Local	v:TVar,w:TVar,i
' if this is a reference to same object refresh values	
		If obj And obj=val.obj
'			sync=val.sync
			If kids.IsEmpty()
				For v=EachIn val.kids
					AddVar v.name
				Next
			Else
				For v=EachIn val.kids
					If i<kids.count()
						w=TVar(kids.ValueAtIndex(i))
						If w w.SetVarName v.name
					Else
						AddVar v.name
					EndIf
					i:+1
				Next			
			EndIf
			Refresh
		EndIf	
' recurse so all references are updated
		If IsHidden() Return				'parent And parent.state=CLOSEDSTATE Return
		For v=EachIn kids
			v.SetValue val
		Next
	End Method
	
	Method Open(view=0)
		owner.sync:+1
		Super.Open view
		owner.SyncVars
	End Method
	
End Type

Type TScope Extends TVar
	Field	tree:TDebugTree
	Field	file$,line,column

	Method Invoke(command,argument:Object=Null)
		Select command
			Case TOOLACTIVATE
				tree.SelectScope Self,True
		End Select
	End Method
	
	Method SetScope(s:TScope)
		Local	v:TVar
		file=s.file
		line=s.line
		column=s.column
		s.obj=Self
		SetValue s
	End Method
	
	Method SetFile(debugtree:TDebugTree,f$)
		Local	p,q,r
		tree=debugtree
		p=Instr(f,"<")
		q=Instr(f,">")
		r=Instr(f,",")
		If p And q And r
			file=f[..p-1]
			line=Int(f[p..r-1])
			column=Int(f[r..q-1])
		EndIf
		obj=Self
	End Method
End Type

Type TDebugTree Extends TVar
	Global	sync
	Global	objlist:TList
	Field	host:TCodePlay
	Field	instack:TList
	Field	inscope:TScope
	Field	invar:TVar
	Field	infile$
	Field	inexception$
	Field	firststop
	Field	cancontinue
		
	Method Reset()
		host.SetMode host.DEBUGMODE
		SetStack New TList
		objlist=New TList	
		instack=Null
		inscope=Null
		invar=Null
		infile=""
		inexception=""
		sync=0
		firststop=True
		cancontinue=False
	End Method

	Function AddObj:TObj(addr$)
		Local	o:TObj
		For o=EachIn objlist
			If o.addr=addr 
				o.refs:+1
				Return o
			EndIf
		Next
		o=New TObj
		o.addr=addr
		o.refs=1
		objlist.addlast o
		Return o
	End Function

	Function FindObj:TObj(addr$)
		Local	o:TObj
		For o=EachIn objlist
			If o.addr=addr Return o
		Next
	End Function
	
	Function RemoveObj(obj:Object)		':TObj
		Local	o:TObj
		o=TObj(obj)
		If Not o Return
		o.refs:-1
		If o.refs=0 
			objlist.Remove o
		EndIf
	End Function

	Method SyncVars()
		Local	o:TObj
		For o=EachIn objlist
			If o.sync<sync 
				o.sync=sync
				host.output.WritePipe "d"+o.addr
			EndIf
		Next		
	End Method
			
	Method SetStack(list:TList)
		Local	scope:TScope
		Local	openscope:TScope
		Local	s:TScope
		Local	count,i

		count=kids.count()			'root.varlist.count()
		For scope=EachIn list
			If i>=count
				Append scope		'root.Append scope
				s=scope
			Else
				s=TScope(kids.ValueAtIndex(i))
' simon was here				
				If s.name=scope.name
					s.SetScope scope
					scope.Free
				Else
					While kids.count()>i
						s=TScope(kids.ValueAtIndex(i))
						s.free
					Wend
					Append scope
					s=scope
					count=i+1
				EndIf
				
			EndIf
			If firststop
				If host.IsSourceOpen(s.file) openscope=s
			Else
				openscope=s
			EndIf
			i:+1
		Next
		While kids.count()>i
			scope=TScope(kids.ValueAtIndex(i))
			scope.free
		Wend 
		If list.isempty() Return
		If Not openscope openscope=TScope(list.First())
		If openscope SelectScope openscope,True
		Refresh
		firststop=False
	End Method

	Method SelectScope(scope:TScope,open)
		If Not scope Return		
		If scope.file host.DebugSource scope.file,scope.line,scope.column
		scope.Open
'		If open
'			SelectTreeViewNode scope.node
'			scope.open
'		EndIf
	End Method

	Method ProcessError$(line$)
		Local	p
				
		While line[..1]=">" 
			line=line[1..]
		Wend
		If Not line Return

		If line[..2]<>"~~>" Return line

		line=line[2..]

		If invar
			If line="}"
				SetValue invar		'root
				invar.Free
				invar=Null
			Else
'				If Not invar.name
'					invar.name=line
'				Else
					invar.AddVar line
'				EndIf
			EndIf
			Return
		EndIf
		
		If instack 			
			If line="}" 
				sync:+1
				SetStack instack
				instack=Null
				inscope=Null
				SyncVars
				If inexception
					Notify inexception
					inexception=""
				EndIf
				Return
			EndIf
			
			If infile
				If line="Local <local>"
				Else
					inscope=New TScope
'					Print "inscope.line="+line
					inscope.name=line
					inscope.owner=Self
					instack.AddLast inscope
				EndIf
				If inscope inscope.setfile Self,infile
				infile=""
				Return
			EndIf

			If Instr(line,"@")=1 And Instr(line,"<")
				infile=line[1..]
			Else
				If inscope inscope.AddVar line
			EndIf

			Return
		EndIf

		If line[..20]="Unhandled Exception:"
			inexception=line
			host.output.WritePipe "t"
			cancontinue=False
			Return
		EndIf

		If line="StackTrace{" 
			instack=New TList
			Return
		EndIf

		If line="Debug:" Or line="DebugStop:"
			host.output.WritePipe "t"
			cancontinue=True
			Return
		EndIf					
		
		If line[..11]="ObjectDump@"
			p=line.find("{")
			If p=-1 Return line
			line=line[11..p]
			invar=New TVar
'			invar.obj=AddObj(line)
			invar.obj=FindObj(line)	'simon come here
			invar.owner=Self
			Return
		EndIf
		
	End Method

	Function CreateDebugTree:TDebugTree(host:TCodePlay)
		Local	d:TDebugTree
		objlist=New TList
		d=New TDebugTree
		d.owner=d
		d.SetName "Debug"
		d.host=host
		d.Open
		Return d		
	End Function
End Type

Type TNodeView
	Field	owner:TNavBar
	Field	root:TNode
	Field	treeview:TGadget
	Field	index
	
	Method NewView()
		Local	n:TNode,hnode:TGadget
		hnode=SelectedTreeViewNode(treeview)
		n=root.Find(hnode,index)
		If n And n.parent owner.AddView n
	End Method

	Method OnEvent()
		Local	n:TNode
		n=root.Find(TGadget(EventExtra()),index)
		If Not n Return
		Select EventID()
			Case EVENT_GADGETSELECT
				n.invoke(TOOLSELECT)				
			Case EVENT_GADGETACTION
				n.invoke(TOOLACTIVATE)				
			Case EVENT_GADGETMENU
				n.invoke(TOOLMENU,Self)
			Case EVENT_GADGETOPEN
				n.open index
			Case EVENT_GADGETCLOSE
				n.close index
		End Select
	End Method
End Type

Type TNavBar Extends TEventHandler
	Field	host:TCodePlay
	Field	tabber:TGadget
	Field	viewlist:TList=New TList
	Field	selected:TNodeView
	Field	navmenu:TGadget
	
	Method SelectedView()
		If selected Return selected.index
	End Method
		
	Method SelectView(index)
		Local	n:TNodeView
		If index>=viewlist.count() Return
		n=TNodeView(viewlist.ValueAtIndex(index))
		If Not n Print "selectview failed";Return
		If n<>selected
			If selected HideGadget selected.treeview
			selected=n
		EndIf
		ShowGadget n.treeview
		SelectGadgetItem tabber,index
	End Method
	
	Method AddView(node:TNode)
		Local	n:TNodeView
		Local	index,root:TGadget
		For n=EachIn viewlist
			If n.root=node SelectView n.index;Return
		Next
		n=New TNodeView
		n.owner=Self
		n.root=node
		n.treeview=CreateTreeView(0,0,ClientWidth(tabber),ClientHeight(tabber),tabber)
		host.options.navstyle.Apply n.treeview
		SetGadgetLayout n.treeview,1,1,1,1
		HideGadget n.treeview

		viewlist.AddLast n		
		n.index=viewlist.Count()

		AddGadgetItem tabber,node.name
		root=TreeViewRoot(n.treeview)
		node.setnode root,n.index
		SelectView n.index
		Return n.index
	End Method

	Method OnEvent()
		If EventSource()=tabber
			SelectView SelectedGadgetItem(tabber)				
		End If
		If selected And EventSource()=selected.treeview
			selected.OnEvent
		EndIf
	End Method

	Method Refresh()
		Local	view:TNodeView
		For view=EachIn viewlist
			host.options.navstyle.Apply view.treeview
		Next
	End Method

	Method Invoke(command,argument:Object=Null)
		If command=TOOLREFRESH Refresh()		
		If command=TOOLNEWVIEW And selected selected.NewView
	End Method

	Function CreateNavMenu:TGadget()
		Local	edit:TGadget
		edit=CreateMenu("&Nav",0,Null)
		CreateMenu "&New View",MENUNEWVIEW,edit
		Return edit
	End Function

	Function Create:TNavBar(host:TCodePlay)	',root:TNode)
		Local	n:TNavBar
		n=New TNavBar
		n.host=host	
		n.tabber=CreateTabber(0,0,1,1,host.client)
'		n.AddView root
		n.navmenu=CreateNavMenu()
		Return n		
	End Function

End Type