Pārlūkot izejas kodu

Massive ted2 reworking/cleanup.

Mark Sibly 9 gadi atpakaļ
vecāks
revīzija
8b82ea96f2
52 mainītis faili ar 799 papildinājumiem un 8138 dzēšanām
  1. 2 2
      src/ted2/assets/about.html
  2. 0 12
      src/ted2/assets/scripts.json
  3. 188 118
      src/ted2/debugview.monkey2
  4. 22 33
      src/ted2/finddialog.monkey2
  5. 0 202
      src/ted2/helpview.monkey2
  6. 0 104
      src/ted2/imgdocument.monkey2
  7. 349 1313
      src/ted2/mainwindow.monkey2
  8. 0 168
      src/ted2/mojox/action.monkey2
  9. BIN
      src/ted2/mojox/assets/DejaVuSansMono.ttf
  10. BIN
      src/ted2/mojox/assets/HelveticaNeue.ttf
  11. BIN
      src/ted2/mojox/assets/Inconsolata-g.ttf
  12. BIN
      src/ted2/mojox/assets/RobotoMono-Regular.ttf
  13. BIN
      src/ted2/mojox/assets/checkmark_icons.png
  14. 0 327
      src/ted2/mojox/assets/htmlview_master_css.css
  15. 0 24
      src/ted2/mojox/assets/markdown_wrapper.html
  16. BIN
      src/ted2/mojox/assets/monkey_font.png
  17. BIN
      src/ted2/mojox/assets/treenode_collapsed.png
  18. BIN
      src/ted2/mojox/assets/treenode_expanded.png
  19. 0 128
      src/ted2/mojox/button.monkey2
  20. 0 135
      src/ted2/mojox/console.monkey2
  21. 0 214
      src/ted2/mojox/dialog.monkey2
  22. 0 329
      src/ted2/mojox/dockingview.monkey2
  23. 0 137
      src/ted2/mojox/filebrowser.monkey2
  24. 0 352
      src/ted2/mojox/htmlview.monkey2
  25. 0 123
      src/ted2/mojox/label.monkey2
  26. 0 217
      src/ted2/mojox/menu.monkey2
  27. 0 89
      src/ted2/mojox/mojo2.monkey2
  28. BIN
      src/ted2/mojox/mojo_window.9.png
  29. 0 29
      src/ted2/mojox/mojox.monkey2
  30. BIN
      src/ted2/mojox/monkey2-logo-63.png
  31. 0 512
      src/ted2/mojox/native/process.cpp
  32. 0 40
      src/ted2/mojox/native/process.h
  33. 0 213
      src/ted2/mojox/native/requesters.cpp
  34. 0 20
      src/ted2/mojox/native/requesters.h
  35. 0 203
      src/ted2/mojox/native/requesters.mm
  36. 0 192
      src/ted2/mojox/scrollbar.monkey2
  37. 0 269
      src/ted2/mojox/scrollview.monkey2
  38. 0 11
      src/ted2/mojox/separator.monkey2
  39. 0 180
      src/ted2/mojox/tabview.monkey2
  40. 0 41
      src/ted2/mojox/test.monkey2
  41. 0 15
      src/ted2/mojox/test2.monkey2
  42. 0 39
      src/ted2/mojox/textfield.monkey2
  43. 0 1089
      src/ted2/mojox/textview.monkey2
  44. 0 258
      src/ted2/mojox/theme.monkey2
  45. 0 32
      src/ted2/mojox/toolbar.monkey2
  46. 0 354
      src/ted2/mojox/treeview.monkey2
  47. 0 310
      src/ted2/mx2document.monkey2
  48. 0 147
      src/ted2/mx2highlighter.monkey2
  49. 155 28
      src/ted2/projectview.monkey2
  50. 31 18
      src/ted2/ted2.monkey2
  51. 52 7
      src/ted2/ted2document.monkey2
  52. 0 104
      src/ted2/txtdocument.monkey2

+ 2 - 2
src/ted2/assets/about.html

@@ -7,9 +7,9 @@
 <style>
 
 body{
-	background: #222;
+	background: #323232;
 	color: #fff;
-	font-size: 20px;
+	font-size: 16px;
 	margin: 8px;
 	padding: 0px;
 }

+ 0 - 12
src/ted2/assets/scripts.json

@@ -1,17 +1,5 @@
 {
 	"scripts":[
-		{
-			"name":"Make docs",
-			"script":"makedocs"
-		},
-		{
-			"name":"Update modules",
-			"script":"updatemods"
-		},
-		{
-			"name":"Rebuild modules",
-			"script":"rebuildmods"
-		},
 		{
 			"name":"Update mx2cc",
 			"script":"updatemx2cc"

+ 188 - 118
src/ted2/debugview.monkey2

@@ -5,28 +5,41 @@ Namespace ted2
 
 Private
 
-Global icons:=New Image[6]
+Global icons:Image[]
 
 Public
 
 Class DebugView Extends DockingView
 
-	Method New()
+	Method New( docs:DocumentManager,console:Console )
 	
-		If Not icons[0] icons=Theme.LoadIcons( "asset::ted2/debug_icons.png",16 )
+		_docs=docs
+		_console=console
+		
+		_console.Finished+=Lambda( exitCode:Int )
+			If Not _debugging Return
+			
+			If _stopped Resume()
+		End
+	
+		If Not icons icons=App.Theme.LoadIcons( "asset::ted2/debug_icons.png" )
 	
 		Local tools:=New ToolBar
 		
+		tools.Style=New Style( tools.Style )
+		tools.Style.Border=New Recti( -4,-4,4,4 )
+		tools.Style.BorderColor=App.Theme.GetColor( "content" )
+		
 		'run/pause
 		_run=tools.AddAction( "",icons[2] )
 		_run.Triggered=Lambda()
 			If Not _debugging Return
 		
 			If _stopped
-				MainWindow._console.WriteStdin( "r~n" )
+				_console.WriteStdin( "r~n" )
 				Resume()
 			Else
-				MainWindow._console.Process.SendBreak()
+				_console.Process.SendBreak()
 			Endif
 		
 		End
@@ -37,7 +50,7 @@ Class DebugView Extends DockingView
 			If Not _debugging Return
 			
 			If _stopped
-				MainWindow._console.WriteStdin( "s~n" )
+				_console.WriteStdin( "s~n" )
 				Resume()
 			Endif
 			
@@ -49,7 +62,7 @@ Class DebugView Extends DockingView
 			If Not _debugging Return
 		
 			If _stopped
-				MainWindow._console.WriteStdin( "e~n" )
+				_console.WriteStdin( "e~n" )
 				Resume()
 			Endif
 			
@@ -61,7 +74,7 @@ Class DebugView Extends DockingView
 			If Not _debugging Return
 		
 			If _stopped
-				MainWindow._console.WriteStdin( "l~n" )
+				_console.WriteStdin( "l~n" )
 				Resume()
 			Endif
 			
@@ -73,44 +86,43 @@ Class DebugView Extends DockingView
 			If Not _debugging Return
 		
 			If _stopped
-				MainWindow._console.WriteStdin( "q~n" )
+				_console.WriteStdin( "q~n" )
 				Resume()
 			Else
-				MainWindow._console.Process.SendBreak()
+				_console.Process.SendBreak()
 				_killme=True
 			Endif
 		
 		End
 		
-		AddView( tools,"top",0 )
+		AddView( tools,"top" )
 		
 		_tree=New TreeView
 		_tree.RootNodeVisible=False
 		_tree.RootNode.Expanded=True
 		
-		_tree.NodeClicked=Lambda( tnode:TreeView.Node,event:MouseEvent )
+		_tree.NodeClicked=Lambda( tnode:TreeView.Node )
 		
 			Local node:=Cast<Node>( tnode )
 			If Not node Return
 			
 			If node.srcFile
 			
-				Local doc:=Cast<Mx2Document>( MainWindow.OpenDocument( node.srcFile ) )
+				Local doc:=Cast<Monkey2Document>( _docs.OpenDocument( node.srcFile,True ) )
 				If Not doc Return
+				
+				MainWindow.UpdateWindow( False )
 
 				doc.DebugLine=node.srcLine-1
-				
-			Else
-				
 			Endif
 		
 		End
 		
-		_tree.NodeToggled=Lambda( tnode:TreeView.Node,event:MouseEvent )
+		_tree.NodeExpanded=Lambda( tnode:TreeView.Node )
 			If Not _stopped Return
 			
 			Local node:=Cast<Node>( tnode )
-			If Not node Or Not node.Expanded Or Not node.scope Return
+			If Not node Or Not node.scope Return
 			
 			New Fiber( Lambda()
 				UpdateExpanded( node )
@@ -122,16 +134,162 @@ Class DebugView Extends DockingView
 		UpdateActions()
 	End
 	
+	Method DebugApp( appFile:String,config:String )
+	
+		If _console.Running Return
+
+		_console.Clear()
+			
+		MainWindow.ShowOutputConsole()
+	
+		Local cmd:=RealPath( appFile )
+		
+		If config<>"debug"
+		
+			_console.Run( cmd )
+			
+			_console.Write( "~nFinished running app.~n" )
+			
+			MainWindow.UpdateKeyView()
+			
+			Return
+		End
+		
+		If Not _console.Start( cmd )
+			Alert( "Failed to start process: '"+cmd+"'" )
+			Return
+		Endif
+		
+		DebugBegin()
+		
+		Repeat
+			
+			Local stdout:=_console.ReadStdout()
+			If Not stdout Exit
+			
+			If stdout="{{!DEBUG!}}~n"
+				DebugStop()
+				Continue
+			End
+			
+			_console.Write( stdout )
+		
+		Forever
+		
+		DebugEnd()
+		
+		For Local doc:=Eachin _docs.OpenDocuments
+			Local mx2Doc:=Cast<Monkey2Document>( doc )
+			If mx2Doc mx2Doc.DebugLine=-1
+		Next
+			
+		_console.Write( "~nFinished debugging app.~n" )
+		
+		MainWindow.UpdateKeyView()
+	End
+
+	Private
+		
+	Class Node Extends TreeView.Node
+
+		Field srcFile:String
+		Field srcLine:Int
+		Field seq:Int
+		
+		Field name:String
+		Field type:String
+		Field value:String
+		Field scope:Bool
+	
+		Method New( label:String,parent:TreeView.Node=Null,seq:Int=0,index:Int=-1 )
+			Super.New( "",parent,index )
+			Self.seq=seq
+			
+			Update( label )
+		End
+		
+		Method Update( label:String )
+		
+			Local tname:=name
+			Local ttype:=type
+			Local tvalue:=value
+		
+			name=""
+			type=""
+			value=""
+			scope=False
+			
+			Local i0:=label.Find( ":" )
+			If i0<>-1
+				name=label.Slice( 0,i0 )
+				Local i1:=label.Find( "=",i0+1 )
+				If i1=-1
+					type=label.Slice( i0+1 )
+				Else
+					type=label.Slice( i0+1,i1 )
+					value=label.Slice( i1+1 )
+					
+					If value.StartsWith( "@" )
+					
+						label=name+":"+type
+						
+						If value.Contains( ":" )
+							scope=True
+						Else
+							Local p:ULong
+							If value.StartsWith( "@0x" )
+								p=StringToULong( value.Slice( 3 ),16 )
+							Else
+								p=StringToULong( value.Slice( 1 ),16 )
+							Endif
+							If p
+								label+="="+value
+								scope=True
+							Else
+								label+="={null}"
+							Endif
+						endif
+					Endif
+				Endif
+			Endif
+			
+			Text=label
+			
+			If name=tname And type=ttype And value=tvalue Return
+			
+			RemoveAllChildren()
+			
+			If scope New Node( "",Self )
+		End
+	
+	End
+	
+	Field _tree:TreeView
+
+	Field _docs:DocumentManager	
+	Field _console:Console
+
+	Field _debugging:Bool
+	Field _stopped:Bool
+	Field _killme:Bool
+	Field _resume:Future<Bool>
+	
+	Field _run:Action
+	Field _step:Action
+	Field _enter:Action
+	Field _leave:Action
+	Field _kill:Action
+	
 	Method UpdateExpanded( node:Node )
 	
 		If Not node.scope Return
 
 		Local lines:=New StringStack
 		
-		MainWindow._console.WriteStdin( node.value+"~n" )
+		_console.WriteStdin( node.value+"~n" )
 		
 		Repeat
-			Local line:=MainWindow._console.ReadStdout().Trim()
+			Local line:=_console.ReadStdout().Trim()
 			If Not line Exit
 			
 			lines.Push( line )
@@ -169,7 +327,7 @@ Class DebugView Extends DockingView
 		
 		Repeat
 		
-			Local line:=MainWindow._console.ReadStdout().Trim()
+			Local line:=_console.ReadStdout().Trim()
 			If Not line Exit
 			
 			If line.StartsWith( ">" )
@@ -190,7 +348,7 @@ Class DebugView Extends DockingView
 				Next
 				
 				If func
-					func.Label=label
+					func.Text=label
 					func.srcLine=Int( bits[2] )
 				Else
 					func=New Node( label+"*",root,seq,funcIndex )
@@ -202,8 +360,11 @@ Class DebugView Extends DockingView
 				Endif
 				
 				If Not first
-					Local doc:=Cast<Mx2Document>( MainWindow.OpenDocument( func.srcFile ) )
-					If doc doc.DebugLine=func.srcLine-1
+					Local doc:=Cast<Monkey2Document>( _docs.OpenDocument( func.srcFile,True ) )
+					If doc
+						MainWindow.UpdateWindow( False )
+						doc.DebugLine=func.srcLine-1
+					Endif
 					first=func
 				Endif
 				
@@ -260,11 +421,13 @@ Class DebugView Extends DockingView
 	Method DebugStop()
 	
 		Assert( Not _stopped )
+		
+		MainWindow.ShowDebugView()
 	
 		UpdateTree()
 		
 		If _killme
-			MainWindow._console.WriteStdin( "q~n" )
+			_console.WriteStdin( "q~n" )
 			Return
 		Endif
 		
@@ -273,11 +436,7 @@ Class DebugView Extends DockingView
 		
 		UpdateActions()
 		
-		MainWindow._buildForceStop.Triggered+=Resume
-		
 		_resume.Get()
-		
-		MainWindow._buildForceStop.Triggered-=Resume
 	End
 	
 	Method Resume()
@@ -292,95 +451,6 @@ Class DebugView Extends DockingView
 		_resume=Null
 	End
 	
-	Private
-	
-	Class Node Extends TreeView.Node
-
-		Field srcFile:String
-		Field srcLine:Int
-		Field seq:Int
-		
-		Field name:String
-		Field type:String
-		Field value:String
-		Field scope:Bool
-	
-		Method New( label:String,parent:TreeView.Node=Null,seq:Int=0,index:Int=-1 )
-			Super.New( "",parent,index )
-			Self.seq=seq
-			
-			Update( label )
-		End
-		
-		Method Update( label:String )
-		
-			Local tname:=name
-			Local ttype:=type
-			Local tvalue:=value
-		
-			name=""
-			type=""
-			value=""
-			scope=False
-			
-			Local i0:=label.Find( ":" )
-			If i0<>-1
-				name=label.Slice( 0,i0 )
-				Local i1:=label.Find( "=",i0+1 )
-				If i1=-1
-					type=label.Slice( i0+1 )
-				Else
-					type=label.Slice( i0+1,i1 )
-					value=label.Slice( i1+1 )
-					
-					If value.StartsWith( "@" )
-					
-						label=name+":"+type
-						
-						If value.Contains( ":" )
-							scope=True
-						Else
-							Local p:ULong
-							If value.StartsWith( "@0x" )
-								p=StringToULong( value.Slice( 3 ),16 )
-							Else
-								p=StringToULong( value.Slice( 1 ),16 )
-							Endif
-							If p
-								label+="="+value
-								scope=True
-							Else
-								label+="={null}"
-							Endif
-						endif
-					Endif
-				Endif
-			Endif
-			
-			Label=label
-			
-			If name=tname And type=ttype And value=tvalue Return
-			
-			RemoveAllChildren()
-			
-			If scope New Node( "",Self )
-		End
-	
-	End
-	
-	Field _tree:TreeView
-
-	Field _debugging:Bool
-	Field _stopped:Bool
-	Field _killme:Bool
-	Field _resume:Future<Bool>
-	
-	Field _run:Action
-	Field _step:Action
-	Field _enter:Action
-	Field _leave:Action
-	Field _kill:Action
-	
 	Method UpdateActions()
 		_run.Icon=_stopped ? icons[0] Else icons[2]
 		_run.Enabled=_debugging

+ 22 - 33
src/ted2/finddialog.monkey2

@@ -3,36 +3,31 @@ Namespace ted2
 
 Class FindDialog Extends Dialog
 
-	Method New()
+	Method New( actions:FindActions )
 	
 		_findField=New TextField
 		
 		_replaceField=New TextField
 		
-		_findField.EnterHit=MainWindow.OnFindNext
-		_findField.TabHit=Lambda()
-			_replaceField.MakeKeyView()
-			_replaceField.SelectAll()
+		_findField.Entered+=Lambda()
+			actions.findNext.Trigger()
 		End
 
-		_replaceField.EnterHit=MainWindow.OnFindNext
-		_replaceField.TabHit=Lambda()
-			_findField.MakeKeyView()
-			_findField.SelectAll()
-		End
+		_findField.Tabbed+=_replaceField.MakeKeyView
+
+		_replaceField.Tabbed+=_findField.MakeKeyView
 		
-		_caseSensitive=New Button( "Case sensitive: " )
-		_caseSensitive.Checkable=True
+		_caseSensitive=New CheckButton( "Case sensitive" )
+		_caseSensitive.Layout="float"
 		
-		_escapedText=New Button( "Escaped text: ")
-		_escapedText.Checkable=True
+'		_escapedText=New CheckButton( "Escaped text" )
 		
 		Local find:=New DockingView
-		find.AddView( New Label( "Find:" ),"left",80,False )
+		find.AddView( New Label( "Find" ),"left",80,False )
 		find.ContentView=_findField
 		
 		Local replace:=New DockingView
-		replace.AddView( New Label( "Replace:" ),"left",80,False )
+		replace.AddView( New Label( "Replace" ),"left",80,False )
 		replace.ContentView=_replaceField
 		
 		_docker=New DockingView
@@ -48,24 +43,18 @@ Class FindDialog Extends Dialog
 		
 		ContentView=_docker
 		
-		AddAction( MainWindow._findNext )
+		AddAction( actions.findNext )
+		AddAction( actions.findPrevious )
+		AddAction( actions.replace )
+		AddAction( actions.replaceAll )
 		
-		AddAction( MainWindow._findPrevious )
+		Local close:=AddAction( "Close" )
+		SetKeyAction( Key.Escape,close )
+		close.Triggered=Close
 		
-		AddAction( MainWindow._findReplace )
+		_findField.Activated+=_findField.MakeKeyView
 		
-		AddAction( MainWindow._findReplaceAll )
-		
-		AddAction( "Close" ).Triggered=Lambda()
-			Close()
-			MainWindow.UpdateKeyView()
-		End
-
-		Opened=Lambda()
-			_findField.MakeKeyView()
-			_findField.SelectAll()
-		End
-
+		Deactivated+=MainWindow.UpdateKeyView
 	End
 	
 	Property FindText:String()
@@ -87,8 +76,8 @@ Class FindDialog Extends Dialog
 	
 	Field _findField:TextField
 	Field _replaceField:TextField
-	Field _caseSensitive:Button
-	Field _escapedText:Button
+	Field _caseSensitive:CheckButton
+	Field _escapedText:CheckButton
 
 	Field _docker:DockingView
 

+ 0 - 202
src/ted2/helpview.monkey2

@@ -1,202 +0,0 @@
-
-Namespace ted2
-
-Function EnumModules:String[]()
-
-	Local mods:=New StringStack
-	
-	For Local line:=Eachin stringio.LoadString( "modules/modules.txt" ).Split( "~n" )
-	
-		Local i:=line.Find( "'" )
-		If i<>-1 line=line.Slice( 0,i )
-		
-		line=line.Trim()
-		If line mods.Push( line )
-		
-	Next
-	
-	Return mods.ToArray()
-End
-
-Class HelpView Extends DockingView
-
-	Field PageClicked:Void( url:String )
-
-	Method New()
-	
-		_findField=New TextField
-		_findField.TabHit=Lambda()
-		
-			If _findField.Document.Text<>_matchText Or Not _matches.Length Return
-			
-			_matchId=(_matchId+1) Mod _matches.Length
-			Go( _matches[_matchId] )
-
-		End
-		_findField.Document.TextChanged=Lambda()
-			UpdateMatches( _findField.Text )
-			If _matches.Length Go( _matches[0] )
-		End
-		
-		Local findBar:=New DockingView
-	
-		findBar.AddView( New Label( "Find:" ),"left" )
-		findBar.ContentView=_findField
-		
-		_helpTree=New HelpTree
-		
-		_helpTree.NodeClicked=Lambda( tnode:TreeView.Node,event:MouseEvent )
-		
-			Local node:=Cast<HelpTree.Node>( tnode )
-			If Not node Return
-			
-			Go( node.Page )
-		End
-		
-		_htmlView=New HtmlView
-
-		_htmlView.AnchorClicked=Lambda( url:String )
-		
-			'dodgy work around for mx2 docs!
-			If url.StartsWith( "javascript:void('" ) And url.EndsWith( "')" )
-				Local page:=url.Slice( url.Find( "'" )+1,url.FindLast( "'" ) )
-				Go( page )
-				Return
-			Endif
-
-			_htmlView.Go( url )
-		End
-		
-		AddView( findBar,"top" )
-		
-		AddView( _helpTree,"top",128 )
-		
-		ContentView=New ScrollView( _htmlView )
-	End
-	
-	Property HelpTree:HelpTree()
-		Return _helpTree
-	End
-	
-	Property HtmlView:HtmlView()
-		Return _htmlView
-	End
-	
-	Method Go( page:String )
-		Local url:="modules/"+page.Replace( ":","/docs/__PAGES__/" ).Replace( ".","-" )+".html"
-		_htmlView.Go( RealPath( url ) )
-	End
-	
-	Method UpdateMatches( text:String )
-
-		_matchId=0
-		_matchText=text
-		_matches.Clear()
-
-		For Local page:=Eachin _helpTree.Index
-			If page.Contains( text ) _matches.Push( page )
-		Next
-
-		_matches.Sort()
-		
-		_helpTree.Matches.RemoveAllChildren()
-		For Local page:=Eachin _matches
-			New HelpTree.Node( page,_helpTree.Matches,_helpTree )
-		Next
-	End
-	
-	Private
-	
-	Field _findField:TextField
-	Field _helpTree:HelpTree
-	Field _htmlView:HtmlView
-	Field _scroller:ScrollView
-	
-	Field _matchId:Int
-	Field _matchText:String
-	Field _matches:=New StringStack
-End
-
-Class HelpTree Extends TreeView
-
-	Class Node Extends TreeView.Node
-	
-		Method New( page:String,parent:TreeView.Node,tree:HelpTree )
-			Super.New( page,parent )
-			
-			_page=page
-		End
-	
-		Method New( obj:JsonObject,parent:TreeView.Node,tree:HelpTree )
-			Super.New( "",parent )
-		
-			Label=obj["text"].ToString()
-			
-			If obj.Contains( "data" )
-				Local data:=obj["data"].ToObject()
-				Local page:=data["page"].ToString()
-				tree._index.Add( page )
-				_page=page
-			Endif
-			
-			If obj.Contains( "children" )
-				For Local child:=Eachin obj["children"].ToArray()
-					New Node( Cast<JsonObject>( child ),Self,tree )
-				Next
-			Endif
-
-		End
-		
-		Property Page:String()
-			Return _page
-		End
-		
-		Private
-		
-		Field _page:String
-	
-	End
-	
-	Method New()
-	
-		RootNodeVisible=False
-		RootNode.Expanded=True
-		
-		_matches=New TreeView.Node( "Matches",RootNode )
-		_modules=New TreeView.Node( "Modules",RootNode )
-	
-		For Local modname:=Eachin EnumModules()
-		
-			Local index:="modules/"+modname+"/docs/__PAGES__/index.js"
-
-			Local obj:=JsonObject.Load( index )
-			If Not obj
-				Print "Error! file="+index
-				Continue
-			Endif
-			
-			New Node( obj,_modules,Self )
-		Next
-		
-	End
-	
-	Property Matches:TreeView.Node()
-		Return _matches
-	End
-	
-	Property Modules:TreeView.Node()
-		Return _modules
-	End
-	
-	Property Index:StringStack()
-		Return _index
-	End
-	
-	Private
-	
-	Field _matches:TreeView.Node
-	Field _modules:TreeView.Node
-	
-	Field _index:=New StringStack
-	
-End

+ 0 - 104
src/ted2/imgdocument.monkey2

@@ -1,104 +0,0 @@
-
-Namespace ted2
-
-Class ImgView Extends View
-
-	Method New( doc:ImgDocument )
-		_doc=doc
-		
-		Layout="fill"
-	End
-	
-	Protected
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		For Local x:=0 Until Width Step 64
-			For Local y:=0 Until Height Step 64
-				canvas.Color=(x~y) & 64 ? New Color( .1,.1,.1 ) Else New Color( .2,.2,.2 )
-				canvas.DrawRect( x,y,64,64 )
-			Next
-		Next
-		
-		If Not _doc.Image Return
-		
-		canvas.Color=Color.White
-		
-		canvas.Translate( Width/2,Height/2 )
-		
-		canvas.Scale( _zoom,_zoom )
-	
-		canvas.DrawImage( _doc.Image,0,0 )
-	End
-	
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		Select event.Type
-		Case EventType.MouseWheel
-			If event.Wheel.Y>0
-				_zoom*=2
-			Else If event.Wheel.Y<0
-				_zoom/=2
-			Endif
-		End
-	
-	End
-	
-	Private
-
-	Field _zoom:Float=1
-		
-	Field _doc:ImgDocument
-End
-
-Class ImgDocument Extends Ted2Document
-
-	Method New( path:String )
-		Super.New( path )
-		
-		_view=New ImgView( Self )
-	End
-	
-	Property Image:Image()
-	
-		Return _image
-	End
-	
-	Protected
-	
-	Method OnLoad:Bool() Override
-	
-		Print "Loading image:"+Path
-	
-		_image=Image.Load( Path )
-		If Not _image Return False
-		
-		Print "OK!"
-		
-		_image.Handle=New Vec2f( .5,.5 )
-		
-		Return True
-	End
-	
-	Method OnSave:Bool() Override
-
-		Return False
-	End
-	
-	Method OnClose() Override
-	
-		If _image _image.Discard()
-	End
-	
-	Method OnCreateView:ImgView() Override
-	
-		Return _view
-	End
-	
-	Private
-	
-	Field _image:Image
-	
-	Field _view:ImgView
-	
-End

+ 349 - 1313
src/ted2/mainwindow.monkey2

@@ -12,1426 +12,462 @@ Global MainWindow:MainWindowInstance
 
 Class MainWindowInstance Extends Window
 
-	Field _debugging:String
-	
-	'paths
-	Field _tmp:String
-	Field _mx2cc:String
-
-	'actions
-	Field _fileNew:Action
-	Field _fileOpen:Action
-	Field _fileClose:Action
-	Field _fileCloseAll:Action
-	Field _fileSave:Action
-	Field _fileSaveAs:Action
-	Field _fileSaveAll:Action
-	Field _fileNextFile:Action
-	Field _filePrevFile:Action
-	Field _fileOpenProject:Action
-	Field _fileQuit:Action
-	
-	Field _editUndo:Action
-	Field _editRedo:Action
-	Field _editCut:Action
-	Field _editCopy:Action
-	Field _editPaste:Action
-	Field _editSelectAll:Action
-	Field _editFind:Action
-	
-	Field _buildDebug:Action
-	Field _buildRelease:Action
-	Field _buildForceStop:Action
-	Field _buildLockFile:Action
-	Field _buildNextError:Action
-	
-	Field _helpOnlineHelp:Action
-	Field _helpOfflineHelp:Action
-	Field _helpAbout:Action
-	
-	Field _findNext:Action
-	Field _findPrevious:Action
-	Field _findReplace:Action
-	Field _findReplaceAll:Action
-	
-	Field _escape:Action
-	
-	'menus
-	Field _menuBar:MenuBar
-	
-	Field _newFiles:Menu
-	Field _recentFiles:Menu
-	Field _closeProject:Menu
-	Field _scripts:Menu
-	
-	Field _fileMenu:Menu
-	Field _editMenu:Menu
-	Field _viewMenu:Menu
-	Field _buildMenu:Menu
-	Field _helpMenu:Menu
-	
-	Field _recent:=New Stack<String>
-	Field _projects:=New Stack<String>
-
-	'dialogs	
-	Field _findDialog:FindDialog
-	
-	'browsers
-	Field _browser:TabView
-	Field _projectView:ProjectView
-	Field _debugView:DebugView
-	Field _helpView:HelpView
-	
-	Field _console:Console
-
-	'documents
-	Field _docTabber:TabView
-	Field _currentDoc:Ted2Document
-	Field _currentTextView:TextView
-	Field _openDocs:=New Stack<Ted2Document>
-	Field _lockedDoc:Ted2Document
-	
-	'main docking view
-	Field _docker:DockingView
-	
-	Field _errors:=New List<Mx2Error>
-	
-	Method OnFileNew()
-	
-		OpenDocument( "" )
-	End
-	
-	Method OnFileOpen()
-
-		Local path:=RequestFile( "Open file...","",False )
-		If Not path Return
-	
-		OpenDocument( path,True )
-		SaveState()
-	End
-	
-	Method OnFileClose()
-	
-		If Not _currentDoc Return
-		
-		If _currentDoc.Dirty
+	Method New( title:String,rect:Recti,flags:WindowFlags,jobj:JsonObject )
+		Super.New( title,rect,flags )
 		
-			Local buttons:=New String[]( "Save","Discard Changes","Cancel" )
+		MainWindow=Self
 		
-			Select TextDialog.Run( "Close","File '"+_currentDoc.Path+"' has been modified.",buttons )
-			Case 0
-				If Not SaveDocument( _currentDoc ) Return
-			Case 2
-				Return
-			End
-
-		Endif
+		_docsTabView=New TabView( TabViewFlags.DraggableTabs|TabViewFlags.ClosableTabs )
+		_browsersTabView=New TabView( TabViewFlags.DraggableTabs )
+		_consolesTabView=New TabView( TabViewFlags.DraggableTabs )
 		
-		CloseDocument( _currentDoc )
+		_recentFilesMenu=New Menu( "Recent Files..." )
+		_closeProjectMenu=New Menu( "Close Project..." )
 		
-		SaveState()
-	End
-	
-	Method OnFileCloseAll()
+		_docsManager=New DocumentManager( _docsTabView )
 
-		Local close:=New Stack<Ted2Document>
-	
-		For Local doc:=Eachin _openDocs
+		_docsManager.CurrentDocumentChanged+=UpdateKeyView
 		
-			If doc.Dirty
-			
-				MakeCurrent( doc )
+		_docsManager.DocumentAdded+=Lambda( doc:Ted2Document )
+			AddRecentFile( doc.Path )
+			UpdateRecentFilesMenu()
+		End
 
-				Local buttons:=New String[]( "Save","Discard Changes","Cancel" )
-			
-				Select TextDialog.Run( "Close All","File '"+doc.Path+"' has been modified.",buttons )
-				Case 0
-					If Not SaveDocument( doc ) Return
-				Case 2
-					Return
-				End
-			
-			Endif
-			
-			close.Add( doc )
+		_docsManager.DocumentRemoved+=Lambda( doc:Ted2Document )
+			If IsTmpPath( doc.Path ) DeleteFile( doc.Path )
+		End
 
-		Next
-		
-		For Local doc:=Eachin close
-			CloseDocument( doc )
-		Next
+		_buildConsole=New Console
+		_outputConsole=New Console
+		_helpView=New HtmlView
+'		_helpView.Style=New Style( _helpView.Style )
+'		_helpView.Style.Border=New Recti( 0,-4,0,0 )
+'		_helpView.Style.BorderColor=App.Theme.GetColor( "content" )
+		_helpView.Go( "asset::ted2/about.html" )
+		
+		_projectView=New ProjectView( _docsManager )
+		
+		_helpTree=New HelpTree( _helpView )
+		
+		_debugView=New DebugView( _docsManager,_outputConsole )
+		
+		_fileActions=New FileActions( _docsManager )
+		_editActions=New EditActions( _docsManager )
+		_findActions=New FindActions( _docsManager )
+		_buildActions=New BuildActions( _docsManager,_buildConsole,_debugView )
+		_helpActions=New HelpActions
+
+		_tabMenu=New Menu
+		_tabMenu.AddAction( _fileActions.close )
+		_tabMenu.AddAction( _fileActions.closeOthers )
+		_tabMenu.AddSeparator()
+		_tabMenu.AddAction( _fileActions.save )
+		_tabMenu.AddAction( _fileActions.saveAs )
+		_tabMenu.AddSeparator()
+		_tabMenu.AddAction( _buildActions.lockBuildFile )
+		
+		_docsTabView.RightClicked+=Lambda()
+			_tabMenu.Open()
+		End
 		
-		SaveState()
-	End
-	
-	Method OnFileSave()
-	
-		If Not _currentDoc Return
-			
-		SaveDocument( _currentDoc )
-	End
-	
-	Method OnFileSaveAs()
+		_docsTabView.CloseClicked+=Lambda( index:Int )
 
-		If Not _currentDoc Return
-			
-		Local path:=RequestFile( "Save As","",True )
-		If Not path Return
+			Local doc:=_docsManager.FindDocument( _docsTabView.TabView( index ) )
+			If Not doc.Dirty
+				doc.Close()
+				Return
+			Endif
+			_docsManager.CurrentDocument=doc
+			_fileActions.close.Trigger()
+		End
+
+		_tmp=RealPath( "tmp/" )
 		
-		RenameDocument( _currentDoc,path )
-		SaveDocument( _currentDoc )
-	End
-	
-	Method OnFileSaveAll()
-		For Local doc:=Eachin _openDocs
-			SaveDocument( doc )
+		_newFiles=New Menu( "New..." )
+		Local p:=AssetsDir()+"ted2/newfiles/"
+		For Local f:=Eachin LoadDir( p )
+			Local src:=stringio.LoadString( p+f )
+			_newFiles.AddAction( StripExt( f.Replace( "_"," " ) ) ).Triggered=Lambda()
+				Local path:=AllocTmpPath( ExtractExt( f ) )
+				If Not path Return
+				SaveString( src,path )
+				Local doc:=_docsManager.OpenDocument( path,True )
+			End
 		Next
-	End
-	
-	Method OnFileNextFile()
-		If _docTabber.Count<2 Return
 		
-		Local i:=_docTabber.CurrentIndex+1
-		If i=_docTabber.Count i=0
-		
-		Local doc:=FindDocument( _docTabber.ViewAtIndex( i ) )
-		If Not doc Return
+		_fileMenu=New Menu( "File" )
+		_fileMenu.AddAction( _fileActions.new_ )
+		_fileMenu.AddSubMenu( _newFiles )
+		_fileMenu.AddAction( _fileActions.open )
+		_fileMenu.AddSubMenu( _recentFilesMenu )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _fileActions.close )
+		_fileMenu.AddAction( _fileActions.closeOthers )
+		_fileMenu.AddAction( _fileActions.closeAll )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _fileActions.save )
+		_fileMenu.AddAction( _fileActions.saveAs )
+		_fileMenu.AddAction( _fileActions.saveAll )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _docsManager.nextDocument )
+		_fileMenu.AddAction( _docsManager.prevDocument )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _projectView.openProject )
+		_fileMenu.AddSubMenu( _closeProjectMenu )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _fileActions.quit )
 		
-		MakeCurrent( doc )
-	End
-	
-	Method OnFilePrevFile()
-		If _docTabber.Count<2 Return
+		_editMenu=New Menu( "Edit" )
+		_editMenu.AddAction( _editActions.undo )
+		_editMenu.AddAction( _editActions.redo )
+		_editMenu.AddSeparator()
+		_editMenu.AddAction( _editActions.cut )
+		_editMenu.AddAction( _editActions.copy )
+		_editMenu.AddAction( _editActions.paste )
+		_editMenu.AddSeparator()
+		_editMenu.AddAction( _editActions.selectAll )
+		_editMenu.AddSeparator()
+		_editMenu.AddAction( _findActions.find )
+		_editMenu.AddAction( _findActions.findNext )
+		_editMenu.AddAction( _findActions.findPrevious )
+		_editMenu.AddAction( _findActions.replace )
+		_editMenu.AddAction( _findActions.replaceAll )
+		
+		_forceStop=New Action( "Force Stop" )
+		_forceStop.Triggered=Lambda()
+			If _buildConsole.Running
+				_buildConsole.Terminate()
+			Else If _outputConsole.Running
+				_outputConsole.Terminate()
+			Endif
+		End
+		_forceStop.HotKey=Key.F5
+		_forceStop.HotKeyModifiers=Modifier.Shift
 		
-		Local i:=_docTabber.CurrentIndex-1
-		If i=-1 i=_docTabber.Count-1
+		_buildMenu=New Menu( "Build" )
+		_buildMenu.AddAction( _buildActions.buildAndRun )
+		_buildMenu.AddAction( _buildActions.build )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddSubMenu( _buildActions.configMenu )
+		_buildMenu.AddSubMenu( _buildActions.targetMenu )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _buildActions.nextError )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _buildActions.lockBuildFile )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _buildActions.updateModules )
+		_buildMenu.AddAction( _buildActions.rebuildModules )
+		_buildMenu.AddAction( _buildActions.rebuildHelp )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _forceStop )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _buildActions.moduleManager )
 		
-		Local doc:=FindDocument( _docTabber.ViewAtIndex( i ) )
-		If Not doc Return
+		_helpMenu=New Menu( "Help" )
+		_helpMenu.AddAction( _helpActions.onlineHelp )
+		_helpMenu.AddAction( _helpActions.viewManuals )
+		_helpMenu.AddSeparator()
+		_helpMenu.AddAction( _helpActions.uploadModules )
+		_helpMenu.AddSeparator()
+		_helpMenu.AddAction( _helpActions.about )
 		
-		MakeCurrent( doc )
-	End
-	
-	Method OnFileOpenProject()
-	
-		Local dir:=RequestDir( "Select Project Directory...","" )
-		If Not dir Return
+		_menuBar=New MenuBar
+		_menuBar.AddMenu( _fileMenu )
+		_menuBar.AddMenu( _editMenu )
+		_menuBar.AddMenu( _buildMenu )
+		_menuBar.AddMenu( _helpMenu )
 		
-		If Not _projectView.OpenProject( dir ) Return
+		_browsersTabView.AddTab( "Files",_projectView,True )
+		_browsersTabView.AddTab( "Debug",_debugView,False )
+		_browsersTabView.AddTab( "Help",_helpTree,False )
 		
-		_projects.Push( dir )
-		UpdateCloseProjectMenu()
+		_consolesTabView.AddTab( "Build",_buildConsole,True )
+		_consolesTabView.AddTab( "Output",_outputConsole,False )
+		_consolesTabView.AddTab( "Documentation",_helpView,False )
 		
-	End
-	
-	Method OnFileQuit()
-	
-		For Local doc:=Eachin _openDocs
+		_contentView=New DockingView
+		_contentView.AddView( _menuBar,"top" )
+		_contentView.AddView( _browsersTabView,"right",250,True )
+		_contentView.AddView( _consolesTabView,"bottom",200,True )
+		_contentView.ContentView=_docsTabView
 		
-			If doc.Dirty
-			
-				MakeCurrent( doc )
+		ContentView=_contentView
 
-				Local buttons:=New String[]( "Save","Discard Changes","Cancel" )
-			
-				Select TextDialog.Run( "Quit","File '"+doc.Path+"' has been modified.",buttons )
-				Case 0
-					If Not SaveDocument( doc ) Return
-				Case 2
-					Return
-				End
-			
-			Endif
-		
-		Next
-		
-		SaveState()
-		
-		_console.Terminate()
-		
-		App.Terminate()
-	End
-	
-	Method OnEditUndo()
+		LoadState( jobj )
 
-		Local textView:=Cast<TextView>( App.KeyView )
-		
-		If textView textView.Undo()
+		App.Idle+=OnAppIdle
 	End
 	
-	Method OnEditRedo()
+	Method AllocTmpPath:String( ext:String )
 	
-		Local textView:=Cast<TextView>( App.KeyView )
-		
-		If textView textView.Redo()
+		For Local i:=1 Until 10
+			Local path:=_tmp+"untitled"+i+ext
+			If GetFileType( path )=FileType.None Return path
+		Next
+
+		Return ""
 	End
 	
-	Method OnEditCut()
-	
-		Local textView:=Cast<TextView>( App.KeyView )
-		
-		If textView textView.Cut()
-	End
-
-	Method OnEditCopy()
+	Method IsTmpPath:Bool( path:String )
 
-		Local textView:=Cast<TextView>( App.KeyView )
-		
-		If textView textView.Copy()
+		Return path.StartsWith( _tmp )
 	End
 
-	Method OnEditPaste()		
-		
-		Local textView:=Cast<TextView>( App.KeyView )
+	Private
 		
-		If textView textView.Paste()
-	End
+	Method DeleteTmps()
 	
-	Method OnEditSelectAll()
-		
-		Local textView:=Cast<TextView>( App.KeyView )
+		For Local f:=Eachin LoadDir( _tmp )
+			Local path:=_tmp+f
+			If GetFileType( path )=FileType.File
+				If Not _docsManager.FindDocument( path ) DeleteFile( path )
+			Endif
+		Next
 		
-		If textView textView.SelectAll()
 	End
 	
-	Method OnEditFind()
+	Public
 	
-		_findDialog.Open()
+	Method ShowProjectView()
+		_browsersTabView.CurrentView=_projectView
 	End
 	
-	Method OnBuildDebug()
+	Method ShowDebugView()
+		_browsersTabView.CurrentView=_debugView
+	End
 	
-		Build( "debug" )
+	Method ShowBuildConsole( vis:Bool=True )
+		If vis _consolesTabView.Visible=True
+		_consolesTabView.CurrentView=_buildConsole
 	End
 	
-	Method OnBuildRelease()
+	Method ShowOutputConsole( vis:Bool=True )
+		If vis _consolesTabView.Visible=True
+		_consolesTabView.CurrentView=_outputConsole
+	End
 	
-		Build( "release" )
+	Method ShowHelpView()
+		_consolesTabView.Visible=True
+		_consolesTabView.CurrentView=_helpView
 	End
 	
-	Method OnBuildForceStop()
+	Method ShowQuickHelp( ident:String )
+		_helpTree.QuickHelp( ident )
+	End
 	
-		_console.Terminate()
+	Method ShowHelp( url:String  )
+		ShowHelpView()
+		_helpView.Go( url )
+		_helpView.Scroll=New Vec2i( 0,0 )
 	End
 	
-	Method OnBuildLockFile()
+	Method UpdateHelpTree()
+		_helpTree.Update()
+	End
 	
-		LockDoc( _currentDoc )
+	Method ReadError( path:String )
+		Alert( "I/O Error reading file '"+path+"'" )
 	End
 	
-	Method OnBuildNextError()
+	Method WriteError( path:String )
+		Alert( "I/O Error writing file '"+path+"'" )
+	End
 
-		While Not _errors.Empty And _errors.First.removed
-			_errors.RemoveFirst()
-		Wend
-		
-		If _errors.Empty Return
+	Method UpdateKeyView()
+
+		Local doc:=_docsManager.CurrentDocument
+		If Not doc Return
 		
-		_errors.AddLast( _errors.RemoveFirst() )
-			
-		GotoError( _errors.First )
+		If doc.TextView doc.TextView.MakeKeyView() Else doc.View.MakeKeyView()
 	End
 	
-	Method OnHelpOnlineHelp()
+	Method SaveState()
 	
-		App.Idle+=Lambda()
-			requesters.OpenUrl( "http://monkey2.monkey-x.com/modules-reference/" )
+		Local jobj:=New JsonObject
+		
+		jobj["windowRect"]=ToJson( Frame )
+		jobj["browserSize"]=New JsonNumber( _contentView.GetViewSize( _browsersTabView ) )
+		jobj["consoleSize"]=New JsonNumber( _contentView.GetViewSize( _consolesTabView ) )
+		
+		Local recent:=New JsonArray
+		For Local path:=Eachin _recentFiles
+			recent.Add( New JsonString( path ) )
 		End
+		jobj["recentFiles"]=recent
 		
+		_docsManager.SaveState( jobj )
+		_buildActions.SaveState( jobj )
+		_projectView.SaveState( jobj )
+		
+		SaveString( jobj.ToJson(),"bin/ted2.state.json" )
 	End
-	
-	Method OnHelpOfflineHelp()
-	
-		App.Idle+=Lambda()
-			requesters.OpenUrl( "file://"+CurrentDir()+"docs/index.html" )
-		End
 
-	End
-	
-	Method OnHelpAbout()
+	Private
 	
-		Local htmlView:=New HtmlView
-		htmlView.Go( "asset::ted2/about.html" )
-
-		Local dialog:=New Dialog( "About Monkey2" )
-		dialog.ContentView=htmlView
-		
-		dialog.MinSize=New Vec2i( 640,600 )
+	Method LoadState( jobj:JsonObject )
 		
-		dialog.MaxSize=Rect.Size
+		If Not jobj Return
 		
-		dialog.AddAction( "Okay!" ).Triggered=Lambda()
+'		If jobj.Contains( "windowRect" ) Frame=ToRecti( jobj["windowRect"] )
+		If jobj.Contains( "browserSize" ) _contentView.SetViewSize( _browsersTabView,jobj["browserSize"].ToNumber() )
+		If jobj.Contains( "consoleSize" ) _contentView.SetViewSize( _consolesTabView,jobj["consoleSize"].ToNumber() )
 		
-			dialog.Close()
+		If jobj.Contains( "recentFiles" )
+			For Local file:=Eachin jobj["recentFiles"].ToArray()
+				Local path:=file.ToString()
+				If GetFileType( path )<>FileType.File Continue
+				_recentFiles.Push( path )
+			Next
 		End
 		
-		dialog.Open()
-	
-	End
-	
-	Method OnFindNext()
-	
-		If Not _currentTextView Return
+		_projectView.ProjectOpened-=UpdateCloseProjectMenu
 		
-		Local text:=_findDialog.FindText
-		If Not text Return
+		_docsManager.LoadState( jobj )
+		_buildActions.LoadState( jobj )
+		_projectView.LoadState( jobj )
 		
-		Local tvtext:=_currentTextView.Text
-		Local cursor:=Max( _currentTextView.Anchor,_currentTextView.Cursor )
+		If Not _projectView.OpenProjects.Length _projectView.OpenProject( CurrentDir() )
 		
-		If Not _findDialog.CaseSensitive
-			tvtext=tvtext.ToLower()
-			text=text.ToLower()
-		Endif
+		_projectView.ProjectOpened+=UpdateCloseProjectMenu
 		
-		Local i:=tvtext.Find( text,cursor )
-		If i=-1
-			i=tvtext.Find( text )
-			If i=-1 Return
-		Endif
+		UpdateRecentFilesMenu()
 		
-		_currentTextView.SelectText( i,i+text.Length )
+		UpdateCloseProjectMenu()
+
+		DeleteTmps()
 	End
 	
-	Method OnFindPrevious()
-		
-		If Not _currentTextView Return
-		
-		Local text:=_findDialog.FindText
-		If Not text Return
-
-		Local tvtext:=_currentTextView.Text
-		Local cursor:=Min( _currentTextView.Anchor,_currentTextView.Cursor )
-		
-		If Not _findDialog.CaseSensitive
-			tvtext=tvtext.ToLower()
-			text=text.ToLower()
-		Endif
-		
-		Local i:=tvtext.Find( text )
-		If i=-1 Return
-		
-		If i>=cursor
-			i=tvtext.FindLast( text )
-		Else
-			Repeat
-				Local n:=tvtext.Find( text,i+text.Length )
-				If n>=cursor Exit
-				i=n
-			Forever
+	Protected
+	
+	Method OnKeyEvent( event:KeyEvent ) Override
+	
+		Select event.Type
+		Case EventType.KeyDown
+			Select event.Key
+			Case Key.Escape
+				If event.Modifiers & Modifier.Shift
+					_browsersTabView.Visible=Not _browsersTabView.Visible
+				Else
+					_consolesTabView.Visible=Not _consolesTabView.Visible
+				Endif
+			End
 		End
-		
-		_currentTextView.SelectText( i,i+text.Length )
 	End
 	
-	Method OnFindReplace()
+	Method OnWindowEvent( event:WindowEvent ) Override
 
-		If Not _currentTextView Return
-		
-		Local text:=_findDialog.FindText
-		If Not text Return
-		
-		Local min:=Min( _currentTextView.Anchor,_currentTextView.Cursor )
-		Local max:=Max( _currentTextView.Anchor,_currentTextView.Cursor )
-		
-		Local tvtext:=_currentTextView.Text.Slice( min,max )
+		Select event.Type
+		Case EventType.WindowClose
+			SaveState()
+			_fileActions.quit.Trigger()
+		Default
+			Super.OnWindowEvent( event )
+		End
+	
+	End
+	
+	Private
+	
+	Field _docsManager:DocumentManager
+	Field _fileActions:FileActions
+	Field _editActions:EditActions
+	Field _findActions:FindActions
+	Field _buildActions:BuildActions
+	Field _helpActions:HelpActions
+	
+	Field _buildConsole:Console
+	Field _outputConsole:Console
+	Field _helpView:HtmlView
 
-		If Not _findDialog.CaseSensitive
-			tvtext=tvtext.ToLower()
-			text=text.ToLower()
-		Endif
-		
-		If tvtext<>text Return
-		
-		_currentTextView.ReplaceText( _findDialog.ReplaceText )
-		
-		OnFindNext()
+	Field _projectView:ProjectView
+	Field _debugView:DebugView
+	Field _helpTree:HelpTree
 
-	End
+	Field _docsTabView:TabView
+	Field _consolesTabView:TabView
+	Field _browsersTabView:TabView
 	
-	Method OnFindReplaceAll()
+	Field _tmp:String
+	Field _forceStop:Action
+
+	Field _tabMenu:Menu
+	Field _newFiles:Menu
+	Field _fileMenu:Menu
+	Field _editMenu:Menu
+	Field _buildMenu:Menu
+	Field _helpMenu:Menu
+	Field _menuBar:MenuBar
 	
-		If Not _currentTextView Return
-		
-		Local text:=_findDialog.FindText
-		If Not text Return
-		
-		Local rtext:=_findDialog.ReplaceText
-		
-		Local tvtext:=_currentTextView.Text
+	Field _contentView:DockingView
 
-		If Not _findDialog.CaseSensitive
-			tvtext=tvtext.ToLower()
-			text=text.ToLower()
-		Endif
-		
-		Local anchor:=_currentTextView.Anchor
-		Local cursor:=_currentTextView.Cursor
-		
-		Local i:=0,t:=0
-		Repeat
-		
-			Local i:=tvtext.Find( text,i )
-			If i=-1 Exit
-			
-			_currentTextView.SelectText( i+t,i+text.Length+t )
-			_currentTextView.ReplaceText( rtext )
-			
-			t+=rtext.Length-text.Length
-			i+=text.Length
-			
-		Forever
-		
-		_currentTextView.SelectText( anchor,cursor )
-		
+	Field _recentFiles:=New StringStack
+	
+	Field _recentFilesMenu:Menu
+	Field _closeProjectMenu:Menu
+	
+	Method ToJson:JsonValue( rect:Recti )
+		Return New JsonArray( New JsonValue[]( New JsonNumber( rect.min.x ),New JsonNumber( rect.min.y ),New JsonNumber( rect.max.x ),New JsonNumber( rect.max.y ) ) )
 	End
 	
-	Method OnEscape()
-		
-		If _findDialog.Visible
-			_findDialog.Close()
-			UpdateKeyView()
-			Return
-		Endif
-		
-		_console.Visible=Not _console.Visible
-		
+	Method ToRecti:Recti( value:JsonValue )
+		Local json:=value.ToArray()
+		Return New Recti( json[0].ToNumber(),json[1].ToNumber(),json[2].ToNumber(),json[3].ToNumber() )
 	End
 	
-	Method InitPaths()
+	Method AddRecentFile( path:String )
 	
-		_tmp=RealPath( "tmp/" )
-		
-#If __HOSTOS__="macos"
-		_mx2cc="bin/mx2cc_macos"
-#Else If __HOSTOS__="windows"
-		_mx2cc="bin/mx2cc_windows.exe"
-#Else
-		_mx2cc="bin/mx2cc_linux"
-#Endif
+		_recentFiles.Remove( path )
+		_recentFiles.Insert( 0,path )
 		
-		CreateDir( _tmp )
+		If _recentFiles.Length>20 _recentFiles.Resize( 20 )
 	End
 	
-	Method InitActions()
+	Method UpdateRecentFilesMenu()
 	
-		_fileNew=New Action( "New" )
-		_fileNew.HotKey=Key.N
-		_fileNew.HotKeyModifiers=Modifier.Control
-		_fileNew.Triggered=OnFileNew
-		
-		_fileOpen=New Action( "Open" )
-		_fileOpen.HotKey=Key.O
-		_fileOpen.HotKeyModifiers=Modifier.Control
-		_fileOpen.Triggered=OnFileOpen
-
-		_fileClose=New Action( "Close" )
-		_fileClose.HotKey=Key.F4
-		_fileClose.HotKeyModifiers=Modifier.Control
-		_fileClose.Triggered=OnFileClose
-
-		_fileCloseAll=New Action( "Close All" )
-		_fileCloseAll.Triggered=OnFileCloseAll
+		_recentFilesMenu.Clear()
 		
-		_fileSave=New Action( "Save" )
-		_fileSave.HotKey=Key.S
-		_fileSave.HotKeyModifiers=Modifier.Control
-		_fileSave.Triggered=OnFileSave
+		Local recentFiles:=New StringStack
 		
-		_fileSaveAs=New Action( "Save As" )
-		_fileSaveAs.Triggered=OnFileSaveAs
+		For Local path:=Eachin _recentFiles
+			If GetFileType( path )<>FileType.File Continue
 		
-		_fileSaveAll=New Action( "Save All" )
-		_fileSaveAll.Triggered=OnFileSaveAll
+			_recentFilesMenu.AddAction( path ).Triggered=Lambda()
+				_docsManager.OpenDocument( path,True )
+			End
+			
+			recentFiles.Add( path )
+		Next
 		
-		_fileNextFile=New Action( "Next File" )
-		_fileNextFile.Triggered=OnFileNextFile
-		_fileNextFile.HotKey=Key.Tab
-		_fileNextFile.HotKeyModifiers=Modifier.Control
+		_recentFiles=recentFiles
+	End
+	
+	Method UpdateCloseProjectMenu( dir:String="" )
+	
+		_closeProjectMenu.Clear()
 		
-		_filePrevFile=New Action( "Previous File" )
-		_filePrevFile.Triggered=OnFilePrevFile
-		_filePrevFile.HotKey=Key.Tab
-		_filePrevFile.HotKeyModifiers=Modifier.Control|Modifier.Shift
+		For Local dir:=Eachin _projectView.OpenProjects
 		
-		_fileOpenProject=New Action( "Open project" )
-		_fileOpenProject.Triggered=OnFileOpenProject
-		
-		_fileQuit=New Action( "Quit" )
-		_fileQuit.Triggered=OnFileQuit
-		
-		_editUndo=New Action( "Undo" )
-		_editUndo.HotKey=Key.Z
-		_editUndo.HotKeyModifiers=Modifier.Control
-		_editUndo.Triggered=OnEditUndo
-		
-		_editRedo=New Action( "Redo" )
-		_editRedo.HotKey=Key.Y
-		_editRedo.HotKeyModifiers=Modifier.Control
-		_editRedo.Triggered=OnEditRedo
-		
-		_editCut=New Action( "Cut" )
-'		_editCut.HotKey=Key.X
-'		_editCut.HotKeyModifiers=Modifier.Control
-		_editCut.Triggered=OnEditCut
-		
-		_editCopy=New Action( "Copy" )
-'		_editCopy.HotKey=Key.C
-'		_editCopy.HotKeyModifiers=Modifier.Control
-		_editCopy.Triggered=OnEditCopy
-		
-		_editPaste=New Action( "Paste" )
-'		_editPaste.HotKey=Key.V
-'		_editPaste.HotKeyModifiers=Modifier.Control
-		_editPaste.Triggered=OnEditPaste
-		
-		_editSelectAll=New Action( "Select All" )
-'		_editSelectAll.HotKey=Key.A
-'		_editSelectAll.HotKeyModifiers=Modifier.Control
-		_editSelectAll.Triggered=OnEditSelectAll
-		
-		_editFind=New Action( "Find" )
-		_editFind.HotKey=Key.F
-		_editFind.HotKeyModifiers=Modifier.Control
-		_editFind.Triggered=OnEditFind
-		
-		_findNext=New Action( "Find Next" )
-		_findNext.HotKey=Key.F3
-		_findNext.Triggered=OnFindNext
-		
-		_findPrevious=New Action( "Find Previous" )
-		_findPrevious.HotKey=Key.F3
-		_findPrevious.HotKeyModifiers=Modifier.Shift
-		_findPrevious.Triggered=OnFindPrevious
-		
-		_findReplace=New Action( "Replace" )
-		_findReplace.Triggered=OnFindReplace
-		
-		_findReplaceAll=New Action( "Replace All" )
-		_findReplaceAll.Triggered=OnFindReplaceAll
-		
-		_buildDebug=New Action( "Debug" )
-		_buildDebug.HotKey=Key.F5
-		_buildDebug.Triggered=OnBuildDebug
-		
-		_buildRelease=New Action( "Release" )
-		_buildRelease.HotKey=Key.F6
-		_buildRelease.Triggered=OnBuildRelease
-		
-		_buildForceStop=New Action( "Force Stop" )
-		_buildForceStop.HotKey=Key.F5
-		_buildForceStop.HotKeyModifiers=Modifier.Shift
-		_buildForceStop.Triggered=OnBuildForceStop
-
-		_buildLockFile=New Action( "Lock Build File" )
-		_buildLockFile.HotKey=Key.L
-		_buildLockFile.HotKeyModifiers=Modifier.Control
-		_buildLockFile.Triggered=OnBuildLockFile
-		
-		_buildNextError=New Action( "Next Error" )
-		_buildNextError.HotKey=Key.F4
-		_buildNextError.Triggered=OnBuildNextError
-		
-		_helpOnlineHelp=New Action( "Online Help" )
-		_helpOnlineHelp.Triggered=OnHelpOnlineHelp
-
-		_helpOfflineHelp=New Action( "Offline Help" )
-		_helpOfflineHelp.Triggered=OnHelpOfflineHelp
-		
-		_helpAbout=New Action( "About Monkey2" )
-		_helpAbout.Triggered=OnHelpAbout
-		
-		_escape=New Action( "" )
-		_escape.HotKey=Key.Escape
-		_escape.Triggered=OnEscape
-	End
-	
-	Method InitMenus()
-	
-		_newFiles=New Menu( "New..." )
-		Local p:=AssetsDir()+"ted2/newfiles/"
-		For Local f:=Eachin LoadDir( p )
-			Local src:=stringio.LoadString( p+f )
-			_newFiles.AddAction( StripExt( f.Replace( "_"," " ) ) ).Triggered=Lambda()
-				Local doc:=Cast<Mx2Document>( OpenDocument( "" ) )
-				If doc
-					doc.TextDocument.Text=src
-					doc.Save()
-				Endif
-			End
-		Next
-		
-		_scripts=New Menu( "Scripts..." )
-		Local obj:=JsonObject.Load( "asset::ted2/scripts.json" )
-		If obj
-			For Local obj2:=Eachin obj["scripts"].ToArray()
-				Local name:=obj2.ToObject()["name"].ToString()
-				Local script:=obj2.ToObject()["script"].ToString()
-				Local action:=_scripts.AddAction( name )
-				action.Triggered=Lambda()
-					RunScript( script )
-				End
-			Next
-		Endif
-		
-		_recentFiles=New Menu( "Recent Files..." )
-		
-		_closeProject=New Menu( "Close Project..." )
-		
-		_fileMenu=New Menu( "File" )
-		_fileMenu.AddAction( _fileNew )
-		_fileMenu.AddSubMenu( _newFiles )
-		_fileMenu.AddAction( _fileOpen )
-		_fileMenu.AddSubMenu( _recentFiles )
-		_fileMenu.AddSeparator()
-		_fileMenu.AddAction( _fileClose )
-		_fileMenu.AddAction( _fileCloseAll )
-		_fileMenu.AddSeparator()
-		_fileMenu.AddAction( _fileSave )
-		_fileMenu.AddAction( _fileSaveAs )
-		_fileMenu.AddAction( _fileSaveAll )
-		_fileMenu.AddSeparator()
-		_fileMenu.AddAction( _fileNextFile )
-		_fileMenu.AddAction( _filePrevFile )
-		_fileMenu.AddSeparator()
-		_fileMenu.AddAction( _fileOpenProject )
-		_fileMenu.AddSubMenu( _closeProject )
-		_fileMenu.AddSeparator()
-		_fileMenu.AddAction( _fileQuit )
-		
-		_editMenu=New Menu( "Edit" )
-		_editMenu.AddAction( _editUndo )
-		_editMenu.AddAction( _editRedo )
-		_editMenu.AddSeparator()
-		_editMenu.AddAction( _editCut )
-		_editMenu.AddAction( _editCopy )
-		_editMenu.AddAction( _editPaste )
-		_editMenu.AddSeparator()
-		_editMenu.AddAction( _editSelectAll )
-		_editMenu.AddSeparator()
-		_editMenu.AddAction( _editFind )
-		_editMenu.AddAction( _findNext )
-		_editMenu.AddAction( _findPrevious )
-		_editMenu.AddAction( _findReplace )
-		_editMenu.AddAction( _findReplaceAll )
-		
-		_buildMenu=New Menu( "Build" )
-		_buildMenu.AddAction( _buildDebug )
-		_buildMenu.AddAction( _buildRelease )
-		_buildMenu.AddSeparator()
-		_buildMenu.AddAction( _buildNextError )
-		_buildMenu.AddSeparator()
-		_buildMenu.AddAction( _buildLockFile )
-		_buildMenu.AddSeparator()
-		_buildMenu.AddSubMenu( _scripts )
-		_buildMenu.AddSeparator()
-		_buildMenu.AddAction( _buildForceStop )
-		
-		_helpMenu=New Menu( "Help" )
-		_helpMenu.AddAction( _helpOnlineHelp )
-		_helpMenu.AddAction( _helpOfflineHelp )
-		_helpMenu.AddAction( _helpAbout )
-		
-		_menuBar=New MenuBar
-		_menuBar.AddMenu( _fileMenu )
-		_menuBar.AddMenu( _editMenu )
-		_menuBar.AddMenu( _buildMenu )
-		_menuBar.AddMenu( _helpMenu )
-	End
-	
-	Method InitViews()
-	
-		_findDialog=New FindDialog
-		
-		_projectView=New ProjectView		
-		_debugView=New DebugView
-		_helpView=New HelpView
-
-		_browser=New TabView
-		_browser.AddTab( "Project",_projectView )
-		_browser.AddTab( "Debug",_debugView )
-'		_browser.AddTab( "Help",_helpView )
-		_browser.CurrentView=_projectView
-		
-		_console=New Console
-		_console.ReadOnly=True
-		
-		_docTabber=New TabView
-		_docTabber.CurrentChanged=Lambda()
-			MakeCurrent( FindDocument( _docTabber.CurrentView ) )
-		End
-		
-		_docker=New DockingView
-		_docker.ContentView=_docTabber
-		_docker.AddView( _menuBar,"top",0 )
-		_docker.AddView( _browser,"right",250 )
-		_docker.AddView( _console,"bottom",200 )
-		
-	End
-	
-	Method New( title:String,rect:Recti,flags:WindowFlags )
-		Super.New( title,rect,flags )
-		
-		MainWindow=Self
-		
-		ClearColor=Theme.ClearColor
-		
-		SwapInterval=1
-		
-		InitPaths()
-		InitActions()
-		InitMenus()
-		InitViews()
-
-		AddChild( _docker )
-		
-		LoadState()
-		
-		DeleteTmps()
-		
-		UpdateRecentFilesMenu()
-		
-		UpdateCloseProjectMenu()
-		
-		If Not _projects.Length
-			Local dir:=CurrentDir()
-			If _projectView.OpenProject( dir ) _projects.Push( dir )
-		Endif
-
-		App.Idle+=AppIdle
-		
-		Update()
-		
-		If Not _docTabber.Count OnHelpAbout()
-		
-	End
-	
-	Method OnWindowEvent( event:WindowEvent ) Override
-	
-		Select event.Type
-		Case EventType.WindowClose
-			_fileQuit.Trigger()
-		Default
-			Super.OnWindowEvent( event )
-		End
-		
-	End
-		
-	Method ToRecti:Recti( value:JsonValue )
-		Local json:=value.ToArray()
-		Return New Recti( json[0].ToNumber(),json[1].ToNumber(),json[2].ToNumber(),json[3].ToNumber() )
-	End
-	
-	Method UpdateCloseProjectMenu()
-		_closeProject.Clear()
-		For Local dir:=Eachin _projects
-			_closeProject.AddAction( dir ).Triggered=Lambda()
+			_closeProjectMenu.AddAction( dir ).Triggered=Lambda()
+			
 				_projectView.CloseProject( dir )
-				_projects.Remove( dir )
+				
 				UpdateCloseProjectMenu()
 			End
-		Next
-	End
-	
-	Method UpdateRecentFilesMenu()
-		_recentFiles.Clear()
-		For Local path:=Eachin _recent
-			_recentFiles.AddAction( path ).Triggered=Lambda()
-				OpenDocument( path )
-			End
-		Next
-	End
-	
-	Method LoadState()
-	
-		Local obj:=JsonObject.Load( "bin/ted2.state.json" )
-		If Not obj Return
-		
-		If obj.Contains( "openDocuments" )
-			For Local doc:=Eachin obj["openDocuments"].ToArray()
-				Local path:=doc.ToString()
-				If GetFileType( path )<>FileType.File Continue
-				OpenDocument( doc.ToString() )
-			Next
-		Endif
-		
-		If obj.Contains( "recentFiles" )
-			_recent.Clear()
-			For Local file:=Eachin obj["recentFiles"].ToArray()
-				Local path:=file.ToString()
-				If GetFileType( path )<>FileType.File Continue
-				_recent.Push( path )
-			Next
-		End
-		
-		If obj.Contains( "openProjects" )
-			_projects.Clear()
-			For Local proj:=Eachin obj["openProjects"].ToArray()
-				Local dir:=proj.ToString()
-				If Not _projectView.OpenProject( dir ) Continue
-				_projects.Push( dir )
-			Next
-		Endif
-		
-		If obj.Contains( "windowRect" )
-			Frame=ToRecti( obj["windowRect"] )
-		Endif
-		
-		If obj.Contains( "consoleSize" )
-			_docker.SetViewSize( _console,obj["consoleSize"].ToNumber() )
-		Endif
-		
-		If obj.Contains( "browserSize" )
-			_docker.SetViewSize( _browser,obj["browserSize"].ToNumber() )
-		Endif
-		
-		If obj.Contains( "helpTreeSize" )
-			_helpView.SetViewSize( _helpView.HelpTree,obj["helpTreeSize"].ToNumber() )
-		Endif
-		
-		If obj.Contains( "lockedDocument" )
-			Local doc:=OpenDocument( obj["lockedDocument"].ToString() )
-			If doc LockDoc( doc )
-		Endif
-		
-	End
-	
-	Method ToJson:JsonValue( rect:Recti )
-		Return New JsonArray( New JsonValue[]( New JsonNumber( rect.min.x ),New JsonNumber( rect.min.y ),New JsonNumber( rect.max.x ),New JsonNumber( rect.max.y ) ) )
-	End
-	
-	Method SaveState()
-	
-		Local obj:=New JsonObject
-		
-		Local docs:=New JsonArray
-		For Local doc:=Eachin _openDocs
-			docs.Add( New JsonString( doc.Path ) )
-		Next
-		obj["openDocuments"]=docs
-		
-		Local recent:=New JsonArray
-		For Local path:=Eachin _recent
-			recent.Add( New JsonString( path ) )
-		End
-		obj["recentFiles"]=recent
-		
-		Local projects:=New JsonArray
-		For Local dir:=Eachin _projects
-			projects.Add( New JsonString( dir ) )
-		Next
-		obj["openProjects"]=projects
-		
-		obj["windowRect"]=ToJson( Frame )
-		
-		obj["consoleSize"]=New JsonNumber( _docker.GetViewSize( _console ) )
-		
-		obj["browserSize"]=New JsonNumber( _docker.GetViewSize( _browser ) )
-		
-		obj["helpTreeSize"]=New JsonNumber( _helpView.GetViewSize( _helpView.HelpTree ) )
-		
-		If _lockedDoc obj["lockedDocument"]=New JsonString( _lockedDoc.Path )
-		
-		SaveString( obj.ToJson(),"bin/ted2.state.json" )
-	
-	End
-	
-	Method Notify( text:String,title:String="Ted2" )
-		Local buttons:=New String[]( "Okay" )
-		TextDialog.Run( title,text,buttons )
-	End
-	
-	Method Confirm:Bool( text:String,title:String="Ted2" )
-		Local buttons:=New String[]( "Okay","Cancel" )
-		Return TextDialog.Run( title,text,buttons )=0
-	End
-	
-	Method DeleteTmps()
-		For Local i:=1 Until 10
-			Local path:=RealPath( _tmp+"untitled"+i+".monkey2" )
-			If GetFileType( path )=FileType.File 
-				If Not FindDocument( path ) DeleteFile( path )
-			Endif
-		Next
-	End
-	
-	Method AllocTmpPath:String()
-		For Local i:=1 Until 10
-			Local path:=_tmp+"untitled"+i+".monkey2"
-			If GetFileType( path )=FileType.None Return path
-		Next
-		Return ""
-	End
-	
-	Method IsTmpPath:Bool( path:String )
-		Return path.StartsWith( _tmp )
-	End
-	
-	Method BuildDoc:Ted2Document()
-		If _lockedDoc Return _lockedDoc
-		Return _currentDoc
-	End
-	
-	Method LockDoc( doc:Ted2Document )
-
-		If _lockedDoc And _lockedDoc=doc
-			_lockedDoc=Null
-			UpdateTabLabel( doc )
-			Return
-		Endif
-
-		If doc And Not Cast<TextView>( doc.View ) doc=Null
-	
-		Local old:=_lockedDoc
-		_lockedDoc=doc
-		
-		If _lockedDoc=old Return
-		
-		UpdateTabLabel( old )
-		UpdateTabLabel( _lockedDoc )
-	
-	End
-	
-	Method UpdateKeyView()
-	
-		If Not _currentDoc Return
-		
-		_currentDoc.View.MakeKeyView()
-	End
-	
-	Method MakeCurrent( doc:Ted2Document )
-	
-		If doc=_currentDoc Return
-		
-		If doc And _docTabber.CurrentView<>doc.View
-			_docTabber.CurrentView=doc.View
-		Endif
-		
-		_currentDoc=doc
-		_currentTextView=Null
-		If doc _currentTextView=Cast<TextView>( doc.View )
-		
-		
-		App.Idle+=Lambda()
-			If _currentDoc
-				Title="Ted2 - "+_currentDoc.Path
-			Else
-				Title="Ted2"
-			Endif
-		End
-
-		UpdateKeyView()
-		
-		Update()
-	End
-	
-	Method FindDocument:Ted2Document( path:String )
-		For Local doc:=Eachin _openDocs
-			If doc.Path=path Return doc
-		Next
-		Return Null
-	End	
-	
-	Method FindDocument:Ted2Document( view:View )
-		For Local doc:=Eachin _openDocs
-			If doc.View=view Return doc
-		Next
-		Return Null
-	End	
-
-	Method ReadError( path:String )
-		Notify( "I/O Error reading file '"+path+"'" )
-	End
-	
-	Method WriteError( path:String )
-		Notify( "I/O Error writing file '"+path+"'" )
-	End
-	
-	Method DocumentTabLabel:String( doc:Ted2Document )
-		Local label:=StripDir( doc.Path )
-		If ExtractExt( doc.Path ).ToLower()=".monkey2"  label=StripExt( label )
-		If IsTmpPath( doc.Path ) label="<"+label+">"
-		If doc=_lockedDoc label="+"+label
-		If doc.Dirty label+="*"
-		Return label
-	End
-	
-	Method UpdateTabLabel( doc:Ted2Document )
-		If doc _docTabber.SetTabLabel( doc.View,DocumentTabLabel( doc ) )
-	End
-	
-	Method OpenDocument:Ted2Document( path:String,addRecent:Bool=False,makeCurrent:Bool=True )
-	
-		Local doc:Ted2Document
-
-		If path
-
-			path=RealPath( path )
-			
-			Local ext:=ExtractExt( path ).ToLower()
-			
-			Select ext
-			Case ".monkey2"
-			Case ".png",".jpg",".bmp"
-			Case ".h",".hpp",".hxx",".c",".cpp",".cxx",".m",".mm",".s",".asm"
-			Case ".html",".md",".json",".xml"
-			Case ".sh",".bat"
-			Case ".glsl"
-			Case ".txt"
-			Default
-				Notify( "Unrecognized file type extension for file '"+path+"'" )
-				Return Null
-			End
-		
-			doc=FindDocument( path )
-			If doc
-				If makeCurrent MakeCurrent( doc )
-				Return doc
-			Endif
-			
-			Select ext
-			Case ".monkey2"
-				doc=New Mx2Document( path )
-			Case ".png",".jpg"
-				doc=New ImgDocument( path )
-			Default
-				doc=New TxtDocument( path )
-			End
-			
-		Else
-		
-			path=AllocTmpPath()
-			If Not path
-				Notify( "Can't create temporary file" )
-				Return Null
-			Endif
-			SaveString( "",path )
-			
-			doc=New Mx2Document( path )
-		
-		Endif
-		
-		If GetFileType( path )<>FileType.File Or Not doc.Load()
-			ReadError( path )
-			Return Null
-		End
-		
-		doc.DirtyChanged=Lambda()
-			UpdateTabLabel( doc )
-		End
-		
-		_docTabber.AddTab( DocumentTabLabel( doc ),doc.View )
-		_openDocs.Add( doc )
-		
-		If addRecent
-			_recent.Remove( path )
-			_recent.Insert( 0,path )
-			If _recent.Length>20 _recent.Resize( 20 )
-			UpdateRecentFilesMenu()
-		Endif
-		
-		If makeCurrent MakeCurrent( doc )
-
-		Return doc
-	End
-	
-	Method RenameDocument( doc:Ted2Document,path:String )
-
-		doc.Rename( path )
-
-		UpdateTabLabel( doc )
-
-	End
-	
-	Method SaveDocument:Bool( doc:Ted2Document )
-	
-		If IsTmpPath( doc.Path )
-
-			Local path:=RequestFile( "Save As","",True )
-
-			If Not path Return False
 			
-			RenameDocument( doc,path )
-		Endif
-		
-		If doc.Save() Return True
-		
-		WriteError( doc.Path )
-		
-		Return False
-	End
-	
-	Method CloseDocument( doc:Ted2Document )
-	
-		Local index:=_docTabber.IndexOfView( doc.View )
-		
-		_docTabber.RemoveTab( doc.View )
-
-		_openDocs.Remove( doc )
-		
-		doc.Close()
-			
-		If IsTmpPath( doc.Path ) DeleteFile( doc.Path )
-		
-		If doc=_lockedDoc _lockedDoc=Null
-		
-		If doc<>_currentDoc Return
-		
-		If Not _docTabber.Count 
-			MakeCurrent( Null )
-			Return
-		Endif
-		
-		If index=_docTabber.Count index-=1
-		
-		MakeCurrent( FindDocument( _docTabber.ViewAtIndex( index ) ) )
-	End
-	
-	Method GotoError( err:Mx2Error )
-	
-		Local doc:=Cast<Mx2Document>( OpenDocument( err.path ) )
-		If Not doc Return
-		
-		Local tv:=Cast<TextView>( doc.View )
-		If Not tv Return
-		
-		Local sol:=tv.Document.StartOfLine( err.line )
-		tv.SelectText( sol,sol )
-		
-		Return
-	End
-	
-	Method Build( config:String )
-
-		If _console.Running Return
-		
-		Local buildDoc:=Cast<Mx2Document>( BuildDoc() )
-		If Not buildDoc Return
-		
-		For Local doc:=Eachin _openDocs
-			Local mx2Doc:=Cast<Mx2Document>( doc )
-			If mx2Doc mx2Doc.Errors.Clear()
-		Next
-		
-		For Local doc:=Eachin _openDocs
-			If doc.Save() Continue
-			WriteError( doc.Path )
-			Return
-		Next
-
-		_console.Clear()
-		
-		Local cmd:=_mx2cc+" makeapp -apptype=gui -build -config="+config+" ~q"+buildDoc.Path+"~q"
-		
-		If Not _console.Start( cmd )
-			Notify( "Failed to start process: '"+cmd+"'" )
-			Return
-		Endif
-		
-		Local appFile:String
-		
-		Local dialog:=New TextDialog( "Ted2","Building "+buildDoc.Path+"..." )
-		
-		dialog.AddAction( "Cancel" ).Triggered=_console.Terminate
-		
-		dialog.Open()
-
-		_errors.Clear()
-		
-		Repeat
-		
-			Local stdout:=_console.ReadStdout()
-			If Not stdout Exit
-			
-			If stdout.StartsWith( "Application built:" )
-				appFile=stdout.Slice( stdout.Find( ":" )+1 ).Trim()
-			Else
-				Local i:=stdout.Find( "] : Error : " )
-				If i<>-1
-					Local j:=stdout.Find( " [" )
-					If j<>-1
-						Local path:=stdout.Slice( 0,j )
-						Local line:=Int( stdout.Slice( j+2,i ) )-1
-						Local msg:=stdout.Slice( i+12 )
-						
-						Local err:=New Mx2Error( path,line,msg )
-						Local doc:=Cast<Mx2Document>( OpenDocument( path,False,False ) )
-						
-						If doc
-							doc.Errors.Add( err )
-							If _errors.Empty GotoError( err )
-							_errors.Add( err )
-						Endif
-						
-					Endif
-				Endif
-			Endif
-			
-			_console.Write( stdout )
-		
-		Forever
-		
-		dialog.Close()
-		
-		If Not appFile Return
-		
-		cmd=appFile
-		
-		If Not _console.Start( cmd )
-			Notify( "Failed to start process: '"+cmd+"'" )
-			Return
-		Endif
-		
-		_console.Clear()
-		
-		Local tab:=_browser.CurrentView
-			
-		If config="debug"
-			_console.Write( "Debugging app:"+appFile+"~n" )
-			_browser.CurrentView=_debugView
-			_debugView.DebugBegin()
-		Else
-			_console.Write( "Running app:"+appFile+"~n" )
-		Endif
-		
-		Repeat
-			
-			Local stdout:=_console.ReadStdout()
-			If Not stdout Exit
-			
-			If config="debug" And stdout="{{!DEBUG!}}~n"
-				_debugView.DebugStop()
-				Continue
-			End
-			
-			_console.Write( stdout )
-		
-		Forever
-		
-		If config="debug"
-			_debugView.DebugEnd()
-		Endif
-		
-		For Local doc:=Eachin _openDocs
-			Local mx2Doc:=Cast<Mx2Document>( doc )
-			If mx2Doc mx2Doc.DebugLine=-1
-		Next
-		
-		_browser.CurrentView=tab
-		
-		_console.Write( "Done.~n" )
-
-	End
-	
-	Method RunScript( script:String )
-	
-		If _console.Running Return
-		
-		For Local doc:=Eachin _openDocs
-			If doc.Save() Continue
-			WriteError( doc.Path )
-			Return
-		Next
-		
-		_console.Clear()
-	
-		Local cmd:=script
-
-#If __HOSTOS__="windows"
-        cmd=script+".bat"
-#Else If __HOSTOS__="macos"
-        cmd="/bin/bash -l "+script+".sh"
-#Else
-        cmd="/bin/bash -l -c "+script+".sh"
-#Endif		
-		
-		Local cd:=CurrentDir()
-		ChangeDir( "scripts" )
-		Local r:=_console.Start( cmd )
-		ChangeDir( cd )
-		
-		If Not r
-			Notify( "Failed to start process: '"+cmd+"'" )
-			Return
-		Endif
-		
-		Repeat
-
-			Local stdout:=_console.ReadStdout()
-			If Not stdout Exit
-
-			_console.Write( stdout )
-		Forever
-			
-		_console.Write( "Done.~n" )
-	End
-	
-	Method RequestDir:String( title:String,dir:String )
-
-		Local future:=New Future<String>
-		
-		App.Idle+=Lambda()
-			future.Set( mojo.requesters.RequestDir( title,dir ) )
-		End
-		
-		Return future.Get()
-	End
-
-	Method RequestFile:String( title:String,filters:String,save:Bool,path:String="" )
-
-		Local future:=New Future<String>
-		
-		App.Idle+=Lambda()
-			future.Set( mojo.requesters.RequestFile( title,filters,save,path ) )
-		End
-		
-		Return future.Get()
-	End
-
-	Method UpdateActions()
-	
-		Local keyView:=Cast<TextView>( App.KeyView )
-	
-		Local dirtyDocs:Bool
-		For Local doc:=Eachin _openDocs
-			If doc.Dirty dirtyDocs=True
 		Next
-		
-		While Not _errors.Empty And _errors.First.removed
-			_errors.RemoveFirst()
-		Wend
-	
-		_fileClose.Enabled=_currentDoc<>Null
-		_fileCloseAll.Enabled=_openDocs.Length<>0
-		_fileSave.Enabled=_currentDoc<>Null And _currentDoc.Dirty
-		_fileSaveAs.Enabled=_currentDoc<>Null
-		_fileSaveAll.Enabled=dirtyDocs
-		_fileNextFile.Enabled=_docTabber.Count>1
-		_filePrevFile.Enabled=_docTabber.Count>1
-		
-		_editUndo.Enabled=keyView And keyView.CanUndo
-		_editRedo.Enabled=keyView And keyView.CanRedo
-		_editCut.Enabled=keyView And keyView.CanCut
-		_editCopy.Enabled=keyView And keyView.CanCopy
-		_editPaste.Enabled=keyView And keyView.CanPaste
-		_editSelectAll.Enabled=keyView<>Null
-		
-		_buildDebug.Enabled=BuildDoc()<>Null And Not _console.Running
-		_buildRelease.Enabled=BuildDoc()<>Null And Not _console.Running
-		_buildLockFile.Enabled=_currentDoc<>Null
-		_buildForceStop.Enabled=_console.Running
-		_buildNextError.Enabled=Not _errors.Empty
-		
-		_scripts.Enabled=Not _console.Running
 	End
 	
-	Method AppIdle()
+	Method OnAppIdle()
 	
-		UpdateActions()
+		_docsManager.Update()
+		_fileActions.Update()
+		_editActions.Update()
+		_findActions.Update()
+		_buildActions.Update()
 		
-		App.RequestRender()
+		_forceStop.Enabled=_buildConsole.Running Or _outputConsole.Running
 	
-		App.Idle+=AppIdle
+		App.Idle+=OnAppIdle
 		
 		GCCollect()	'thrash that GC!
 	End

+ 0 - 168
src/ted2/mojox/action.monkey2

@@ -1,168 +0,0 @@
-
-Namespace mojox
-
-Class Action
-
-	Field Triggered:Void()
-	
-	Field Modified:Void()
-
-	Method New( label:String,icon:Image=Null )
-	
-		_label=label
-		_icon=icon
-	End
-	
-	Property Label:String()
-	
-		Return _label
-	
-	Setter( label:String )
-		If label=_label Return
-	
-		_label=label
-		
-		Modified()
-	End
-	
-	Property Icon:Image()
-	
-		Return _icon
-	
-	Setter( icon:Image )
-		If icon=_icon Return
-		
-		_icon=icon
-		
-		Modified()
-	End
-	
-	Property Enabled:Bool()
-	
-		Return _enabled
-	
-	Setter( enabled:Bool )
-		If enabled=_enabled Return
-		
-		_enabled=enabled
-		
-		If _enabled EnableHotKey() Else DisableHotKey()
-		
-		Modified()
-	End
-	
-	Property Async:Bool()
-	
-		Return _async
-	
-	Setter( async:Bool )
-	
-		_async=async
-	End
-	
-	Property HotKey:Key()
-	
-		Return _hotKey
-	
-	Setter( hotKey:Key )
-		If hotKey=_hotKey Return
-	
-		If _enabled DisableHotKey()
-	
-		_hotKey=hotKey
-		
-		If _enabled EnableHotKey()
-	End
-	
-	Property HotKeyModifiers:Modifier()
-	
-		Return _hotKeyMods
-	
-	Setter( hotKeyModifiers:Modifier )
-	
-		_hotKeyMods=hotKeyModifiers
-	End
-	
-	Property HotKeyLabel:String()
-
-		If Not _hotKey Return ""
-		
-		Local label:=""
-		If _hotKeyMods & Modifier.Shift label+="Shift"
-		If _hotKeyMods & Modifier.Control label+="+Ctrl"
-		If _hotKeyMods & Modifier.Alt label+="+Alt"
-		label+="+"+Keyboard.KeyName( _hotKey )
-		If label.StartsWith( "+" ) label=label.Slice( 1 )
-		Return label
-	End
-	
-	Method Trigger()
-	
-		If _async
-			New Fiber( Triggered )
-		Else
-			Triggered()
-		Endif
-		
-	End
-	
-	Private
-	
-	Field _enabled:Bool=True
-	Field _label:String
-	Field _icon:Image
-	Field _hotKey:Key
-	Field _hotKeyMods:Modifier
-	Field _async:Bool=True
-	
-	Global _hotKeys:Map<Key,Stack<Action>>
-	
-	Method DisableHotKey()
-	
-		If Not _hotKey Return
-		
-		_hotKeys[_hotKey].Remove( Self )
-	End
-	
-	Method EnableHotKey()
-	
-		If Not _hotKey Return
-		
-		If Not _hotKeys
-			
-			_hotKeys=New Map<Key,Stack<Action>>
-			
-			App.KeyEventFilter+=Lambda( event:KeyEvent )
-			
-				If event.Eaten Return
-				
-				If event.Type<>EventType.KeyDown Return
-
-				Local actions:=_hotKeys[event.Key]
-				If Not actions Return
-
-				Local mods:=event.Modifiers
-				mods|=Cast<Modifier>( (Int(mods) & $541) Shl 1 | (Int(mods) & $a82) Shr 1 )
-
-				For Local action:=Eachin actions
-					If event.Key<>action._hotKey Continue
-					If mods<>action._hotKeyMods Continue
-					action.Trigger()
-					event.Eat()
-					Return
-				Next
-				
-			End
-			
-		Endif
-		
-		Local actions:=_hotKeys[_hotKey]
-		If Not actions
-			actions=New Stack<Action>
-			_hotKeys[_hotKey]=actions
-		Endif
-		
-		actions.Add( Self )
-	End
-
-End

BIN
src/ted2/mojox/assets/DejaVuSansMono.ttf


BIN
src/ted2/mojox/assets/HelveticaNeue.ttf


BIN
src/ted2/mojox/assets/Inconsolata-g.ttf


BIN
src/ted2/mojox/assets/RobotoMono-Regular.ttf


BIN
src/ted2/mojox/assets/checkmark_icons.png


+ 0 - 327
src/ted2/mojox/assets/htmlview_master_css.css

@@ -1,327 +0,0 @@
-html {
-    display: block;
-    height:100%;
-    width:100%;
-	position: relative;
-}
-
-head {
-    display: none
-}
-
-meta {
-    display: none
-}
-
-title {
-    display: none
-}
-
-link {
-    display: none
-}
-
-style {
-    display: none
-}
-
-script {
-    display: none
-}
-
-body {
-	display:block; 
-	margin:8px; 
-    height:100%;
-    width:100%;
-}
-
-p {
-	display:block; 
-	margin-top:1em; 
-	margin-bottom:1em;
-}
-
-b, strong {
-	display:inline; 
-	font-weight:bold;
-}
-
-i, em {
-	display:inline; 
-	font-style:italic;
-}
-
-center 
-{
-	text-align:center;
-	display:block;
-}
-
-a:link
-{
-	text-decoration: underline;
-	color: #00f;
-	cursor: pointer;
-}
-
-h1, h2, h3, h4, h5, h6, div {
-	display:block;
-}
-
-h1 {
-	font-weight:bold; 
-	margin-top:0.67em; 
-	margin-bottom:0.67em; 
-	font-size: 2em;
-}
-
-h2 {
-	font-weight:bold; 
-	margin-top:0.83em; 
-	margin-bottom:0.83em; 
-	font-size: 1.5em;
-}
-
-h3 {
-	font-weight:bold; 
-	margin-top:1em; 
-	margin-bottom:1em; 
-	font-size:1.17em;
-}
-
-h4 {
-	font-weight:bold; 
-	margin-top:1.33em; 
-	margin-bottom:1.33em
-}
-
-h5 {
-	font-weight:bold; 
-	margin-top:1.67em; 
-	margin-bottom:1.67em;
-	font-size:.83em;
-}
-
-h6 {
-	font-weight:bold; 
-	margin-top:2.33em; 
-	margin-bottom:2.33em;
-	font-size:.67em;
-} 
-
-br {
-	display:inline-block;
-}
-
-br[clear="all"]
-{
-	clear:both;
-}
-
-br[clear="left"]
-{
-	clear:left;
-}
-
-br[clear="right"]
-{
-	clear:right;
-}
-
-span {
-	display:inline
-}
-
-img {
-	display: inline-block;
-}
-
-img[align="right"]
-{
-	float: right;
-}
-
-img[align="left"]
-{
-	float: left;
-}
-
-hr {
-    display: block;
-    margin-top: 0.5em;
-    margin-bottom: 0.5em;
-    margin-left: auto;
-    margin-right: auto;
-    border-style: inset;
-    border-width: 1px
-}
-
-
-/***************** TABLES ********************/
-
-table {
-    display: table;
-    border-style: solid;
-    border-collapse: separate;
-    border-spacing: 2px;
-    border-top-color:gray;
-    border-left-color:gray;
-    border-bottom-color:black;
-    border-right-color:black;
-}
-
-tbody, tfoot, thead {
-	display:table-row-group;
-	vertical-align:middle;
-}
-
-tr {
-    display: table-row;
-    vertical-align: inherit;
-    border-color: inherit;
-}
-
-td, th {
-    display: table-cell;
-    vertical-align: inherit;
-    border-width:1px;
-    padding:1px;
-}
-
-th {
-	font-weight: bold;
-}
-
-table[border] {
-    border-style:solid;
-}
-
-table[border|=0] {
-    border-style:none;
-}
-
-table[border] td, table[border] th {
-    border-style:solid;
-    border-top-color:black;
-    border-left-color:black;
-    border-bottom-color:gray;
-    border-right-color:gray;
-}
-
-table[border|=0] td, table[border|=0] th {
-    border-style:none;
-}
-
-caption {
-	display: table-caption;
-}
-
-td[nowrap], th[nowrap] {
-	white-space:nowrap;
-}
-
-tt, code, kbd, samp {
-    font-family: monospace
-}
-
-pre, xmp, plaintext, listing {
-    display: block;
-    font-family: monospace;
-    white-space: pre;
-    margin: 1em 0
-}
-
-/***************** LISTS ********************/
-
-ul, menu, dir {
-    display: block;
-    list-style-type: disc;
-    margin-top: 1em;
-    margin-bottom: 1em;
-    margin-left: 0;
-    margin-right: 0;
-    padding-left: 40px
-}
-
-ol {
-    display: block;
-    list-style-type: decimal;
-    margin-top: 1em;
-    margin-bottom: 1em;
-    margin-left: 0;
-    margin-right: 0;
-    padding-left: 40px
-}
-
-li {
-    display: list-item;
-}
-
-ul ul, ol ul {
-    list-style-type: circle;
-}
-
-ol ol ul, ol ul ul, ul ol ul, ul ul ul {
-    list-style-type: square;
-}
-
-dd {
-    display: block;
-    margin-left: 40px;
-}
-
-dl {
-    display: block;
-    margin-top: 1em;
-    margin-bottom: 1em;
-    margin-left: 0;
-    margin-right: 0;
-}
-
-dt {
-    display: block;
-}
-
-ol ul, ul ol, ul ul, ol ol {
-    margin-top: 0;
-    margin-bottom: 0
-}
-
-blockquote {
-	display: block;
-	margin-top: 1em;
-	margin-bottom: 1em;
-	margin-left: 40px;
-	margin-left: 40px;
-}
-
-/*********** FORM ELEMENTS ************/
-
-form {
-	display: block;
-	margin-top: 0em;
-}
-
-option {
-	display: none;
-}
-
-input, textarea, keygen, select, button, isindex {
-	margin: 0em;
-	color: initial;
-	line-height: normal;
-	text-transform: none;
-	text-indent: 0;
-	text-shadow: none;
-	display: inline-block;
-}
-input[type="hidden"] {
-	display: none;
-}
-
-
-article, aside, footer, header, hgroup, nav, section 
-{
-	display: block;
-}

+ 0 - 24
src/ted2/mojox/assets/markdown_wrapper.html

@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-
-<head>
-
-<style>
-
-body{
-	background: #888;
-	color: #fff;
-}
-
-</style>
-
-</head>
-
-<html>
-
-<body>
-
-${CONTENT}
-
-</body>
-
-</html>

BIN
src/ted2/mojox/assets/monkey_font.png


BIN
src/ted2/mojox/assets/treenode_collapsed.png


BIN
src/ted2/mojox/assets/treenode_expanded.png


+ 0 - 128
src/ted2/mojox/button.monkey2

@@ -1,128 +0,0 @@
-
-Namespace mojox
-
-Class Button Extends Label
-
-	Method New()
-		Layout="float"
-		Style=Style.GetStyle( "mojo.Button" )
-		TextGravity=New Vec2f( .5,.5 )
-	End
-	
-	Method New( icon:Image )
-		Self.New()
-		
-		Icon=icon
-	End
-	
-	Method New( text:String,icon:Image=Null )
-		Self.New()
-
-		Text=text
-		Icon=icon
-	End
-	
-	Method New( action:Action )
-		Self.New()
-		
-		Text=action.Label
-		Icon=action.Icon
-		
-		Clicked=Lambda()
-			action.Trigger()
-		End
-		
-		action.Modified=Lambda()
-			Enabled=action.Enabled
-			Text=action.Label
-			Icon=action.Icon
-		End
-	End
-	
-	Property Checkable:Bool()
-	
-		Return _checkable
-	
-	Setter( checkable:Bool)
-	
-		_checkable=checkable
-	End
-	
-	Property Checked:Bool()
-	
-		Return _checked
-	
-	Setter( checked:Bool )
-	
-		_checked=checked
-	End
-	
-	Property Selected:Bool()
-	
-		Return _selected
-	
-	Setter( selected:Bool )
-	
-		_selected=selected
-		
-		UpdateStyleState()
-	End
-	
-	Protected
-	
-	Method OnValidateStyle() Override
-	
-		If _checkable And _checked
-			CheckMark=RenderStyle.GetImage( "checkmark:checked" )
-		Else If _checkable
-			CheckMark=RenderStyle.GetImage( "checkmark:unchecked" )
-		Else
-			CheckMark=Null
-		End
-	End
-	
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		Select event.Type
-		Case EventType.MouseDown
-			_org=event.Location
-			_active=True
-		Case EventType.MouseUp
-			If _active And _hover
-				If _checkable _checked=Not _checked
-				Clicked()
-			Endif
-			_active=False
-		Case EventType.MouseEnter
-			_hover=True
-		Case EventType.MouseLeave
-			_hover=False
-		Case EventType.MouseMove
-			If _active Dragged( event.Location-_org )
-		End
-		
-		UpdateStyleState()
-	End
-	
-	Method UpdateStyleState()
-
-		If _selected
-			StyleState="selected"
-		Else If _active And _hover
-			StyleState="active"
-		Else If _active Or _hover
-			StyleState="hover"
-		Else
-			StyleState=""
-		Endif
-	
-	End
-
-	Field _selected:Bool
-	Field _checkable:Bool
-	Field _checked:Bool
-	Field _active:Bool
-	Field _hover:Bool
-	Field _org:Vec2i
-
-End

+ 0 - 135
src/ted2/mojox/console.monkey2

@@ -1,135 +0,0 @@
-
-Namespace mojox
-
-Class Console Extends TextView
-
-	Field Finished:Void( exitCode:Int )
-	
-	Property Running:Bool()
-
-		Return _running
-	End
-
-	Property Process:Process()
-	
-		If _running Return _process
-		
-		Return Null
-	End
-	
-	Method Start:Bool( cmd:String )
-	
-		If _running Return False
-	
-		_process=New Process
-		
-		_process.Finished=Lambda()
-			_procOpen=False
-			UpdateRunning()
-		End
-		
-		_process.StdoutReady=Lambda()
-		
-			Local stdout:=_process.ReadStdout()
-			
-			If Not stdout
-				If _stdout _stdoutBuf.Add( _stdout )
-				_stdoutOpen=False
-				UpdateRunning()
-				Return
-			Endif
-			
-			stdout=_stdout+stdout.Replace( "~r~n","~n" )
-			
-			Local i0:=0
-			Repeat
-				Local i:=stdout.Find( "~n",i0 )
-				If i=-1
-					_stdout=stdout.Slice( i0 )
-					Exit
-				Endif
-				_stdoutBuf.Add( stdout.Slice( i0,i+1 ) )
-				i0=i+1
-			Forever
-			
-			If _stdoutWaiting And Not _stdoutBuf.Empty _stdoutWaiting.Set( True )
-			
-		End
-		
-		If Not _process.Start( cmd ) Return False
-		
-		_running=True
-		_procOpen=True
-		_stdoutOpen=True
-		
-		_stdout=""
-		_stdoutBuf.Clear()
-		_stdoutWaiting=Null
-		
-		Return True
-	End
-	
-	Method ReadStdout:String()
-	
-		While _stdoutBuf.Empty
-		
-			If Not _stdoutOpen
-				If _procOpen
-					_stdoutWaiting=New Future<Bool>
-					_stdoutWaiting.Get()
-					_stdoutWaiting=Null
-				Endif
-				Return ""
-			Endif
-			
-			_stdoutWaiting=New Future<Bool>
-			_stdoutWaiting.Get()
-			_stdoutWaiting=Null
-		Wend
-		
-		Return _stdoutBuf.RemoveFirst()
-	End
-	
-	Method WriteStdin( str:String )
-	
-		If Not _procOpen Return
-	
-		_process.WriteStdin( str )
-	End
-	
-	Method Terminate()
-	
-		If Not _procOpen Return
-	
-		_process.Terminate()
-	End
-	
-	Method Write( text:String )
-	
-		ReplaceText( text )
-	End
-	
-	Private
-	
-	Field _process:Process
-	
-	Field _running:Bool
-	Field _procOpen:Bool
-	
-	Field _stdoutOpen:Bool
-	Field _stdout:String
-	Field _stdoutBuf:=New StringList
-	Field _stdoutWaiting:Future<Bool>
-	
-	Method UpdateRunning()
-	
-		If Not _running Or _procOpen Or _stdoutOpen Return
-		
-		_running=False
-		
-		Finished( _process.ExitCode )
-		
-		If _stdoutWaiting _stdoutWaiting.Set( True )
-	End
-
-End

+ 0 - 214
src/ted2/mojox/dialog.monkey2

@@ -1,214 +0,0 @@
-
-Namespace mojox
-
-Class DialogTitle Extends Label
-
-	Field Dragged:Void( v:Vec2i )
-
-	Method New( text:String="" )
-		Super.New( text )
-'		Layout="fill"
-		Style=Style.GetStyle( "mojo.DialogTitle" )
-	End
-	
-	Private
-	
-	Field _org:Vec2i
-	Field _drag:Bool
-	Field _hover:Bool
-	
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		Select event.Type
-		Case EventType.MouseDown
-			_drag=True
-			_org=event.Location
-		Case EventType.MouseUp
-			_drag=False
-		Case EventType.MouseEnter
-			_hover=True
-		Case EventType.MouseLeave
-			_hover=False
-		Case EventType.MouseMove
-			If _drag Dragged( event.Location-_org )
-		End
-		
-		If _drag
-			StyleState="active"
-		Else If _hover
-			StyleState="hover"
-		Else
-			StyleState=""
-		Endif
-		
-	End
-
-End
-
-Class Dialog Extends View
-
-	Field Opened:Void()
-	Field Closed:Void()
-
-	Method New()
-		Layout="float"
-		Style=Style.GetStyle( "mojo.Dialog" )
-		Gravity=New Vec2f( 0,0 )
-		Visible=False
-		
-		_title=New DialogTitle
-		_title.Layout="fill"
-		_title.Style=Style.GetStyle( "mojo.DialogTitle" )
-		_title.Dragged=Lambda( vec:Vec2i )
-			Offset+=vec
-		End
-		
-		_content=New DockingView
-		_content.Style=Style.GetStyle( "mojo.DialogContent" )
-		
-		_actions=New DockingView
-		_actions.Style=Style.GetStyle( "mojo.DialogActions" )
-		_actions.Layout="float"
-		
-		_docker=New DockingView
-
-		_docker.AddView( _title,"top" )
-		_docker.ContentView=_content
-		_docker.AddView( _actions,"bottom" )
-		
-		AddChild( _docker )
-	End
-	
-	Method New( title:String )
-		Self.New()
-		
-		Title=title
-	End
-
-	Property Title:String()
-	
-		Return _title.Text
-	
-	Setter( title:String )
-	
-		_title.Text=title
-	End
-	
-	Property ContentView:View()
-	
-		Return _content.ContentView
-	
-	Setter( contentView:View )
-	
-		_content.ContentView=contentView
-	End
-	
-	Method AddAction( action:Action )
-
-		Local button:=New Button( action )
-
-		_actions.AddView( button,"left" )
-	End
-	
-	Method AddAction:Action( label:String,icon:Image=Null )
-	
-		Local action:=New Action( label,icon )
-		AddAction( action )
-		Return action
-	End
-	
-	Method Open()
-	
-		Visible=True
-	
-		_window=App.ActiveWindow
-		
-		Measure()
-		
-		Offset=(_window.Rect.Size-MeasuredSize)/New Vec2i( 2,3 )
-		
-		_window.AddChild( Self )
-
-		Visible=True
-		
-		Opened()
-	End
-	
-	Method Close()
-	
-		_window.RemoveChild( Self )
-		
-		_window=Null
-	
-		Visible=False
-		
-		Closed()
-	End
-	
-	Private
-	
-	Field _title:DialogTitle
-	Field _content:DockingView
-	Field _actions:DockingView
-	Field _docker:DockingView
-	Field _window:Window
-	
-	Method OnMeasure:Vec2i() Override
-	
-		Return _docker.LayoutSize
-	End
-	
-End
-
-Class TextDialog Extends Dialog
-
-	Method New( title:String="",text:String="" )
-		Super.New( title )
-		
-		_label=New Label( text )
-		
-		ContentView=_label
-	End
-	
-	Property Text:String()
-	
-		Return _label.Text
-	
-	Setter( text:String )
-		
-		_label.Text=text
-		
-	End
-	
-	Function Run:Int( title:String,text:String,buttons:String[] )
-	
-		Local dialog:=New TextDialog( title,text )
-		
-		Local result:=New Future<Int>
-		
-		For Local i:=0 Until buttons.Length
-		
-			dialog.AddAction( buttons[i] ).Triggered=Lambda()
-			
-				result.Set( i )
-			End
-		Next
-		
-		dialog.Open()
-		
-		App.BeginModal( dialog )
-		
-		Local r:=result.Get()
-		
-		App.EndModal()
-		
-		dialog.Close()
-		
-		Return r
-	End
-	
-	Private
-	
-	Field _label:Label
-	
-End

+ 0 - 329
src/ted2/mojox/dockingview.monkey2

@@ -1,329 +0,0 @@
-
-Namespace mojox
-
-Class DragKnob Extends View
-
-	Field Dragged:Void( v:Vec2i )
-
-	Method New()
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.DragKnob" )
-	End
-	
-	Private
-	
-	Field _org:Vec2i
-	
-	Field _drag:Bool
-	Field _hover:Bool
-	
-	Method OnMeasure:Vec2i() Override
-	
-		Return New Vec2i( 0,0 )
-	End
-	
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		Select event.Type
-		Case EventType.MouseDown
-			_drag=True
-			_org=event.Location
-		Case EventType.MouseUp
-			_drag=False
-		Case EventType.MouseEnter
-			_hover=True
-		Case EventType.MouseLeave
-			_hover=False
-		Case EventType.MouseMove
-			If _drag Dragged( event.Location-_org )
-		End
-		
-		If _drag
-			StyleState="active"
-		Else If _hover
-			StyleState="hover"
-		Else
-			StyleState=""
-		Endif
-		
-	End
-	
-End
-
-Class DockView Extends View
-
-	Method New( view:View,location:String,size:Int,resizable:Bool )
-		_view=view
-		_location=location
-		_size=size
-		_resizable=resizable
-		
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.DockView" )
-		
-		AddChild( _view.Container )
-
-		If _size And _resizable
-			_knob=New DragKnob
-			_knob.Dragged=Lambda( v:Vec2i )
-				Select _location
-				Case "top"
-					_size+=v.y
-				Case "bottom"
-					_size-=v.y
-				Case "left"
-					_size+=v.x
-				Case "right"
-					_size-=v.x
-				End
-				_size=Max( _size,0 )
-			End
-			AddChild( _knob )
-		Endif
-	End
-	
-	Property View:View()
-	
-		Return _view
-		
-	Setter( view:View )
-	
-		If _view RemoveChild( _view.Container )
-		
-		_view=view
-		
-		If _view AddChild( _view.Container )
-	End
-	
-	Property Location:String()
-	
-		Return _location
-	End
-	
-	Property Size:Int()
-	
-		Return _size
-		
-	Setter( size:Int )
-	
-		_size=size
-	End
-	
-	Private
-	
-	Field _view:View
-	Field _knob:DragKnob
-	Field _location:String
-	Field _size:Int
-	Field _resizable:Bool
-	
-	Method OnMeasure:Vec2i() Override
-	
-		Local size:=_view.Container.LayoutSize
-		
-		If _knob
-			Local w:=_knob.LayoutSize.x
-			Local h:=_knob.LayoutSize.y
-			Select _location
-			Case "top","bottom"
-				size.y=_size+h
-			Case "left","right"
-				size.x=_size+w
-			End
-		Else If _size
-			Select _location
-			Case "top","bottom"
-				size.y=_size
-			Case "left","right"
-				size.x=_size
-			End
-		Endif
-		
-		Return size
-	End
-	
-	Method OnLayout:Void() Override
-	
-		Local rect:=Rect
-		
-		If _knob
-			Local w:=_knob.LayoutSize.x
-			Local h:=_knob.LayoutSize.y
-			Select _location
-			Case "top"
-				_knob.Frame=New Recti( 0,Height-h,Width,Height )
-				rect.Bottom-=h
-			Case "bottom"
-				_knob.Frame=New Recti( 0,0,Width,h )
-				rect.Top+=h
-			Case "left"
-				_knob.Frame=New Recti( Width-w,0,Width,Height )
-				rect.Right-=w
-			Case "right"
-				_knob.Frame=New Recti( 0,0,w,Height )
-				rect.Left+=w
-			End
-		Endif
-		
-		_view.Container.Frame=rect
-	End
-
-End
-
-Class DockingView Extends View
-
-	Method New()
-		Layout="fill"
-	End
-	
-	Property ContentView:View()
-
-		Return _content
-			
-	Setter( contentView:View )
-	
-		If _content RemoveChild( _content.Container )
-		
-		_content=contentView
-		
-		If _content AddChild( _content.Container )
-	End
-	
-	Method AddView( view:View,location:String,size:Int=0,resizable:Bool=True )
-	
-		Local dock:=New DockView( view,location,size,resizable )
-
-		_docks.Add( dock )
-		
-		AddChild( dock )
-	End
-	
-	Method RemoveView( view:View )
-	
-		Local dock:=FindView( view )
-		If Not dock Return
-		
-		dock.View=Null
-		
-		RemoveChild( dock )
-		
-		_docks.Remove( dock )
-	End
-	
-	Method GetViewSize:Int( view:View )
-	
-		Return FindView( view ).Size
-	End
-	
-	Method SetViewSize( view:View,size:Int )
-	
-		FindView( view ).Size=size
-	End
-	
-	Method ClearViews()
-	
-		For Local dock:=Eachin _docks
-		
-			dock.View=Null
-			
-			RemoveChild( dock )
-		Next
-		
-		_docks.Clear()
-	End
-	
-	Method OnMeasure:Vec2i() Override
-
-		Local size:=New Vec2i
-		
-		If _content size=_content.Container.LayoutSize
-	
-		For Local dock:=Eachin _docks
-
-			'FIXME - silly place to do this...		
-			dock.Visible=dock.View.Visible
-			If Not dock.Visible Continue
-	
-			Select dock.Location
-			Case "top","bottom"
-				size.x=Max( size.x,dock.LayoutSize.x )
-				size.y+=dock.LayoutSize.y
-			Case "left","right"
-				size.x+=dock.LayoutSize.x
-				size.y=Max( size.y,dock.LayoutSize.y )
-			End
-
-		Next
-		
-		Return size
-
-	End
-	
-	Method OnLayout() Override
-	
-		Local rect:=Rect
-		
-		For Local dock:=Eachin _docks
-
-			If Not dock.Visible Continue
-		
-			Local size:=dock.LayoutSize
-		
-			Select dock.Location
-			Case "top"
-
-				Local top:=rect.Top+size.y
-				If top>rect.Bottom top=rect.Bottom
-				dock.Frame=New Recti( rect.Left,rect.Top,rect.Right,top )
-				rect.Top=top
-				
-'				dock.Frame=New Recti( rect.Left,rect.Top,rect.Right,rect.Top+size.y )
-'				rect.Top+=size.y
-			Case "bottom"
-			
-				Local bottom:=rect.Bottom-size.y
-				If bottom<rect.Top bottom=rect.Top
-				dock.Frame=New Recti( rect.Left,bottom,rect.Right,rect.Bottom )
-				rect.Bottom=bottom
-				
-'				dock.Frame=New Recti( rect.Left,rect.Bottom-size.y,rect.Right,rect.Bottom )
-'				rect.Bottom-=size.y
-			Case "left"
-			
-				Local left:=rect.Left+size.x
-				If left>rect.Right left=rect.Right
-				dock.Frame=New Recti( rect.Left,rect.Top,left,rect.Bottom )
-				rect.Left=left
-				
-'				dock.Frame=New Recti( rect.Left,rect.Top,rect.Left+size.x,rect.Bottom )
-'				rect.Left+=size.x
-			Case "right"
-				Local right:=rect.Right-size.x
-				If right<rect.Left right=rect.Left
-				dock.Frame=New Recti( right,rect.Top,rect.Right,rect.Bottom )
-				rect.Right=right
-				
-'				dock.Frame=New Recti( rect.Right-size.x,rect.Top,rect.Right,rect.Bottom )
-'				rect.Right-=size.x
-			End
-
-		Next
-		
-		If _content _content.Container.Frame=rect
-	End
-	
-	Private
-	
-	Field _content:View
-	Field _docks:=New Stack<DockView>
-	
-	Method FindView:DockView( view:View )
-	
-		For Local dock:=Eachin _docks
-			If dock.View=view Return dock
-		Next
-		
-		Return Null
-	End
-
-End

+ 0 - 137
src/ted2/mojox/filebrowser.monkey2

@@ -1,137 +0,0 @@
-
-Namespace mojox
-
-Class FileBrowser Extends TreeView
-
-	Field FileClicked:Void( path:String,event:MouseEvent )
-
-	Method New( rootPath:String="." )
-	
-		Style=Style.GetStyle( "mojo.FileBrowser" )
-	
-		_rootNode=New Node( Null )
-		
-		RootPath=rootPath
-
-		NodeClicked=OnNodeClicked
-		NodeToggled=OnNodeToggled
-		
-		RootNode=_rootNode
-		
-		Update()
-	End
-	
-	Property RootPath:String()
-	
-		Return _rootPath
-	
-	Setter( path:String )
-	
-		_rootPath=path
-		
-		_rootNode._path=path
-		_rootNode.Label=_rootPath
-	End
-	
-	Method Update()
-	
-		UpdateNode( _rootNode,_rootPath,True )
-	End
-
-	Private
-	
-	Class Node Extends TreeView.Node
-	
-		Method New( parent:Node )
-			Super.New( "",parent )
-		End
-		
-		Private
-		
-		Field _path:String
-	
-	End
-	
-	Field _rootNode:Node
-	Field _rootPath:String
-	
-	Method OnNodeClicked( tnode:TreeView.Node,event:MouseEvent )
-	
-		Local node:=Cast<Node>( tnode )
-		If Not node Return
-		
-		FileClicked( node._path,event )
-	End
-	
-	Method OnNodeToggled( tnode:TreeView.Node,event:MouseEvent )
-
-		Local node:=Cast<Node>( tnode )
-		If Not node Return
-	
-		If node.Expanded
-			UpdateNode( node,node._path,True )
-		Else
-			For Local child:=Eachin node.Children
-				child.RemoveAllChildren()
-			Next
-		Endif
-	
-		Update()
-	End
-	
-	Method UpdateNode( node:Node,path:String,recurse:Bool )
-	
-		Local dir:=filesystem.LoadDir( path )
-		
-		Local dirs:=New Stack<String>
-		Local files:=New Stack<String>
-		
-		For Local f:=Eachin dir
-			Local fpath:=path+"/"+f
-			Select GetFileType( fpath )
-			Case FileType.Directory
-				dirs.Push( f )
-			Default
-				files.Push( f )
-			End
-		Next
-		
-		dirs.Sort()
-		files.Sort()
-		
-		Local i:=0,children:=node.Children
-		
-		While i<dir.Length
-		
-			Local f:=""
-			If i<dirs.Length f=dirs[i] Else f=files[i-dirs.Length]
-			
-			Local child:Node
-			
-			If i<children.Length
-				child=Cast<Node>( children[i] )
-			Else
-				child=New Node( node )
-			Endif
-			
-			Local fpath:=path+"/"+f
-			
-			child.Label=f
-			child._path=fpath
-			
-			If i<dirs.Length
-				If child.Expanded Or recurse
-					UpdateNode( child,fpath,child.Expanded )
-				Endif
-			Else
-				child.RemoveAllChildren()
-			Endif
-			
-			i+=1
-		Wend
-		
-		node.RemoveChildren( i )
-		
-	End
-	
-End

+ 0 - 352
src/ted2/mojox/htmlview.monkey2

@@ -1,352 +0,0 @@
-
-Namespace mojox
-
-#Import "assets/htmlview_master_css.css@/mojox"
-#Import "assets/markdown_wrapper.html@/mojox"
-
-Class HtmlView Extends View
-
-	Field AnchorClicked:Void( url:String )
-
-	Method New()
-		Layout="fill"
-		
-		Style=Style.GetStyle( "mojo.HtmlView" )
-		
-		_context=New litehtml.context
-		_context.load_master_stylesheet( stringio.LoadString( "asset::mojox/htmlview_master_css.css" ) )
-
-		_container=New document_container( Self )
-		
-		_baseUrl=filesystem.CurrentDir()
-		
-		AnchorClicked=Go
-	End
-	
-	Property BaseUrl:String()
-		Return _baseUrl
-	Setter( baseUrl:String )
-		If Not baseUrl.EndsWith( "/" ) baseUrl+="/"
-		_baseUrl=baseUrl
-	End
-	
-	Property HtmlSource:String()
-		Return _source
-	Setter( htmlSource:String )
-		_source=htmlSource
-		_document=New litehtml.document( _source,_container,_context )
-		_layoutSize=New Vec2i( 0,0 )
-		_renderSize=New Vec2i( 0,0 )
-	End
-	
-	Property Container:View() Override
-		If Not _scroller
-			_scroller=New ScrollView( Self )
-		Endif
-		Return _scroller
-	End
-	
-	Method Go( url:String )
-	
-		If url.Contains( "#" )
-			Return
-		Endif
-		
-		Local root:=ExtractRootDir( url )
-		
-		If root="http://" Or root="https://"
-			requesters.OpenUrl( url )
-			Return
-		Endif
-		
-		If Not root
-			url=BaseUrl+url
-		Endif
-		
-		Local src:=stringio.LoadString( url )
-		
-		If ExtractExt( url )=".md"
-			src=hoedown.MarkdownToHtml( src )
-			Local wrapper:=stringio.LoadString( "asset::mojox/markdown_wrapper.html" )
-			src=wrapper.Replace( "${CONTENT}",src )
-		End
-		
-		BaseUrl=ExtractDir( url )
-		
-		HtmlSource=src
-	End
-	
-	Private
-	
-	Field _context:litehtml.context
-	Field _container:litehtml.document_container
-	Field _anchorClicked:String
-	
-	Field _baseUrl:String
-	Field _source:String
-	Field _document:litehtml.document
-	Field _layoutSize:Vec2i
-	Field _renderSize:Vec2i
-
-	Field _scroller:ScrollView
-	
-	Method OnMeasure2:Vec2i( size:Vec2i ) Override
-	
-		If Not _document Return New Vec2i( 0,0 )
-		
-		If size.x=_layoutSize.x Return _renderSize
-		
-		_layoutSize=size
-		
-		_document.render( size.x )
-		
-		_renderSize=New Vec2i( _document.width(),_document.height() )
-		
-		Return _renderSize
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		If Not _document Return
-		
-		Local clip:litehtml.position
-		clip.x=ClipRect.X
-		clip.y=ClipRect.Y
-		clip.width=ClipRect.Width
-		clip.height=ClipRect.Height
-
-		_document.draw( canvas,0,0,Varptr clip )
-	End
-
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		If Not _document Return
-	
-		Local x:=event.Location.X
-		Local y:=event.Location.Y
-		
-		_anchorClicked=""
-		
-		Select event.Type
-		Case EventType.MouseMove
-			_document.on_mouse_over( x,y,x,y )
-		Case EventType.MouseDown
-			_document.on_lbutton_down( x,y,x,y )
-		Case EventType.MouseUp
-			_document.on_lbutton_up( x,y,x,y )
-			_document.on_mouse_leave()
-		End
-		
-		If _anchorClicked AnchorClicked( _anchorClicked )
-	End
-	
-End
-
-Class document_container Extends litehtml.document_container
-
-	Field _view:HtmlView
-	
-	Global _fontScale:=1
-	Global _imageCache:=New StringMap<Image>
-	
-	Method New( view:HtmlView )
-	
-		_view=view
-	End
-	
-	Method set_color( canvas:Canvas,color:litehtml.web_color )
-	
-		canvas.Color=New Color( color.red/255.0,color.green/255.0,color.blue/255.0,1 )
-	End
-	
-	Method make_url:String( href:String )
-		Return _view._baseUrl+href
-	End
-
-	Method create_font:Object( faceName:String,size:Int,weight:Int,style:litehtml.font_style,decoration:UInt,fm:litehtml.font_metrics Ptr ) Override
-	
-		Local font:Font
-		
-		If faceName.Contains( "monospace" )
-			font=Font.Open( App.DefaultMonoFontName,size )
-		Else
-			font=Font.Open( App.DefaultFontName,size )
-		Endif
-		
-		Local height:=size
-
-		fm[0].height=height
-		fm[0].ascent=height
-		fm[0].descent=0
-		fm[0].x_height=height
-		fm[0].draw_spaces=True
-		
-		Return font
-	End
-
-	Method delete_font( font:Object ) Override
-	End
-	
-	Method text_width:Int( text:String,hfont:Object ) Override
-	
-		Local font:=Cast<Font>( hfont )
-		
-		Return font.TextWidth( text ) * _fontScale
-	End
-	
-	Method draw_text( hdc:Object,text:String,hfont:Object,color:litehtml.web_color Ptr,pos:litehtml.position Ptr ) Override
-	
-		Local canvas:=Cast<Canvas>( hdc )
-		
-		Local font:=Cast<Font>( hfont )
-		
-		canvas.Font=font
-
-		set_color( canvas,color[0] )
-		
-		canvas.DrawText( text,pos[0].x,pos[0].y )
-		
-		Return
-#rem		
-		canvas.PushMatrix()
-		canvas.Translate( pos[0].x,pos[0].y )
-		canvas.Scale( _fontScale,1 )
-		canvas.DrawText( text,0,0 )
-		canvas.PopMatrix()
-#end
-	End
-	
-	Method pt_to_px:Int( pt:Int ) Override
-		Return 0
-	End
-	
-	Method get_default_font_size:Int() Override
-		Return 16
-	End
-	
-	Method get_default_font_name:String() Override
-		Return "mojo"
-	End
-	
-	Method draw_list_marker( hdc:Object,marker:litehtml.list_marker Ptr ) Override
-	
-		If marker[0].marker_type=litehtml.list_style_type_none Return
-	
-		Local canvas:=Cast<Canvas>( hdc )
-	
-		set_color( canvas,marker[0].color )
-		
-		canvas.DrawRect( marker[0].pos.x,marker[0].pos.y,marker[0].pos.width,marker[0].pos.height )
-	End
-	
-	Method load_image( src:String,baseurl:String,redraw_on_ready:Bool ) Override
-		If _imageCache.Contains( src ) Return
-		Local image:=Image.Load( make_url( src ) )
-		_imageCache.Set( src,image )
-	End
-	
-	Method get_image_size( src:String,baseurl:String,sz:litehtml.size Ptr ) Override
-		Local image:=_imageCache.Get( src )
-		If Not image Return
-		sz[0].width=image.Width
-		sz[0].height=image.Height
-	End
-
-	Method draw_background( hdc:Object,img_src:String,img_baseurl:String,bg:litehtml.background_paint Ptr ) Override
-	
-		Local canvas:=Cast<Canvas>( hdc )
-		
-		Local image:=_imageCache.Get( img_src )
-		If image
-			canvas.Color=Color.White
-			canvas.DrawImage( image,bg[0].position_x,bg[0].position_y )
-			Return
-		Endif
-
-		set_color( canvas,bg[0].color )
-		
-'		canvas.DrawRect( bg[0].clip_box.x,bg[0].clip_box.y,bg[0].clip_box.width,bg[0].clip_box.height )
-		canvas.DrawRect( bg[0].border_box.x,bg[0].border_box.y,bg[0].border_box.width,bg[0].border_box.height )
-
-	End
-	
-	Method draw_border( canvas:Canvas,border:litehtml.border,x:Int,y:Int,w:Int,h:Int )
-
-		If border.style<>litehtml.border_style_solid Or border.width<1 Return
-		
-		set_color( canvas,border.color )
-		
-		canvas.DrawRect( x,y,w,h )
-	End
-	
-	Method draw_borders( hdc:Object,borders:litehtml.borders Ptr,pos:litehtml.position Ptr,root:Bool ) Override
-	
-		Local canvas:=Cast<Canvas>( hdc )
-		
-		Local x:=pos[0].x,y:=pos[0].y
-		
-		Local w:=pos[0].width,h:=pos[0].height
-		
-		draw_border( canvas,borders[0].left,x,y,1,h )
-		
-		draw_border( canvas,borders[0].top,x,y,w,1 )
-		
-		draw_border( canvas,borders[0].right,x+w-1,y,1,h )
-		
-		draw_border( canvas,borders[0].bottom,x,y+h-1,w,1 )
-	End
-
-	Method set_caption( caption:String ) Override
-	End
-	
-	Method set_base_url( baseurl:String ) Override
-	End
-	
-	Method on_anchor_click( url:String ) Override
-		_view._anchorClicked=url
-	End
-		
-	Method set_cursor( cursor:String ) Override
-	End
-	
-	Method import_css:String( url:String,baseurl:String ) Override
-		Local css:=stringio.LoadString( make_url( url ) )
-		Return css
-	End
-	
-	Method set_clip( pos:litehtml.position Ptr,radiuses:litehtml.border_radiuses Ptr ) Override
-	End
-	
-	Method del_clip() Override
-	End
-	
-	Method get_client_rect( client:litehtml.position Ptr ) Override
-'		If _view._rendering Print "get client rect"
-		client[0].x=0
-		client[0].y=0
-		client[0].width=_view._layoutSize.x
-		client[0].height=_view._layoutSize.y
-	End
-	
-	Method get_media_features( media:litehtml.media_features Ptr ) Override
-'		If _view._rendering Print "get media features"
-		media[0].type=litehtml.media_type_screen
-		media[0].width=_view._layoutSize.x
-		media[0].height=_view._layoutSize.y
-		media[0].device_width=1920
-		media[0].device_height=1080
-		media[0].color=8
-		media[0].color_index=0
-		media[0].monochrome=0
-		media[0].resolution=96
-	End
-	
-	Method get_language:String() Override
-		Return ""
-	End
-	
-	Method get_culture:String() Override
-		Return ""
-	End
-	
-End

+ 0 - 123
src/ted2/mojox/label.monkey2

@@ -1,123 +0,0 @@
-
-Namespace mojox
-
-Class Label Extends View
-
-	Field Clicked:Void()
-	
-	Field Dragged:Void( offset:Vec2i )
-
-	Method New()
-		Layout="float"
-		Style=Style.GetStyle( "mojo.Label" )
-		Gravity=New Vec2f( 0,.5 )
-		TextGravity=New Vec2f( 0,.5 )
-	End
-	
-	Method New( icon:Image )
-		Self.New()
-		
-		Icon=icon
-	End
-	
-	Method New( text:String,icon:Image=Null )
-		Self.New()
-		
-		Text=text
-		Icon=icon
-	End
-	
-	Property Text:String()
-	
-		Return _text
-		
-	Setter( text:String )
-	
-		_text=text
-	End
-	
-	Property Icon:Image()
-	
-		Return _icon
-	
-	Setter( icon:Image )
-	
-		_icon=icon
-	End
-	
-	Property CheckMark:Image()
-	
-		Return _check
-		
-	Setter( checkMark:Image )
-	
-		_check=checkMark
-	End
-	
-	Property TextGravity:Vec2f()
-	
-		Return _textGravity
-	
-	Setter( textGravity:Vec2f )
-	
-		_textGravity=textGravity
-	End
-	
-	Protected
-
-	Method OnMeasure:Vec2i() Override
-	
-		Local size:=New Vec2i
-		
-		If _text
-			size.x=RenderStyle.DefaultFont.TextWidth( _text )
-			size.y=RenderStyle.DefaultFont.Height
-		Endif
-
-		If _icon
-			size.x+=_icon.Width
-			size.y=Max( size.y,Int( _icon.Height ) )
-		Endif
-		
-		If _check
-			size.x+=_check.Width
-			size.y=Max( size.y,Int( _check.Height ) )
-		Endif
-		
-		Return size
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		Local x:=0,w:=0
-		
-		If _icon
-			Local y:=(MeasuredSize.y-_icon.Height)/2
-			canvas.DrawImage( _icon,0,y )
-			w+=_icon.Width
-			x=_icon.Width
-		Endif
-		
-		If _check
-			Local y:=(MeasuredSize.y-_check.Height)/2
-			canvas.DrawImage( _check,Width-_check.Width,y )
-			w+=_check.Width
-		Endif
-		
-		If _text
-			Local tx:=((Width-w)-(MeasuredSize.x-w)) * _textGravity.x
-			Local ty:=(Height-MeasuredSize.y) * _textGravity.y
-			canvas.DrawText( _text,tx+x,ty )
-		Endif
-
-	End
-	
-	Private
-	
-	Field _text:String
-	Field _textGravity:Vec2f
-	Field _icon:Image
-	Field _check:Image
-	
-End
-

+ 0 - 217
src/ted2/mojox/menu.monkey2

@@ -1,217 +0,0 @@
-
-Namespace mojox
-
-Class MenuButton Extends Button
-
-	Method New( text:String )
-		Super.New( text )
-		
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.MenuButton" )
-		TextGravity=New Vec2f( 0,.5 )
-
-'		MinSize=New Vec2i( 128,0 )
-	End
-	
-	Method New( action:Action )
-		Super.New( action )
-		
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.MenuButton" )
-		TextGravity=New Vec2f( 0,.5 )
-		
-		MinSize=New Vec2i( 160,0 )
-
-		_action=action
-	End
-	
-	Method OnMeasure:Vec2i() Override
-	
-		Local size:=Super.OnMeasure()
-		
-		If _action
-			Local hotKey:=_action.HotKeyLabel
-			If hotKey size.x+=Style.DefaultFont.TextWidth( "         "+hotKey )
-		Endif
-		
-		Return size
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		Super.OnRender( canvas )
-		
-		If _action
-			Local hotKey:=_action.HotKeyLabel
-			If hotKey
-				Local w:=Style.DefaultFont.TextWidth( hotKey )
-				Local tx:=(Width-w)
-				Local ty:=(Height-MeasuredSize.y) * TextGravity.y
-				canvas.DrawText( hotKey,tx,ty )
-			Endif
-		Endif
-	
-	End
-	
-	Field _action:Action
-
-End
-
-Class Menu Extends DockingView
-
-	Method New( label:String )
-		_label=label
-		Visible=False
-		Style=mojo.app.Style.GetStyle( "mojo.Menu" )
-		Layout="float"
-		Gravity=New Vec2f( 0,0 )
-	End
-	
-	Property Label:String()
-		Return _label
-	End
-	
-	Method Clear()
-		Super.ClearViews()
-	End
-	
-	Method AddAction( action:Action )
-		Local button:=New MenuButton( action )
-		button.Clicked+=Lambda()
-			_open[0].Close()
-		End
-		AddView( button,"top",0 )
-	End
-	
-	Method AddAction:Action( label:String )
-		Local action:=New Action( label )
-		AddAction( action )
-		Return action
-	End
-	
-	Method AddSeparator()
-		AddView( New Separator,"top",0 )
-	End
-	
-	Method AddSubMenu( menu:Menu )
-	
-		Local label:=New MenuButton( menu.Label )
-
-		label.Clicked=Lambda()
-			If menu.Visible
-				menu.Close()
-			Else
-				Local location:=New Vec2i( label.Bounds.Right,label.Bounds.Top )
-				menu.Open( location,label,Self )
-			Endif
-		End
-		
-		AddView( label,"top",0 )
-	End
-	
-	Method Open( location:Vec2i,view:View,owner:View )
-	
-		Assert( Not Visible )
-		
-		While Not _open.Empty And _open.Top<>owner
-			_open.Top.Close()
-		Wend
-		
-		If _open.Empty
-			_filter=App.MouseEventFilter
-			App.MouseEventFilter=MouseEventFilter
-		Endif
-		
-		Local window:=view.FindWindow()
-		location=view.TransformPointToView( location,window )
-		
-		window.AddChild( Self )
-		Offset=location
-		Visible=True
-		
-		_owner=owner
-		_open.Push( Self )
-	End
-	
-	Method Close()
-	
-		Assert( Visible )
-		
-		While Not _open.Empty
-		
-			Local menu:=_open.Pop()
-			menu.Parent.RemoveChild( menu )
-			menu.Visible=False
-			menu._owner=Null
-			
-			If menu=Self Exit
-		Wend
-		
-		If Not _open.Empty Return
-		
-		App.MouseEventFilter=_filter
-		_filter=Null
-	End
-	
-	Private
-	
-	Field _label:String
-	Field _owner:View
-	
-	Global _open:=New Stack<Menu>
-	Global _filter:Void( MouseEvent )
-	
-	Function MouseEventFilter( event:MouseEvent )
-	
-		If event.Eaten Return
-		
-		Local view:=event.View
-		
-		If view<>_open[0]._owner
-			
-			For Local menu:=Eachin _open
-				If view.IsChildOf( menu ) Return
-			Next
-		
-			If view.IsChildOf( _open[0]._owner ) Return
-
-		Endif
-		
-		If event.Type<>EventType.MouseDown
-			event.Eat()
-			Return
-		Endif
-		
-		event.Eat()
-		
-		_open[0].Close()
-	End
-		
-End
-
-Class MenuBar Extends DockingView
-
-	Method New()
-		Style=Style.GetStyle( "mojo.MenuBar" )
-		Layout="fill"
-	End
-	
-	Method AddMenu( menu:Menu )
-	
-		Local label:=New MenuButton( menu.Label )
-
-		label.Clicked=Lambda()
-		
-			If Not menu.Visible
-				Local location:=New Vec2i( label.Bounds.Left,label.Bounds.Bottom )
-				menu.Open( location,label,Self )
-			Else
-				menu.Close()
-				Return
-			Endif
-		End
-		
-		AddView( label,"left",0 )
-	End
-	
-End

+ 0 - 89
src/ted2/mojox/mojo2.monkey2

@@ -1,89 +0,0 @@
-
-
-Class Image
-
-	Property Vertices:Vertex2f[]()
-	
-End
-
-Class Light
-
-	Property Color:Color()
-	
-End
-
-Class Vertex2f
-	Field x:Float
-	Field y:Float
-	Field u:Float
-	Field v:Float
-	Field tx:Float
-	Field ty:Float
-	Field rgba:UInt
-End
-
-Enum BlendMode
-	Opaque
-	Alpha
-	Multiply
-	Additive
-End
-
-Class RenderOp
-	Field shader:Shader
-	Field material:Material
-	Field blendMode:BlendMode
-	Field geom:Int
-	Field first:Int
-	Field count:Int
-End
-
-Class DrawList
-
-	Property Color:Color()
-	
-	Property Matrix:AffineMat3f()
-	
-	Property BlendMode:BlendMode()
-	
-	Property DefaultMaterial:Material()
-	
-	Method AddLight( light:Light )
-	
-	Method AddShadowCaster( shadowCaster:ShadowCaster )
-	
-	Method DrawImage( image:Image )
-	
-	Method DrawCircle( tx:Float,ty:Float,radius:Float,material:Material=Null )
-	
-	Method DrawPolygons( vertices:Vertex2f,geom:Int,count:Int,material:Material=Null )
-
-	Private
-	
-	Field _color:Color
-	Field _matrix:Matrix
-	Field _lights:=New Stack<Light>
-	Field _casters:=New Stack<ShadowCaster>
-	Field _vertices:=New Stack<Vertex2f>
-	Field _renderOps:=New Stack<RenderOp>
-	
-	Field _currentOp:RenderOp
-	
-	Method AddRenderOp:Int( material:Material,geom:Int,count:Int )
-		If _currentOp.material=material And _currentOp.geom=geom And _currentOp.blendMode=_blendMode
-			_currentOp.count+=count
-			Local i:=_vertices.Length
-			_vertices.Resize( i+count )
-			Return i
-		End
-		_currentOp=New RenderOp
-		_currentOp.blendMode=_blendMode
-		_currentOp.material=material
-		_currentOp.geom=geom
-		_currentOp.first=_vertices.Length
-		_currentOp.count=count*geom
-		_vertices.Resize( _currentOp.first+_currentOp.count )
-		Return _currentOp.first
-	End
-	
-End

BIN
src/ted2/mojox/mojo_window.9.png


+ 0 - 29
src/ted2/mojox/mojox.monkey2

@@ -1,29 +0,0 @@
-
-Namespace mojox
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<litehtml>"
-#Import "<hoedown>"
-
-#Import "action"
-#Import "scrollbar"
-#Import "scrollview"
-#Import "label"
-#Import "button"
-#Import "dockingview"
-#Import "menu"
-#Import "tabview"
-#Import "htmlview"
-#Import "treeview"
-#Import "filebrowser"
-#Import "textview"
-#Import "console"
-#Import "dialog"
-#Import "toolbar"
-#Import "separator"
-#Import "textfield"
-#Import "theme"
-
-Using std..
-Using mojo..

BIN
src/ted2/mojox/monkey2-logo-63.png


+ 0 - 512
src/ted2/mojox/native/process.cpp

@@ -1,512 +0,0 @@
-
-#include "process.h"
-
-#ifndef EMSCRIPTEN
-
-#include <thread>
-#include <atomic>
-#include <mutex>
-#include <condition_variable>
-
-#include <SDL.h>
-
-bbInt g_mojox_AppInstance_AddAsyncCallback(bbFunction<void()> l_func);
-
-struct semaphore{
-
-	int count=0;
-	std::mutex mutex;
-	std::condition_variable cond_var;
-	
-	void wait(){
-		std::unique_lock<std::mutex> lock( mutex );
-		while( !count ) cond_var.wait( lock );
-		--count;
-	}
-	
-	void signal(){
-		std::unique_lock<std::mutex> lock( mutex );
-		++count;
-		cond_var.notify_one();
-	}
-};
-
-#if _WIN32
-
-#include <windows.h>
-#include <tlhelp32.h>
-
-#else
-
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#endif
-
-namespace{
-
-	const int INVOKE=0x40000000;
-	const int REMOVE=0x80000000;
-
-	void postEvent( int code ){
-		SDL_UserEvent event;
-		event.type=SDL_USEREVENT;
-		event.code=code;
-		event.data1=0;
-		event.data2=0;
-		if( SDL_PeepEvents( (SDL_Event*)&event,1,SDL_ADDEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT )!=1 ){
-			printf(" SDL_PeepEvents error!\n" );fflush( stdout );
-		}
-	}
-	
-#if _WIN32
-
-	void terminateChildren( DWORD procid,HANDLE snapshot,int exitCode ){
-	
-		PROCESSENTRY32 procinfo;
-			
-		procinfo.dwSize=sizeof( procinfo );
-		
-		int gotinfo=Process32First( snapshot,&procinfo );
-			
-		while( gotinfo ){
-		
-			if( procinfo.th32ParentProcessID==procid ){
-			
-//				printf("process=%i parent=%i module=%x path=%s\n",procinfo.th32ProcessID,procinfo.th32ParentProcessID,procinfo.th32ModuleID,procinfo.szExeFile);
-
-				terminateChildren( procinfo.th32ProcessID,snapshot,exitCode );
-				 
-				HANDLE child=OpenProcess( PROCESS_ALL_ACCESS,0,procinfo.th32ProcessID );
-				
-				if( child ){
-					int res=TerminateProcess( child,exitCode );
-					CloseHandle( child );
-				}
-			}
-			
-			gotinfo=Process32Next( snapshot,&procinfo );
-		}	
-	}
-	
-	int TerminateProcessGroup( HANDLE prochandle,int exitCode ){
-
-		HANDLE snapshot;
-		
-		int procid=GetProcessId( prochandle );
-		
-		snapshot=CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS,0 );
-		
-		if( snapshot!=INVALID_HANDLE_VALUE ){
-		
-			terminateChildren( GetProcessId( prochandle ),snapshot,exitCode );
-
-			CloseHandle( snapshot );
-		}
-			
-		int res=TerminateProcess( prochandle,exitCode );
-		return res;
-	}
-	
-#endif	
-
-#ifndef _WIN32
-
-	char **makeargv( const char *cmd ){
-	    int n,c;
-	    char *p;
-	    static char *args,**argv;
-	
-	    if( args ) free( args );
-	    if( argv ) free( argv );
-	    args=(char*)malloc( strlen(cmd)+1 );
-	    strcpy( args,cmd );
-	
-	    n=0;
-	    p=args;
-	    while( (c=*p++) ){
-	        if( c==' ' ){
-	            continue;
-	        }else if( c=='\"' ){
-	            while( *p && *p!='\"' ) ++p;
-	        }else{
-	            while( *p && *p!=' ' ) ++p;
-	        }
-	        if( *p ) ++p;
-	        ++n;
-	    }
-	    argv=(char**)malloc( (n+1)*sizeof(char*) );
-	    n=0;
-	    p=args;
-	    while( (c=*p++) ){
-	        if( c==' ' ){
-	            continue;
-	        }else if( c=='\"' ){
-	            argv[n]=p;
-	            while( *p && *p!='\"' ) ++p;
-	        }else{
-	            argv[n]=p-1;
-	            while( *p && *p!=' ' ) ++p;
-	        }
-	        if( *p ) *p++=0;
-	        ++n;
-	    }
-	    argv[n]=0;
-	    return argv;
-	}
-	
-#endif
-
-}
-
-struct bbProcess::Rep{
-
-	std::atomic_int refs;
-	
-	semaphore stdoutSema;
-	char stdoutBuf[4096];
-	char *stdoutGet;
-	int stdoutAvail=0;
-	bool terminated=false;
-	int exit;
-
-#if _WIN32
-
-	HANDLE proc;
-	HANDLE in;
-	HANDLE out;
-	HANDLE err;
-	
-	Rep( HANDLE proc,HANDLE in,HANDLE out,HANDLE err ):proc( proc ),in( in ),out( out ),err( err ),exit( -1 ),refs( 1 ){
-	}
-	
-	void close(){
-		CloseHandle( in );
-		CloseHandle( out );
-		CloseHandle( err );
-	}
-
-#else
-
-	int proc;
-	int in;
-	int out;
-	int err;
-
-	Rep( int proc,int in,int out,int err ):proc( proc ),in( in ),out( out ),err( err ),exit( -1 ),refs( 1 ){
-	}
-	
-	void close(){
-		::close( in );
-		::close( out );
-		::close( err );
-	}
-
-#endif
-	
-	void retain(){
-		++refs;
-	}
-	
-	void release(){
-		if( --refs ) return;
-		
-		close();
-		
-		delete this;
-	}
-};
-
-bbProcess::bbProcess():_rep( nullptr ){
-}
-
-bbProcess::~bbProcess(){
-
-	if( _rep ) _rep->release();
-}
-
-bbBool bbProcess::start( bbString cmd ){
-
-	if( _rep ) return false;
-	
-#if _WIN32
-
-	HANDLE in[2],out[2],err[2];
-	SECURITY_ATTRIBUTES sa={sizeof(sa),0,1};
-	CreatePipe( &in[0],&in[1],&sa,0 );
-	CreatePipe( &out[0],&out[1],&sa,0 );
-	CreatePipe( &err[0],&err[1],&sa,0 );
-
-	STARTUPINFOA si={sizeof(si)};
-	si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
-	si.hStdInput=in[0];
-	si.hStdOutput=out[1];
-	si.hStdError=err[1];
-	si.wShowWindow=SW_HIDE;
-
-	PROCESS_INFORMATION pi={0};
-    
-	DWORD flags=CREATE_NEW_PROCESS_GROUP;
-    
-	int res=CreateProcessA( 0,(LPSTR)cmd.c_str(),0,0,TRUE,flags,0,0,&si,&pi );
-
-	CloseHandle( in[0] );
-	CloseHandle( out[1] );
-	CloseHandle( err[1] );
-
-	if( !res ){
-		CloseHandle( in[1] );
-		CloseHandle( out[0] );
-		CloseHandle( err[0] );
-		return false;
-	}
-
-	CloseHandle( pi.hThread );
-	
-	Rep *rep=new Rep( pi.hProcess,in[1],out[0],err[0] );
-    
-#else
-  
-	int in[2],out[2],err[2];
-
-	pipe( in );
-	pipe( out );
-	pipe( err );
-
-	char **argv=makeargv( bbCString( cmd ) );
-	
-	bool failed=false;
-
-	int proc=vfork();
-
-	if( !proc ){
-
-#if __linux
-		setsid();
-#else
-		setpgid(0,0);
-#endif
-
-		dup2( in[0],0 );
-		dup2( out[1],1 );
-		dup2( err[1],2 );
-
-		execvp( argv[0],argv );
-		
-		failed=true;
-
-		_exit( 127 );
-	}
-	
-	if( failed ) proc=-1;
-
-	close( in[0] );
-	close( out[1] );
-	close( err[1] );
-
-	if( proc==-1 ){
-		close( in[1] );
-		close( out[0] );
-		close( err[0] );
-		return false;
-	}
-  
-	Rep *rep=new Rep( proc,in[1],out[0],err[0] );
-	
-#endif
-
-	//Create finished thread    
-    rep->retain();
-
-    int callback=g_mojox_AppInstance_AddAsyncCallback( finished );
-    
-    std::thread( [=](){
-    
-		#if _WIN32
-		
-	    	WaitForSingleObject( rep->proc,INFINITE );
-	    	
-	    	GetExitCodeProcess( rep->proc,(DWORD*)&rep->exit );
-	    		
-	    	CloseHandle( rep->proc );
-	    	
-		#else
-		
-			int status;
-			waitpid( rep->proc,&status,0 );
-			
-			if( WIFEXITED( status ) ){
-				rep->exit=WEXITSTATUS( status );
-			}else{
-				rep->exit=-1;
-			}
-			
-		#endif
-    		
-	    	postEvent( callback|INVOKE|REMOVE );
-    		
-    		rep->release();
-
-	} ).detach();
-	
-	
-	//Create stdoutReady thread
-	rep->retain();
-	
-	int callback2=g_mojox_AppInstance_AddAsyncCallback( stdoutReady );
-	
-	std::thread( [=](){
-	
-		for(;;){
-		
-#if _WIN32		
-			DWORD n=0;
-			if( !ReadFile( rep->out,rep->stdoutBuf,4096,&n,0 ) ) break;
-			if( n<=0 ) break;
-#else
-			int n=read( rep->out,rep->stdoutBuf,4096 );
-			if( n<=0 ) break;
-#endif
-			rep->stdoutGet=rep->stdoutBuf;
-			
-			rep->stdoutAvail=n;
-			
-			postEvent( callback2|INVOKE );
-			
-			rep->stdoutSema.wait();
-			
-			if( rep->stdoutAvail ) break;
-		}
-		
-		rep->stdoutAvail=0;
-		
-		postEvent( callback2|INVOKE|REMOVE );
-		
-		rep->release();
-
-	} ).detach();
-	
-	_rep=rep;
-    
-    return true;
-}
-
-int bbProcess::exitCode(){
-
-	if( !_rep ) return -1;
-
-	return _rep->exit;
-}
-
-bbInt bbProcess::stdoutAvail(){
-
-	if( !_rep ) return 0;
-
-	return _rep->stdoutAvail;
-}
-
-bbString bbProcess::readStdout(){
-
-	if( !_rep || !_rep->stdoutAvail ) return "";
-
-	bbString str=bbString::fromCString( _rep->stdoutGet,_rep->stdoutAvail );
-	
-	_rep->stdoutAvail=0;
-	
-	_rep->stdoutSema.signal();
-	
-	return str;
-}
-
-bbInt bbProcess::readStdout( void *buf,int count ){
-
-	if( !_rep || count<=0 || !_rep->stdoutAvail ) return 0;
-
-	if( count>_rep->stdoutAvail ) count=_rep->stdoutAvail;
-	
-	memcpy( buf,_rep->stdoutGet,count );
-	
-	_rep->stdoutGet+=count;
-
-	_rep->stdoutAvail-=count;
-	
-	if( !_rep->stdoutAvail ) _rep->stdoutSema.signal();
-	
-	return count;
-}
-
-void bbProcess::writeStdin( bbString str ){
-
-	if( !_rep ) return;
-
-#if _WIN32	
-	WriteFile( _rep->in,str.c_str(),str.length(),0,0 );
-#else
-	write( _rep->in,str.c_str(),str.length() );
-#endif
-}
-
-void bbProcess::sendBreak(){
-
-	if( !_rep ) return;
-	
-#if _WIN32
-	GenerateConsoleCtrlEvent( CTRL_BREAK_EVENT,GetProcessId( _rep->proc ) );
-#else
-	killpg( _rep->proc,SIGTSTP );
-#endif
-}
-
-void bbProcess::terminate(){
-
-	if( !_rep ) return;
-
-#if _WIN32
-	TerminateProcessGroup( _rep->proc,-1 );
-#else
-	killpg( _rep->proc,SIGTERM );
-#endif
-}
-
-#else
-
-//***** Dummy emscripten version *****
-
-struct bbProcess::Rep{
-};
-
-void bbProcess::discard(){
-}
-
-bbBool bbProcess::start( bbString cmd ){
-	return false;
-}
-	
-bbInt bbProcess::exitCode(){
-	return -1;
-}
-	
-bbInt bbProcess::stdoutAvail(){
-	return 0;
-}
-	
-bbString bbProcess::readStdout(){
-	return "";
-}
-
-bbInt bbProcess::readStdout( void *buf,bbInt count ){
-	return 0;
-}
-
-void bbProcess::writeStdin( bbString str ){
-}
-
-void bbProcess::sendBreak(){
-}
-
-void bbProcess::terminate(){
-}
-
-#endif

+ 0 - 40
src/ted2/mojox/native/process.h

@@ -1,40 +0,0 @@
-
-#ifndef BB_STD_PROCESS_H
-#define BB_STD_PROCESS_H
-
-#include <bbmonkey.h>
-
-class bbProcess : public bbObject{
-public:
-
-	bbProcess();
-	~bbProcess();
-	
-	void discard();
-	
-	bbFunction<void()> finished;
-	bbFunction<void()> stdoutReady;
-	
-	bbBool start( bbString cmd );
-	
-	bbInt exitCode();
-	
-	bbInt stdoutAvail();
-	
-	bbString readStdout();
-	
-	bbInt readStdout( void *buf,bbInt count );
-	
-	void writeStdin( bbString str );
-	
-	void sendBreak();
-	
-	void terminate();
-	
-private:
-	struct Rep;
-	
-	Rep *_rep;
-};
-
-#endif

+ 0 - 213
src/ted2/mojox/native/requesters.cpp

@@ -1,213 +0,0 @@
-
-#include "requesters.h"
-
-#if _WIN32
-
-#include <windows.h>
-#include <shlobj.h>
-
-namespace{
-
-	HWND focHwnd;
-
-	void beginPanel(){
-		focHwnd=GetFocus();
-	}
-
-	void endPanel(){
-		SetFocus( focHwnd );
-	}
-
-	int panel( bbString title,bbString text,int flags ){
-		beginPanel();
-		int n=MessageBoxW( GetActiveWindow(),bbWString( text ),bbWString( title ),flags );
-		endPanel();
-		return n;
-	}
-	
-	WCHAR *tmpWString( bbString str ){
-		WCHAR *p=(WCHAR*)malloc( str.length()*2+2 );
-		memcpy( p,str.data(),str.length()*2 );
-		p[str.length()]=0;
-		return p;
-	}
-	
-	int CALLBACK BrowseForFolderCallbackW( HWND hwnd,UINT uMsg,LPARAM lp,LPARAM pData ){
-		wchar_t szPath[MAX_PATH];
-		switch( uMsg ){
-		case BFFM_INITIALIZED:
-			SendMessageW( hwnd,BFFM_SETSELECTIONW,TRUE,pData );
-			break;
-		case BFFM_SELCHANGED: 
-			if( SHGetPathFromIDListW( (LPITEMIDLIST)lp,szPath ) ){
-				SendMessageW( hwnd,BFFM_SETSTATUSTEXTW,0,(LPARAM)szPath );
-			}
-			break;
-		}
-		return 0;
-	}
-	
-	int CALLBACK BrowseForFolderCallbackA( HWND hwnd,UINT uMsg,LPARAM lp,LPARAM pData ){
-		char szPath[MAX_PATH];
-		switch( uMsg ){
-		case BFFM_INITIALIZED:
-			SendMessageA( hwnd,BFFM_SETSELECTIONA,TRUE,pData );
-			break;
-		case BFFM_SELCHANGED: 
-			if( SHGetPathFromIDListA( (LPITEMIDLIST)lp,szPath ) ){
-				SendMessageA( hwnd,BFFM_SETSTATUSTEXTA,0,(LPARAM)szPath );
-			}
-			break;
-		}
-		return 0;
-	}
-}
-	
-void bbRequesters::Notify( bbString title,bbString text,bbBool serious ){
-	int flags=(serious ? MB_ICONWARNING : MB_ICONINFORMATION)|MB_OK|MB_APPLMODAL|MB_TOPMOST;
-	panel( title,text,flags );
-}
-
-bbBool bbRequesters::Confirm( bbString title,bbString text,bbBool serious ){
-	int flags=(serious ? MB_ICONWARNING : MB_ICONINFORMATION)|MB_OKCANCEL|MB_APPLMODAL|MB_TOPMOST;
-	int n=panel( title,text,flags );
-	if( n==IDOK ) return 1;
-	return 0;
-}
-
-int bbRequesters::Proceed( bbString title,bbString text,bbBool serious ){
-	int flags=(serious ? MB_ICONWARNING : MB_ICONINFORMATION)|MB_YESNOCANCEL|MB_APPLMODAL|MB_TOPMOST;
-	int n=panel( title,text,flags );
-	if( n==IDYES ) return 1;
-	if( n==IDNO ) return 0;
-	return -1;
-}
-
-bbString bbRequesters::RequestFile( bbString title,bbString exts,bbBool save,bbString path ){
-
-	bbString file,dir;
-	path=path.replace( "/","\\" );
-		
-	int i=path.findLast( "\\" );
-	if( i!=-1 ){
-		dir=path.slice( 0,i );
-		file=path.slice( 1+1 );
-	}else{
-		file=path;
-	}
-
-	if( file.length()>MAX_PATH ) return "";
-
-	if( exts.length() ){
-		if( exts.find( ":" )==-1 ){
-			exts=bbString( "Files\0*.",8 )+exts;
-		}else{
-			exts=exts.replace( ":",bbString( "\0*.",3 ) );
-		}
-		exts=exts.replace( ";",bbString( "\0",1 ) );
-		exts=exts.replace( ",",";*." )+bbString( "\0",1 );
-	}
-
-	WCHAR buf[MAX_PATH+1];
-	memcpy( buf,file.data(),file.length()*2 );
-	buf[file.length()]=0;
-
-	OPENFILENAMEW of={sizeof(of)};
-
-	of.hwndOwner=GetActiveWindow();
-	of.lpstrTitle=tmpWString( title );
-	of.lpstrFilter=tmpWString( exts );
-	of.lpstrFile=buf;
-	of.lpstrInitialDir=dir.length() ? tmpWString( dir ) : 0;
-	of.nMaxFile=MAX_PATH;
-	of.Flags=OFN_HIDEREADONLY|OFN_NOCHANGEDIR;
-	
-	bbString str;
-	
-	beginPanel();
-	
-	if( save ){
-		of.lpstrDefExt=L"";
-		of.Flags|=OFN_OVERWRITEPROMPT;
-		if( GetSaveFileNameW( &of ) ){
-			str=bbString( buf );
-		}
-	}else{
-		of.Flags|=OFN_FILEMUSTEXIST;
-		if( GetOpenFileNameW( &of ) ){
-			str=bbString( buf );
-		}
-	}
-	
-	endPanel();
-	
-	free( (void*)of.lpstrTitle );
-	free( (void*)of.lpstrFilter );
-	free( (void*)of.lpstrInitialDir );
-	
-	str=str.replace( "\\","/" );
-	
-	return str;
-}
-
-bbString bbRequesters::RequestDir( bbString title,bbString dir ){
-
-	CoInitialize( 0 );
-	
-	dir=dir.replace( "/","\\" );
-
-	LPMALLOC shm;
-	BROWSEINFOW bi={0};
-	
-	WCHAR buf[MAX_PATH],*p;
-	GetFullPathNameW( bbWString( dir ),MAX_PATH,buf,&p );
-	
-	bi.hwndOwner=GetActiveWindow();
-	bi.lpszTitle=tmpWString( title );
-	bi.ulFlags=BIF_RETURNONLYFSDIRS|BIF_NEWDIALOGSTYLE;
-	bi.lpfn=BrowseForFolderCallbackW;
-	bi.lParam=(LPARAM)buf;
-	
-	beginPanel();
-
-	bbString str;
-	
-	if( ITEMIDLIST *idlist=SHBrowseForFolderW( &bi ) ){
-		SHGetPathFromIDListW( idlist,buf );
-		str=bbString( buf );
-		//SHFree( idlist );	//?!?
-	}
-	
-	endPanel();
-	
-	free( (void*)bi.lpszTitle );
-
-	str=str.replace( "\\","/" );
-	if( !str.endsWith( "/" ) ) str+="/";
-
-	return str;
-}
-
-#elif __linux
-
-#include <limits.h>
-
-bbString bbRequesters::RequestFile( bbString title,bbString exts,bbBool save,bbString path ){
-
-	bbString cmd=BB_T("zenity --title=\"")+title+BB_T("\" --file-selection");
-
-	FILE *f=popen( cmd.c_str(),"r" );
-	if( !f ) return "";
-	
-	char buf[PATH_MAX];
-	int n=fread( buf,1,PATH_MAX,f );
-	pclose( f );
-	
-	if( n<0 || n>PATH_MAX ) return "";
-	
-	while( n && buf[n-1]<=32 ) --n;
-	
-	return bbString::fromCString( buf,n );
-}
-
-#endif

+ 0 - 20
src/ted2/mojox/native/requesters.h

@@ -1,20 +0,0 @@
-
-#ifndef BB_REQUESTERS_H
-#define BB_REQUESTERS_H
-
-#include <bbmonkey.h>
-
-namespace bbRequesters{
-
-	void Notify( bbString title,bbString text,bbBool serious );
-
-	bbBool Confirm( bbString title,bbString text,bbBool serious );
-
-	bbInt Proceed( bbString title,bbString text,bbBool serious );
-
-	bbString RequestFile( bbString title,bbString filters,bbBool save,bbString path );
-
-	bbString RequestDir( bbString title,bbString dir );
-}
-
-#endif

+ 0 - 203
src/ted2/mojox/native/requesters.mm

@@ -1,203 +0,0 @@
-
-#include "requesters.h"
-
-#import <Cocoa/Cocoa.h>
-
-namespace{
-
-	typedef int (*AlertPanel)( 
-		NSString *title,
-		NSString *msg,
-		NSString *defaultButton,
-		NSString *alternateButton,
-		NSString *otherButton );
-	
-	NSWindow *keyWin;
-	
-	void beginPanel(){
-		keyWin=[NSApp keyWindow];
-		if( !keyWin ) [NSApp activateIgnoringOtherApps:YES];
-	}
-	
-	void endPanel(){
-		if( keyWin ) [keyWin makeKeyWindow];
-	}
-	
-	NSString *ConvString( bbString str ){
-		return [NSString stringWithCharacters:(const unichar*)str.data() length:str.length()];
-	}
-	
-	bbString ConvString( NSString *str ){
-		int n=[str length];
-		unichar *buf=new unichar[ n ];
-		[str getCharacters:buf range:NSMakeRange( 0,n )];
-		bbString t=bbString( buf,n );
-		delete[] buf;
-		return t;
-	}
-}
-
-void bbRequesters::Notify( bbString title,bbString text,bbBool serious ){
-
-	AlertPanel panel=(AlertPanel) ( serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel );
-	
-	beginPanel();
-	
-	panel( ConvString( title ),ConvString( text ),@"OK",0,0 );
-	
-	endPanel();
-}
-
-bbBool bbRequesters::Confirm( bbString title,bbString text,bbBool serious ){
-
-	AlertPanel panel=(AlertPanel) ( serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel );
-	
-	beginPanel();
-	
-	int n=panel( ConvString( title ),ConvString( text ),@"OK",@"Cancel",0 );
-
-	endPanel();
-	
-	switch( n ){
-	case NSAlertDefaultReturn:return 1;
-	}
-	return 0;
-}
-
-int bbRequesters::Proceed( bbString title,bbString text,bbBool serious ){
-
-	AlertPanel panel=(AlertPanel) ( serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel );
-	
-	beginPanel();
-	
-	int n=panel( ConvString( title ),ConvString( text ),@"Yes",@"No",@"Cancel" );
-	
-	endPanel();
-	
-	switch( n ){
-	case NSAlertDefaultReturn:return 1;
-	case NSAlertAlternateReturn:return 0;
-	}
-	return -1;
-}
-
-bbString bbRequesters::RequestFile( bbString title,bbString filter,bbBool save,bbString path ){
-
-	bbString file,dir;
-	int i=path.findLast( "\\" );
-	if( i!=-1 ){
-		dir=path.slice( 0,i );
-		file=path.slice( 1+1 );
-	}else{
-		file=path;
-	}
-	
-	NSMutableArray *nsfilter=0;
-	bool allowOthers=true;
-
-	if( filter.length() ){
-	
-		allowOthers=false;
-	
-		nsfilter=[NSMutableArray arrayWithCapacity:10];
-		
-		int i0=0;
-		while( i0<filter.length() ){
-		
-			int i1=filter.find( ":",i0 )+1;
-			if( !i1 ) break;
-			
-			int i2=filter.find( ";",i1 );
-			if( i2==-1 ) i2=filter.length();
-			
-			while( i1<i2 ){
-			
-				int i3=filter.find( ",",i1 );
-				if( i3==-1 ) i3=i2;
-				
-				bbString ext=filter.slice( i1,i3 );
-				if( ext==BB_T("*") ){
-					allowOthers=true;
-				}else{
-					[nsfilter addObject:ConvString( ext )];
-				}
-				i1=i3+1;
-			}
-			i0=i2+1;
-		}
-	}
-
-	NSString *nsdir=0;
-	NSString *nsfile=0;
-	NSString *nstitle=0;
-	NSMutableArray *nsexts=0;
-
-	if( dir.length() ) nsdir=ConvString( dir );
-	if( file.length() ) nsfile=ConvString( file );
-	if( title.length() ) nstitle=ConvString( title );
-
-	beginPanel();
-	
-	bbString str;
-
-	if( save ){
-		NSSavePanel *panel=[NSSavePanel savePanel];
-		
-		if( nstitle ) [panel setTitle:nstitle];
-		
-		if( nsfilter ){
-			[panel setAllowedFileTypes:nsfilter];
-			[panel setAllowsOtherFileTypes:allowOthers];
-		}
-		
-		if( [panel runModalForDirectory:nsdir file:nsfile]==NSFileHandlingPanelOKButton ){
-			str=ConvString( [panel filename] );
-		}
-
-	}else{
-		NSOpenPanel *panel=[NSOpenPanel openPanel];
-
-		if( nstitle ) [panel setTitle:nstitle];
-		
-		if( allowOthers ) nsfilter=0;
-		
-		if( [panel runModalForDirectory:nsdir file:nsfile types:nsfilter]==NSFileHandlingPanelOKButton ){
-			str=ConvString( [panel filename] );
-		}
-	}
-	endPanel();
-
-	return str;
-}
-
-bbString bbRequesters::RequestDir( bbString title,bbString dir ){
-
-	NSString *nsdir=0;
-	NSString *nstitle=0;
-	NSOpenPanel *panel;
-	
-	if( dir.length() ) nsdir=ConvString( dir );
-	if( title.length() ) nstitle=ConvString( title );
-
-	panel=[NSOpenPanel openPanel];
-	
-	[panel setCanChooseFiles:NO];
-	[panel setCanChooseDirectories:YES];
-	[panel setCanCreateDirectories:YES];
-	
-	if( nstitle ) [panel setTitle:nstitle];
-
-	beginPanel();
-	
-	bbString str;
-	
-	if( [panel runModalForDirectory:nsdir file:0 types:0]==NSFileHandlingPanelOKButton ){
-	
-		str=ConvString( [panel filename] );
-	}
-
-	endPanel();
-	
-	return str;
-}
-

+ 0 - 192
src/ted2/mojox/scrollbar.monkey2

@@ -1,192 +0,0 @@
-
-Namespace mojox
-
-Class ScrollBar Extends View
-
-	Field ValueChanged:Void( value:Int )
-
-	Method New( axis:Axis=std.geom.Axis.X )
-
-		_axis=axis
-
-		Layout="fill"
-		
-		Local taxis:=_axis=Axis.X ? "x" Else "y"
-		
-		Style=Style.GetStyle( "mojo.ScrollBar:"+taxis )
-
-		_knobStyle=Style.GetStyle( "mojo.ScrollKnob:"+taxis )
-	End
-	
-	Property Axis:Axis()
-	
-		Return _axis
-		
-	Setter( axis:Axis )
-	
-		_axis=axis
-	End
-	
-	Property PageSize:Int()
-	
-		Return _pageSize
-		
-	Setter( pageSize:Int )
-	
-		_pageSize=pageSize
-	End
-	
-	Property Value:Int()
-	
-		Return _value
-		
-	Setter( value:Int )
-	
-		_value=value
-		_value=Clamp( _value,_minimum,_maximum )
-	End
-	
-	Property Minimum:Int()
-	
-		Return _minimum
-		
-	Setter( minimum:Int )
-	
-		_minimum=minimum
-		_value=Max( _value,_minimum )
-	End
-	
-	Property Maximum:Int()
-	
-		Return _maximum
-		
-	Setter( maximum:Int )
-	
-		_maximum=maximum
-		_value=Min( _value,_maximum )
-	End
-	
-	Protected
-	
-	Field _axis:Axis
-	Field _value:Int
-	Field _minimum:Int
-	Field _maximum:Int
-	Field _pageSize:Int=1
-	
-	Field _knobStyle:Style
-	Field _knobRect:Recti
-	
-	Field _drag:Bool
-	Field _hover:Bool
-	
-	Field _offset:Int
-	
-	Method OnMeasure:Vec2i() Override
-	
-		Return _knobStyle.Bounds.Size
-	End
-	
-	Method OnLayout() Override
-	
-		Local range:=_maximum-_minimum+_pageSize
-		
-		Select _axis
-		Case Axis.X
-		
-			Local sz:=range ? Max( _pageSize*Width/range,16 ) Else Width
-			Local pos:=_maximum>_minimum ? (_value-_minimum)*(Width-sz)/(_maximum-_minimum) Else 0
-			
-			_knobRect=New Recti( pos,0,pos+sz,Height )
-		
-'			Local min:=(_value-_minimum)*Width/range
-'			Local max:=(_value-_minimum+_pageSize)*Width/range
-			
-'			_knobRect=New Recti( min,0,max,16 )
-			
-		Case Axis.Y
-		
-			Local sz:=range ? Max( _pageSize*Height/range,16 ) Else Height
-			Local pos:=_maximum>_minimum ? (_value-_minimum)*(Height-sz)/(_maximum-_minimum) Else 0
-			
-			_knobRect=New Recti( 0,pos,Width,pos+sz )
-			
-'			Local min:=(_value-_minimum)*Height/range
-'			Local max:=(_value-_minimum+_pageSize)*Height/range
-			
-'			_knobRect=New Recti( 0,min,16,max )
-		End
-		
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		If _maximum=_minimum Return
-		
-		Local style:=_knobStyle
-		
-		If _drag style=style.GetState( "active" ) Else If _hover style=style.GetState( "hover" )
-
-		style.Render( canvas,_knobRect )
-	End
-
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		Local p:=event.Location
-		
-		Local value:=_value
-		
-		Local range:=_maximum-_minimum+_pageSize
-	
-		Select event.Type
-		Case EventType.MouseDown
-			If _knobRect.Contains( p )
-				Select _axis
-				Case Axis.X
-					_offset=p.x*range/Rect.Width-_value
-				Case Axis.Y
-					_offset=p.y*range/Rect.Height-_value
-				End
-				_drag=True
-			Else If _axis=Axis.X
-				If p.x<_knobRect.Left 
-					_value-=_pageSize
-				Else If p.x>=_knobRect.Right
-					_value+=_pageSize
-				Endif
-			Else If _axis=Axis.Y
-				If p.y<_knobRect.Top
-					_value-=_pageSize
-				Else If p.y>=_knobRect.Bottom
-					_value+=_pageSize
-				Endif
-			Endif
-		Case EventType.MouseMove
-			If _drag
-				Local range:=_maximum-_minimum+_pageSize
-				Select _axis
-				Case Axis.X
-					_value=p.x*range/Rect.Width-_offset
-				Case Axis.Y
-					_value=p.y*range/Rect.Height-_offset
-				End
-			Else If _knobRect.Contains( p )
-				_hover=True
-			Else
-				_hover=False
-			Endif
-		Case EventType.MouseUp
-			_drag=False
-		Case EventType.MouseLeave
-			_hover=False
-		End
-		
-		_value=Clamp( _value,_minimum,_maximum )
-		
-		If _value<>value
-			ValueChanged( _value )
-		Endif
-
-	End
-
-End

+ 0 - 269
src/ted2/mojox/scrollview.monkey2

@@ -1,269 +0,0 @@
-
-Namespace mojox
-
-Class ClipView Extends View
-
-	Method New()
-	
-		Layout="fill"
-	End
-	
-	Property ContentView:View()
-	
-		Return _content
-		
-	Setter( contentView:View )
-	
-		If _content RemoveChild( _content )
-		
-		_content=contentView
-		
-		If _content AddChild( _content )
-	End
-	
-	Property ContentFrame:Recti()
-	
-		Return _contentFrame
-	
-	Setter( contentFrame:Recti )
-	
-		_contentFrame=contentFrame
-	End
-	
-	Private
-	
-	Field _content:View
-	Field _contentFrame:Recti
-	
-	Method OnMeasure:Vec2i() Override
-	
-		If _content Return _content.LayoutSize
-		
-		Return New Vec2i
-	End
-	
-	Method OnLayout() Override
-	
-		If _content _content.Frame=_contentFrame
-	End
-	
-End
-
-Class ScrollView Extends View
-
-	Method New()
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.ScrollView" )
-		
-		_clipper=New ClipView
-		AddChild( _clipper )
-
-		_scrollx=New ScrollBar( Axis.X )
-		_scrollx.ValueChanged=Lambda( value:Int )
-			_scroll.x=value
-		End
-		AddChild( _scrollx )
-		
-		_scrolly=New ScrollBar( Axis.Y )
-		_scrolly.ValueChanged=Lambda( value:Int )
-			_scroll.y=value
-		End
-		AddChild( _scrolly )
-	End
-
-	Method New( contentView:View )
-		Self.New()
-		
-		ContentView=contentView
-	End
-
-	Property ContentView:View()
-	
-		Return _content
-		
-	Setter( contentView:View )
-	
-		_content=contentView
-		
-		_clipper.ContentView=_content
-	End
-	
-	Property ContentMargin:Recti()
-	
-		Return _contentMargin
-	
-	Setter( contentMargin:Recti )
-	
-		_contentMargin=contentMargin
-	End
-	
-	Property ContentClipRect:Recti()
-	
-		Return New Recti( _scroll,_scroll+_clipper.Frame.Size )
-'		Return New Recti( -_clipper.ContentFrame.Origin,_clipper.Frame.Size )
-	End
-	
-	Property ScrollBarsVisible:Bool()
-	
-		Return _scrollBarsVisible
-	
-	Setter( scrollBarsVisible:Bool )
-	
-		_scrollBarsVisible=scrollBarsVisible
-	End
-	
-	Method ScrollTo( scroll:Vec2i )
-
-		If Not _clipper.Frame.Width Or Not _clipper.Frame.Height Return
-		
-		Local frame:=_clipper.Frame
-		If _content frame-=_content.Style.Bounds
-		
-		scroll.x=Min( scroll.x,_content.Width-frame.Width )
-		scroll.x=Max( scroll.x,0 )
-		
-		scroll.y=Min( scroll.y,_content.Height-frame.Height )
-		scroll.y=Max( scroll.y,0 )
-		
-		_scroll=scroll
-	End
-	
-	Method EnsureVisible( rect:Recti )
-
-		If Not _clipper.Frame.Width Or Not _clipper.Frame.Height Return
-		
-		Local frame:=_clipper.Frame
-		If _content frame-=_content.Style.Bounds
-		
-		If rect.Right>_scroll.x+frame.Width
-			_scroll.x=rect.Right-frame.Width
-		Endif
-		
-		If rect.Left<_scroll.x
-			_scroll.x=rect.Left
-		Endif
-		
-		If rect.Bottom>_scroll.y+frame.Height
-			_scroll.y=rect.Bottom-frame.Height
-		Endif
-		
-		If rect.Top<_scroll.y
-			_scroll.y=rect.Top
-		Endif
-			
-	End
-	
-	Protected
-	
-	Method OnMeasure:Vec2i() Override
-	
-		Return _clipper.LayoutSize+_contentMargin.Size
-	End
-	
-	Method OnLayout() Override
-	
-		If Not _content Return
-	
-		Local size:=Rect.Size
-		
-		Local csize:=size-_contentMargin.Size
-		Local vsize:=_content.Measure2( size-New Vec2i( _scrolly.LayoutSize.x,0 ) )
-		
-		If _scrollBarsVisible
-
-	'		Print "size="+size.ToString()
-	'		Print "csize="+csize.ToString()
-	'		Print "vsize="+vsize.ToString()
-			
-			Local xbar:=_scrollx.LayoutSize.y
-			Local ybar:=_scrolly.LayoutSize.x
-			
-			If vsize.y<=csize.y
-				If vsize.x<=csize.x xbar=0
-			Else
-				If vsize.x<=csize.x-ybar xbar=0
-			Endif
-			
-			If vsize.y<=csize.y-xbar ybar=0
-			
-			csize.x-=ybar
-			csize.y-=xbar
-			
-			If xbar
-				_scrollx.Visible=True
-				_scrollx.Frame=New Recti( 0,size.y-xbar,size.x-ybar,size.y )
-				_scrollx.PageSize=csize.x
-				_scrollx.Maximum=vsize.x-csize.x
-				_scrollx.Value=_scroll.x
-			Else
-				_scrollx.Visible=False
-				_scrollx.Value=0
-				vsize.x=csize.x
-			Endif
-			
-			If ybar
-				_scrolly.Visible=True
-				_scrolly.Frame=New Recti( size.x-ybar,0,size.x,size.y-xbar )
-				_scrolly.PageSize=csize.y
-				_scrolly.Maximum=vsize.y-csize.y
-				_scrolly.Value=_scroll.y
-			Else
-				_scrolly.Visible=False
-				_scrolly.Value=0
-				vsize.y=csize.y
-			Endif
-
-		Else
-			_scrollx.Visible=False
-			_scrollx.PageSize=csize.x
-			_scrollx.Maximum=vsize.x-csize.x
-			_scrollx.Value=_scroll.x
-			
-			_scrolly.Visible=False
-			_scrolly.PageSize=csize.y
-			_scrolly.Maximum=vsize.y-csize.y
-			_scrolly.Value=_scroll.y
-
-		Endif
-		
-		_scroll.x=_scrollx.Value
-		_scroll.y=_scrolly.Value
-		
-		_clipper.ContentFrame=New Recti( -_scroll,-_scroll+vsize )
-		
-		_clipper.Frame=New Recti( 0,0,csize )-_contentMargin.Origin
-
-	End
-	
-	Method OnKeyEvent( event:KeyEvent ) Override
-	
-		If _content _content.SendKeyEvent( event )
-	End
-	
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		Select event.Type
-		Case EventType.MouseWheel
-			_scroll.y-=event.Wheel.Y*16
-		End
-		
-	End
-
-	Private
-	
-	Field _content:View
-	Field _contentMargin:Recti
-	
-	Field _scroll:Vec2i
-
-	Field _clipper:ClipView	
-	Field _scrollx:ScrollBar
-	Field _scrolly:ScrollBar
-	
-	Field _scrollBarsVisible:Bool=True
-	
-End
-
-	
-	
-	

+ 0 - 11
src/ted2/mojox/separator.monkey2

@@ -1,11 +0,0 @@
-
-Namespace mojox
-
-Class Separator Extends View
-
-	Method New()
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.Separator" )
-	End
-
-End

+ 0 - 180
src/ted2/mojox/tabview.monkey2

@@ -1,180 +0,0 @@
-
-Namespace mojox
-
-Class TabButton Extends Button
-
-	Method New( text:String,view:View )
-		Super.New( text )
-		Style=Style.GetStyle( "mojo.TabButton" )
-		TextGravity=New Vec2f( 0,.5 )
-		_view=view
-	End
-	
-	Property View:View()
-	
-		Return _view
-	End
-	
-	Private
-	
-	Field _view:View
-
-End
-
-Class TabView Extends View
-
-	Field CurrentChanged:Void()
-
-	Method New()
-		Style=Style.GetStyle( "mojo.TabView" )
-		Layout="fill"
-	End
-	
-	Property Count:Int()
-	
-		Return _tabs.Length
-	End
-	
-	Property CurrentIndex:Int()
-
-		If _current Return IndexOfView( _current.View )
-		Return -1
-		
-	Setter( currentIndex:Int )
-	
-		MakeCurrent( _tabs[currentIndex] )
-	End
-	
-	Property CurrentView:View()
-	
-		If _current Return _current.View
-		Return Null
-	
-	Setter( currentView:View )
-	
-		For Local tab:=Eachin _tabs
-			If tab.View<>currentView Continue
-			MakeCurrent( tab )
-			Return
-		Next
-	End
-	
-	Method ViewAtIndex:View( index:Int )
-		Return _tabs[index].View
-	End
-
-	Method IndexOfView:Int( view:View )
-		For Local i:=0 Until _tabs.Length
-			If _tabs[i].View=view Return i
-		Next
-		Return -1
-	End
-
-	Method AddTab:Int( text:String,view:View,makeCurrent:Bool=False )
-
-		Local index:=_tabs.Length
-
-		Local tab:=New TabButton( text,view )
-		tab.Clicked=Lambda()
-			MakeCurrent( tab )
-		End
-		_tabs.Add( tab )
-
-		AddChild( tab )
-
-		If makeCurrent MakeCurrent( tab )
-
-		Return index
-	End
-	
-	Method RemoveTab( view:View )
-	
-		RemoveTab( IndexOfView( view ) )
-	End
-	
-	Method RemoveTab( index:Int )
-	
-		If _current=_tabs[index]
-			_current.Selected=False
-			RemoveChild( _current.View.Container )
-			_current=Null
-		Endif
-		
-		RemoveChild( _tabs[index] )
-		
-		_tabs.Erase( index )
-	End
-	
-	Method SetTabLabel( view:View,label:String )
-	
-		SetTabLabel( IndexOfView( view ),label )
-	
-	End
-	
-	Method SetTabLabel( index:Int,label:String )
-	
-		_tabs[index].Text=label
-	End
-	
-	Private
-	
-	Field _tabs:=New Stack<TabButton>
-	
-	Field _current:TabButton
-	
-	Field _buttonsSize:Vec2i
-	
-	Method MakeCurrent( tab:TabButton )
-	
-		If tab=_current Return
-		
-		If _current 
-			_current.Selected=False
-			RemoveChild( _current.View.Container )
-		Endif
-
-		_current=tab
-
-		If _current
-			_current.Selected=True
-			AddChild( _current.View.Container )
-		Endif
-		
-		CurrentChanged()
-			
-	End
-	
-	Method OnMeasure:Vec2i() Override
-	
-		Local size:=New Vec2i
-		
-		For Local tab:=Eachin _tabs
-			size.x+=tab.LayoutSize.x
-			size.y=Max( size.y,tab.LayoutSize.y )
-		Next
-		
-		_buttonsSize=size
-		
-		If _current
-			size.x=Max( size.x,_current.View.LayoutSize.x )
-			size.y+=_current.View.LayoutSize.y
-		Endif
-		
-		Return size
-	
-	End
-	
-	Method OnLayout() Override
-	
-		Local x:=0
-		
-		For Local tab:=Eachin _tabs
-			tab.Frame=New Recti( x,0,x+tab.LayoutSize.x,_buttonsSize.y )
-			x+=tab.LayoutSize.x
-		Next
-		
-		If _current _current.View.Container.Frame=New Recti( 0,_buttonsSize.y,Width,Height )
-	End
-	
-End
-

+ 0 - 41
src/ted2/mojox/test.monkey2

@@ -1,41 +0,0 @@
-
-Namespace ted
-
-#Import "mojox"
-
-Using std..
-Using mojo..
-Using mojo2..
-
-Class MainWindow Extends Window
-
-	Method New( title:String,rect:Recti,flags:WindowFlags )
-		Super.New( title,rect,flags )
-		
-		Style=New Style( Style )
-		Style.BackgroundColor=Color.Magenta
-		
-		App.RequestRender()
-		
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		canvas.DrawText( "Hello World",0,0 )
-		
-		App.RequestRender()
-		
-		GCCollect()
-	End
-
-End
-
-Function Main()
-
-	New AppInstance
-	
-	New MainWindow( "Ted2",New Recti( 16,16,640+16,640+16 ),WindowFlags.Resizable )
-	
-	App.Run()
-	
-End

+ 0 - 15
src/ted2/mojox/test2.monkey2

@@ -1,15 +0,0 @@
-
-Global t:=New Float[100]
-
-Function Main()
-
-	Local sum:Float
-	
-	For Local i:=0 Until 100
-	
-		sum+=t[i]
-		
-		DebugAssert( True,"This better work!" )
-	Next
-	
-End

+ 0 - 39
src/ted2/mojox/textfield.monkey2

@@ -1,39 +0,0 @@
-
-Namespace mojox
-
-Class TextField Extends TextView
-
-	Field EnterHit:Void()
-	
-	Field TabHit:Void()
-
-	Method New()
-		Style=Style.GetStyle( "mojo.TextField" )
-		Local scroller:=Cast<ScrollView>( Container )
-		scroller.ScrollBarsVisible=False
-		scroller.Layout="fill-x"
-	End
-	
-	Protected
-	
-	Method OnKeyEvent( event:KeyEvent ) Override
-	
-		Select event.Type
-		Case EventType.KeyDown
-			Select event.Key
-			Case Key.Enter
-'				SelectText( 0,0 )
-				EnterHit()
-				Return
-			Case Key.Tab
-'				SelectText( 0,0 )
-				TabHit()
-				Return
-			End
-		End
-		
-		Super.OnKeyEvent( event)
-	
-	End
-	
-End

+ 0 - 1089
src/ted2/mojox/textview.monkey2

@@ -1,1089 +0,0 @@
-
-Namespace mojox
-
-Alias TextHighlighter:Int( text:String,colors:Byte[],sol:Int,eol:Int,state:Int )
-
-Class TextDocument
-
-	Field LinesModified:Void( first:Int,removed:Int,inserted:Int )
-
-	Field TextChanged:Void()
-	
-	Method New()
-	
-		_lines.Push( New Line )
-	End
-
-	Property Text:String()
-	
-		Return _text
-		
-	Setter( text:String )
-	
-		text=text.Replace( "~r~n","~n" )
-		text=text.Replace( "~r","~n" )
-	
-		ReplaceText( 0,_text.Length,text )
-	End
-	
-	Property TextLength:Int()
-	
-		Return _text.Length
-	End
-	
-	Property LineCount:Int()
-	
-		Return _lines.Length
-	End
-	
-	Property Colors:Byte[]()
-	
-		Return _colors.Data
-	End
-	
-	Property TextHighlighter:TextHighlighter()
-	
-		Return _highlighter
-	
-	Setter( textHighlighter:TextHighlighter )
-	
-		_highlighter=textHighlighter
-	End
-	
-	Method LineState:Int( line:Int )
-		If line>=0 And line<_lines.Length Return _lines[line].state
-		Return -1
-	End
-	
-	Method StartOfLine:Int( line:Int )
-		If line<=0 Return 0
-		If line<_lines.Length Return _lines[line-1].eol+1
-		Return _text.Length
-	End
-	
-	Method EndOfLine:Int( line:Int )
-		If line<0 Return 0
-		If line<_lines.Length Return _lines[line].eol
-		Return _text.Length
-	End
-	
-	Method FindLine:Int( index:Int )
-	
-		If index<=0 Return 0
-		If index>=_text.Length Return _lines.Length-1
-		
-		Local min:=0,max:=_lines.Length-1
-		
-		Repeat
-			Local line:=(min+max)/2
-			If index>_lines[line].eol
-				min=line+1
-			Else If max-min<2
-				Return min
-			Else
-				max=line
-			Endif
-		Forever
-
-		Return 0		
-	End
-
-	Method GetLine:String( line:Int )
-		Return _text.Slice( StartOfLine( line ),EndOfLine( line ) )
-	End
-	
-	Method AppendText( text:String )
-	
-		ReplaceText( _text.Length,_text.Length,text )
-	End
-	
-	Method ReplaceText( anchor:Int,cursor:Int,text:String )
-	
-		Local min:=Min( anchor,cursor )
-		Local max:=Max( anchor,cursor )
-		
-		Local eols1:=0,eols2:=0
-		For Local i:=min Until max
-			If _text[i]=10 eols1+=1
-		Next
-		For Local i:=0 Until text.Length
-			If text[i]=10 eols2+=1
-		Next
-		
-		Local dlines:=eols2-eols1
-		Local dchars:=text.Length-(max-min)
-		
-		Local line0:=FindLine( min )
-		Local line:=line0
-		Local eol:=StartOfLine( line )-1
-		
-'		Print "eols1="+eols1+", eols2="+eols2+", dlines="+dlines+", dchars="+dchars+" text="+text.Length
-		
-		'Move data!
-		'
-		Local oldlen:=_text.Length
-		_text=_text.Slice( 0,min )+text+_text.Slice( max )
-		
-		_colors.Resize( _text.Length )
-		Local p:=_colors.Data.Data
-		libc.memmove( p + min + text.Length, p + max , oldlen-max )
-		libc.memset( p + min , 0 , text.Length )
-		
-		'Update lines
-		'
-		If dlines>=0
-		
-			_lines.Resize( _lines.Length+dlines )
-
-			Local i:=_lines.Length
-			While i>line+eols2+1
-				i-=1
-				_lines.Data[i].eol=_lines[i-dlines].eol+dchars
-				_lines.Data[i].state=_lines[i-dlines].state
-			Wend
-		
-		Endif
-
-		For Local i:=0 Until eols2+1
-			eol=_text.Find( "~n",eol+1 )
-			If eol=-1 eol=_text.Length
-			_lines.Data[line+i].eol=eol
-			_lines.Data[line+i].state=-1
-		Next
-		
-		If dlines<0
-
-			Local i:=line+eols2+1
-			While i<_lines.Length+dlines
-				_lines.Data[i].eol=_lines[i-dlines].eol+dchars
-				_lines.Data[i].state=_lines[i-dlines].state
-				i+=1
-			Wend
-
-			_lines.Resize( _lines.Length+dlines )
-		Endif
-
-		If _highlighter<>Null
-		
-			'update highlighting
-			'
-			Local state:=-1
-			If line state=_lines[line-1].state
-			
-			For Local i:=0 Until eols2+1
-				state=_highlighter( _text,_colors.Data,StartOfLine( line ),EndOfLine( line ),state )
-				_lines.Data[line].state=state
-				line+=1
-			Next
-			
-			While line<_lines.Length 'And state<>_lines[line].state
-				state=_highlighter( _text,_colors.Data,StartOfLine( line ),EndOfLine( line ),state )
-				_lines.Data[line].state=state
-				line+=1
-			End
-		Endif
-		
-'		Print "lines="+_lines.Length+", chars="+_text.Length
-
-		LinesModified( line0,eols1+1,eols2+1 )
-		
-		TextChanged()
-	End
-	
-	#rem
-		_lines.Resize( _lines.Length+dlines )
-		
-		
-		'eols1=eols deleted, eols2=eols inserted, dchars=delta chars
-		
-		
-		Local oldlen:=Text.Length
-		_text=_text.Slice( 0,min )+text+_text.Slice( max )
-		
-		_colors.Resize( _text.Length )
-		
-		Local p:=Varptr( _colors.Data[0] )
-		libc.memmove( p+min+text.Length,p+max,oldlen-max )
-		libc.memset( p+min,0,text.Length )
-		
-		UpdateEols()
-		
-		If eols1>eols2
-			LinesDeleted( FindLine( min ),eols1-eols2 )
-		Else If eols2>eols1
-			LinesInserted( FindLine( min ),eols2-eols1 )
-		Endif
-		
-		TextChanged()
-	End
-	#end
-	
-	Method HighlightLine( line:Int )
-#rem	
-		Return
-	
-		If _highlighter=Null Return
-		
-		If _lines[line].state<>-1 Return
-	
-		Local sol:=StartOfLine( line )
-		Local eol:=EndOfLine( line )
-		If eol>sol
-			Local colors:=_colors.Data
-			_highlighter( _text,colors,sol,eol )
-		Endif
-		
-		_lines.Data[line].state=0
-#end
-
-	End
-	
-	Private
-	
-	Struct Line
-		Field eol:Int
-		Field state:Int
-	End
-	
-	Field _text:String
-	
-	Field _lines:=New Stack<Line>
-	Field _colors:=New Stack<Byte>
-	Field _highlighter:TextHighlighter
-	
-	#rem
-	'not very efficient - scans entire document and recalcs all EOLs.
-	'
-	Method UpdateEols()
-	
-		_nlines=1
-		Local eol:=-1
-		
-		Repeat
-			eol=_text.Find( "~n",eol+1 )
-			If eol=-1 Exit
-			_nlines+=1
-		Forever
-		
-		_eols.Resize( _nlines )
-		
-		Local line:=0
-		Repeat
-			eol=_text.Find( "~n",eol+1 )
-			If eol=-1
-				_eols.Data[line].eol=_text.Length
-				Exit
-			Endif
-			
-			_eols.Data[line].eol=eol
-			line+=1
-		Forever
-		
-		'invalidate all line coloring
-		'
-		_colors.Resize( _text.Length )
-		
-		For Local i:=0 Until _nlines
-			Local sol:=StartOfLine( i )
-			If sol>=_colors.Length Exit
-			_colors[ sol ]=-1
-		Next
-		
-'		Print "lines="+_nlines
-'		For Local i:=0 Until _nlines
-'			Print "eol="+_eols[i]
-'		Next
-	End
-	
-	#end
-	
-End
-
-Class TextView Extends View
-
-	Field CursorMoved:Void()
-
-	Field FieldEntered:Void()
-	
-	Field FieldTabbed:Void()
-
-	Method New()
-	
-		Layout="fill"
-	
-		Style=Style.GetStyle( "mojo.TextView" )
-
-		_doc=New TextDocument
-		
-'		_textColors=New Color[]( New Color( 0,0,0,1 ),New Color( 0,0,.5,1 ),New Color( 0,.5,0,1 ),New Color( .5,0,0,1 ),New Color( .5,0,.5,1 ) )
-		_textColors=New Color[]( New Color( 1,1,1,1 ),New Color( 0,1,0,1 ),New Color( 1,1,0,1 ),New Color( 0,.5,1,1 ),New Color( 0,1,.5,1 ) )
-	End
-	
-	Method New( doc:TextDocument )
-		Self.New()
-	
-		_doc=doc
-	End
-	
-	Property Document:TextDocument()
-	
-		Return _doc
-		
-	Setter( doc:TextDocument )
-	
-		_doc=doc
-		
-		_cursor=Clamp( _cursor,0,_doc.TextLength )
-		_anchor=_cursor
-		
-		UpdateCursor()
-	End
-	
-	Property TextColors:Color[]()
-	
-		Return _textColors
-	
-	Setter( textColors:Color[] )
-	
-		_textColors=textColors
-	End
-	
-	Property SelectionColor:Color()
-	
-		Return _selColor
-		
-	Setter( selectionColor:Color )
-	
-		_selColor=selectionColor
-	End
-	
-	Property CursorColor:Color()
-	
-		Return _cursorColor
-	
-	Setter( cursorColor:Color )
-	
-		_cursorColor=cursorColor
-	End
-	
-	Property BlockCursor:Bool()
-	
-		Return _blockCursor
-	
-	Setter( blockCursor:Bool )
-	
-		_blockCursor=blockCursor
-	End
-
-	Property Text:String()
-	
-		Return _doc.Text
-		
-	Setter( text:String )
-	
-		_doc.Text=text
-	End
-	
-	Property ReadOnly:Bool()
-	
-		Return _readOnly
-	
-	Setter( readOnly:Bool )
-	
-		_readOnly=readOnly
-	End
-	
-	Property TabsStop:Int()
-	
-		Return _tabStop
-		
-	Setter( tabStop:Int )
-	
-		_tabStop=tabStop
-		_tabSpaces=" "
-		For Local i:=1 Until tabStop
-			_tabSpaces+=" "
-		Next
-	End
-	
-	Property Cursor:Int()
-	
-		Return _cursor
-	End
-	
-	Property Anchor:Int()
-	
-		Return _anchor
-	End
-	
-	Property CursorColumn:Int()
-	
-		Return Column( _cursor )
-	End
-	
-	Property CursorRow:Int()
-	
-		Return Row( _cursor )
-	End
-	
-	Property CursorRect:Recti()
-
-		Return _cursorRect
-	End
-	
-	Property LineHeight:Int()
-	
-		Return _charh
-	End
-	
-	Property CanUndo:Bool()
-	
-		Return Not _readOnly And Not _undos.Empty
-	End
-	
-	Property CanRedo:Bool()
-	
-		Return Not _readOnly And Not _redos.Empty
-	End
-	
-	Property CanCut:Bool()
-	
-		Return Not _readOnly And _anchor<>_cursor
-	End
-	
-	Property CanCopy:Bool()
-	
-		Return _anchor<>_cursor
-	End
-	
-	Property CanPaste:Bool()
-	
-		Return Not _readOnly And Not App.ClipboardTextEmpty
-	End
-	
-	Property Container:View() Override
-	
-		If Not _scroller
-		
-			_scroller=New ScrollView
-			_scroller.ContentView=Self
-			
-			CursorMoved+=Lambda()
-				_scroller.EnsureVisible( CursorRect-New Vec2i( _gutterw,0 ) )
-			End
-			
-		Endif
-		
-		Return _scroller
-	End
-	
-	Method Clear()
-		SelectAll()
-		ReplaceText( "" )
-	End
-	
-	Method SelectText( anchor:Int,cursor:Int )
-		_anchor=Clamp( anchor,0,_doc.TextLength )
-		_cursor=Clamp( cursor,0,_doc.TextLength )
-		UpdateCursor()
-	End
-	
-	Method ReplaceText( text:String )
-	
-		Local undo:=New UndoOp
-		undo.text=_doc.Text.Slice( Min( _anchor,_cursor ),Max( _anchor,_cursor ) )
-		undo.anchor=Min( _anchor,_cursor )
-		undo.cursor=undo.anchor+text.Length
-		_undos.Push( undo )
-		
-		ReplaceText( _anchor,_cursor,text )
-	End
-	
-	'non-undoable
-	Method ReplaceText( anchor:Int,cursor:Int,text:String )
-			
-		_redos.Clear()
-	
-		_doc.ReplaceText( anchor,cursor,text )
-		_cursor=Min( anchor,cursor )+text.Length
-		_anchor=_cursor
-		
-		UpdateCursor()
-	End
-	
-	Method Undo()
-		If _readOnly Return
-	
-		If _undos.Empty Return
-		
-		Local undo:=_undos.Pop()
-
-		Local text:=undo.text
-		Local anchor:=undo.anchor
-		Local cursor:=undo.cursor
-		
-		undo.text=_doc.Text.Slice( anchor,cursor )
-		undo.cursor=anchor+text.Length
-		
-		_redos.Push( undo )
-		
-		_doc.ReplaceText( anchor,cursor,text )
-		_cursor=anchor+text.Length
-		_anchor=_cursor
-		
-		UpdateCursor()
-	End
-	
-	Method Redo()
-		If _readOnly Return
-		
-		If _redos.Empty Return
-
-		Local undo:=_redos.Pop()
-		
-		Local text:=undo.text
-		Local anchor:=undo.anchor
-		Local cursor:=undo.cursor
-		
-		undo.text=_doc.Text.Slice( anchor,cursor )
-		undo.cursor=anchor+text.Length
-		
-		_undos.Push( undo )
-		
-		_doc.ReplaceText( anchor,cursor,text )
-		_cursor=anchor+text.Length
-		_anchor=_cursor
-		
-		UpdateCursor()
-	End
-	
-	Method SelectAll()
-		SelectText( 0,_doc.TextLength )
-	End
-	
-	Method Cut()
-		If _readOnly Return
-		Copy()
-		ReplaceText( "" )
-	End
-	
-	Method Copy()
-		Local min:=Min( _anchor,_cursor )
-		Local max:=Max( _anchor,_cursor )
-		Local text:=_doc.Text.Slice( min,max )
-		App.ClipboardText=text
-	End
-	
-	Method Paste()
-	
-		If _readOnly Return
-		
-		If App.ClipboardTextEmpty Return
-		
-		Local text:String=App.ClipboardText
-		text=text.Replace( "~r~n","~n" )
-		text=text.Replace( "~r","~n" )
-		
-		If text ReplaceText( text )
-	End
-	
-	Private
-	
-	Class UndoOp
-		Field text:String
-		Field anchor:Int
-		Field cursor:Int
-	End
-	
-	Field _doc:TextDocument
-	Field _tabStop:Int=4
-	Field _tabSpaces:String="    "
-	Field _cursorColor:Color=New Color( 0,.5,1,1 )
-	Field _selColor:Color=New Color( 1,1,1,.25 )
-	Field _blockCursor:Bool=True
-	
-	Field _textColors:Color[]
-	
-	Field _anchor:Int
-	Field _cursor:Int
-	
-	Field _tabw:Int
-	Field _charw:Int
-	Field _charh:Int
-	Field _gutterw:Int
-	Field _columnX:Int
-	Field _cursorRect:Recti
-	
-	Field _contentMargin:Recti
-	
-	Field _undos:=New Stack<UndoOp>
-	Field _redos:=New Stack<UndoOp>
-	
-	Field _dragging:Bool
-	
-	Field _scroller:ScrollView
-	
-	Field _readOnly:Bool
-	
-	Method Row:Int( index:Int )
-		Return _doc.FindLine( index )
-	End
-	
-	Method Column:Int( index:Int )
-		Return index-_doc.StartOfLine( _doc.FindLine( index ) )
-	End
-	
-	Method UpdateCursor()
-	
-		Local rect:=MakeCursorRect( _cursor )
-		If rect=_cursorRect Return
-		
-		_cursorRect=rect
-		_columnX=rect.X
-		
-		CursorMoved()
-	End
-	
-	Method MakeCursorRect:Recti( cursor:Int )
-	
-		ValidateStyle()
-		
-		Local line:=_doc.FindLine( cursor )
-		Local text:=_doc.GetLine( line )
-		
-		Local x:=0.0,i0:=0,e:=cursor-_doc.StartOfLine( line )
-		
-		While i0<e
-		
-			Local i1:=text.Find( "~t",i0 )
-			If i1=-1 i1=e
-			
-			If i1>i0
-				If i1>e i1=e
-				x+=Style.DefaultFont.TextWidth( text.Slice( i0,i1 ) )
-				If i1=e Exit
-			Endif
-			
-			x=Int( (x+_tabw)/_tabw ) * _tabw
-			i0=i1+1
-			
-		Wend
-		
-		Local w:=_charw
-		
-		If e<text.Length
-			If text[e]=9
-'				w=Int( (x+_tabw)/_tabw ) * _tabw-x
-			Else
-				w=Style.DefaultFont.TextWidth( text.Slice( e,e+1 ) )
-			Endif
-		Endif
-		
-		x+=_gutterw
-		Local y:=line*_charh
-		
-		Return New Recti( x,y,x+w,y+_charh )
-	End
-	
-	Method PointXToIndex:Int( px:Int,line:Int )
-	
-		ValidateStyle()
-
-		px=Max( px-_gutterw,0 )
-		
-		Local text:=_doc.GetLine( line )
-		Local sol:=_doc.StartOfLine( line )
-		
-		Local x:=0.0,i0:=0,e:=text.Length
-		
-		While i0<e
-		
-			Local i1:=text.Find( "~t",i0 )
-			If i1=-1 i1=e
-			
-			If i1>i0
-				For Local i:=i0 Until i1
-					x+=Style.DefaultFont.TextWidth( text.Slice( i,i+1 ) )
-					If px<x Return sol+i
-				Next
-				If i1=e Exit
-			Endif
-			
-			x=Int( (x+_tabw)/_tabw ) * _tabw
-			If px<x Return sol+i0
-			
-			i0=i1+1
-		Wend
-		
-		Return sol+e
-	
-	End
-	
-	Method PointToIndex:Int( p:Vec2i )
-	
-		If p.y<0 Return 0
-		
-		Local line:=p.y/_charh
-		If line>_doc.LineCount Return _doc.TextLength
-		
-		Return PointXToIndex( p.x,line )
-	End
-	
-	Method MoveLine( delta:Int )
-	
-		Local line:=Clamp( Row( _cursor )+delta,0,_doc.LineCount-1 )
-		
-		_cursor=PointXToIndex( _columnX,line )
-		
-		Local x:=_columnX
-		
-		UpdateCursor()
-		
-		_columnX=x
-	End
-	
-	Protected
-	
-	Property GutterWidth:Int()
-	
-		Return _gutterw
-	
-	Setter( gutterWidth:Int )
-	
-		_gutterw=gutterWidth
-	End
-	
-	Property ContentMargin:Recti()
-	
-		Return _contentMargin
-	
-	Setter( contentMargin:Recti )
-	
-		_contentMargin=contentMargin
-	End
-	
-	Method OnValidateStyle() Override
-	
-		_charw=Style.DefaultFont.TextWidth( "X" )
-		_charh=Style.DefaultFont.Height
-		_tabw=_charw*_tabStop
-		
-		UpdateCursor()
-	End
-	
-	Method OnMeasure:Vec2i() Override
-		Return New Vec2i( 320*_charw+_gutterw,_doc.LineCount*_charh )+_contentMargin.Size
-	End
-
-	Method OnRender( canvas:Canvas ) Override
-	
-		Local firstVisLine:=ClipRect.Top/_charh
-		Local lastVisLine:=Min( (ClipRect.Bottom-1)/_charh+1,_doc.LineCount )
-		
-		If _cursor<>_anchor
-		
-			Local min:=MakeCursorRect( Min( _anchor,_cursor ) )
-			Local max:=MakeCursorRect( Max( _anchor,_cursor ) )
-			
-			canvas.Color=_selColor
-			
-			If min.Y=max.Y
-				canvas.DrawRect( min.Left,min.Top,max.Left-min.Left,min.Height )
-			Else
-				canvas.DrawRect( min.Left,min.Top,(ClipRect.Right-min.Left),min.Height )
-				canvas.DrawRect( _gutterw,min.Bottom,ClipRect.Right-_gutterw,max.Top-min.Bottom )
-				canvas.DrawRect( _gutterw,max.Top,max.Left-_gutterw,max.Height )
-			Endif
-			
-		Else If Not _readOnly And App.KeyView=Self
-		
-			canvas.Color=_cursorColor
-			
-			If _blockCursor
-				canvas.DrawRect( _cursorRect.X,_cursorRect.Y,_cursorRect.Width,_cursorRect.Height )
-			Else
-				canvas.DrawRect( _cursorRect.X-0,_cursorRect.Y,2,_cursorRect.Height )
-				canvas.DrawRect( _cursorRect.X-2,_cursorRect.Y,6,2 )
-				canvas.DrawRect( _cursorRect.X-2,_cursorRect.Y+_cursorRect.Height-2,6,2 )
-			Endif
-			
-		Endif
-
-		_textColors[0]=Style.DefaultColor
-		
-		For Local line:=firstVisLine Until lastVisLine
-		
-			_doc.HighlightLine( line )
-		
-			Local sol:=_doc.StartOfLine( line )
-			Local eol:=_doc.EndOfLine( line )
-
-			Local text:=_doc.Text.Slice( sol,eol )
-			Local colors:=_doc.Colors
-			
-			Local x:=0,y:=line*_charh,i0:=0
-			
-			While i0<text.Length
-			
-				Local i1:=text.Find( "~t",i0 )
-				If i1=-1 i1=text.Length
-				
-				If i1>i0
-					
-					Local color:=colors[sol+i0]
-					Local start:=i0
-					
-					Repeat
-						
-						While i0<i1 And colors[sol+i0]=color
-							i0+=1
-						Wend
-						
-						If i0>start
-							If color<0 Or color>=_textColors.Length color=0
-							canvas.Color=_textColors[color]
-							
-							Local t:=text.Slice( start,i0 )
-							canvas.DrawText( t,x+_gutterw,y )
-							x+=Style.DefaultFont.TextWidth( t )
-						Endif
-						
-						If i0=i1 Exit
-						
-						color=colors[sol+i0]
-						start=i0
-						i0+=1
-						
-					Forever
-				
-					If i1=text.Length Exit
-					
-				Endif
-				
-				x=Int( (x+_tabw) / _tabw ) * _tabw
-				
-				i0=i1+1
-			
-			Wend
-			
-		Next
-		
-	End
-	
-	Method OnKeyEvent( event:KeyEvent ) Override
-	
-		If _readOnly Return
-	
-		Select event.Type
-		
-		Case EventType.KeyDown,EventType.KeyRepeat
-
-			Local control:=event.Modifiers & Modifier.Control
-		
-			Select event.Key
-			
-			Case Key.A
-			
-				If control SelectAll()
-				Return
-				
-			Case Key.X
-			
-				If control Cut()
-				Return
-				
-			Case Key.C
-			
-				If control Copy()
-				Return
-			
-			Case Key.V
-			
-				If control Paste()
-				Return
-				
-			Case Key.Z
-			
-				If control Undo()
-				Return
-			
-			Case Key.Backspace
-			
-				If _anchor=_cursor And _cursor>0 SelectText( _cursor-1,_cursor )
-				ReplaceText( "" )
-				
-			Case Key.KeyDelete
-			
-				If _anchor=_cursor And _cursor<_doc.Text.Length SelectText( _cursor,_cursor+1 )
-				ReplaceText( "" )
-				
-			Case Key.Tab
-			
-				Local min:=_doc.FindLine( Min( _cursor,_anchor ) )
-				Local max:=_doc.FindLine( Max( _cursor,_anchor ) )
-				
-				If min=max
-				
-					ReplaceText( "~t" )
-					
-				Else
-				
-					'block tab/untab
-					Local lines:=New StringStack
-					
-					For Local i:=min Until max
-						lines.Push( _doc.GetLine( i ) )
-					Next
-					
-					Local go:=True
-					If event.Modifiers & Modifier.Shift
-						For Local i:=0 Until lines.Length
-							If lines[i][0]=9 
-								lines[i]=lines[i].Slice( 1 )+"~n"
-								Continue
-							Endif
-							go=False
-							Exit
-						Next
-					Else
-						For Local i:=0 Until lines.Length
-							lines[i]="~t"+lines[i]+"~n"
-						Next
-					Endif
-					
-					If go
-						SelectText( _doc.StartOfLine( min ),_doc.StartOfLine( max ) )
-						ReplaceText( lines.Join( "" ) )
-						SelectText( _doc.StartOfLine( min ),_doc.StartOfLine( max ) )
-						Return						
-					Endif
-					
-				Endif
-				
-			Case Key.Enter
-			
-				ReplaceText( "~n" )
-				
-				'auto indent!
-				Local line:=CursorRow
-				If line>0
-				
-					Local ptext:=_doc.GetLine( line-1 )
-					
-					Local indent:=ptext
-					For Local i:=0 Until ptext.Length
-						If ptext[i]<=32 Continue
-						indent=ptext.Slice( 0,i )
-						Exit
-					Next
-					
-					If indent ReplaceText( indent )
-				
-				Endif
-				
-			Case Key.Left
-			
-				If _cursor 
-					_cursor-=1
-					UpdateCursor()
-				Endif
-				
-			Case Key.Right
-			
-				If _cursor<_doc.Text.Length
-					_cursor+=1
-					UpdateCursor()
-				Endif
-				
-			Case Key.Home
-			
-				If control
-					_cursor=0
-				Else				
-					_cursor=_doc.StartOfLine( Row( _cursor ) )
-				Endif
-				
-				UpdateCursor()
-				
-			Case Key.KeyEnd
-			
-				If control
-					_cursor=_doc.TextLength
-				Else
-					_cursor=_doc.EndOfLine( Row( _cursor ) )
-				Endif
-				
-				UpdateCursor()
-
-			Case Key.Up
-			
-				MoveLine( -1 )
-			
-			Case Key.Down
-			
-				MoveLine( 1 )
-				
-			Case Key.PageUp
-			
-				Local n:=ClipRect.Height/_charh-1		'shouldn't really use cliprect here...
-				
-				MoveLine( -n )
-				
-			Case Key.PageDown
-			
-				Local n:=ClipRect.Height/_charh-1
-				
-				MoveLine( n )
-				
-			Default
-			
-				Return
-			End
-			
-			If Not (event.Modifiers & Modifier.Shift) _anchor=_cursor
-			
-		Case EventType.KeyChar
-		
-			If _undos.Length
-				Local undo:=_undos.Top
-				If Not undo.text And _cursor=undo.cursor
-					ReplaceText( _anchor,_cursor,event.Text )
-					undo.cursor=_cursor
-					Return
-				Endif
-			Endif
-		
-			ReplaceText( event.Text )
-			
-		End
-	End
-	
-	Method OnMouseEvent( event:MouseEvent ) Override
-	
-		Select event.Type
-		Case EventType.MouseDown
-			App.KeyView=Self
-			_cursor=PointToIndex( event.Location )
-			_anchor=_cursor
-			_dragging=True
-			UpdateCursor()
-		Case EventType.MouseUp
-			_dragging=False
-		Case EventType.MouseMove
-			If _dragging
-				_cursor=PointToIndex( event.Location )
-				UpdateCursor()
-			Endif
-		Case EventType.MouseWheel
-			Super.OnMouseEvent( event )
-			Return
-		End
-		
-	End
-	
-	Method OnMakeKeyView() Override
-		Super.OnMakeKeyView()
-		UpdateCursor()
-	End
-	
-End

+ 0 - 258
src/ted2/mojox/theme.monkey2

@@ -1,258 +0,0 @@
-
-Namespace mojox
-
-#Import "assets/checkmark_icons.png@/mojox"
-#Import "assets/treenode_expanded.png@/mojox"
-#Import "assets/treenode_collapsed.png@/mojox"
-
-Const Theme:=New ThemeInstance
-
-Class ThemeInstance
-
-	Property Name:String()
-		Return _name
-	End
-
-	Property ClearColor:Color()
-		Return _clearColor
-	End
-	
-	Method Load()
-	
-		_name="dark"
-		_fontSize=16
-		_monoFontSize=16
-		
-		Local obj:=JsonObject.Load( "bin/ted2.config.json" )
-		If obj
-			If obj.Contains( "theme" )
-				_name=obj["theme"].ToString()
-			Endif
-			If obj.Contains( "fontSize" )
-				_fontSize=obj["fontSize"].ToNumber()
-			Endif
-			If obj.Contains( "monoFontSize" )
-				_monoFontSize=obj["monoFontSize"].ToNumber()
-			Endif
-		Endif
-
-		Select _name
-		Case "light"
-		
-			_textColor=New Color( 0,0,0 )
-			_disabledColor=New Color( .5,.5,.5 )
-			_clearColor=New Color( .8,.8,.8 )
-			_contentColor=New Color( .95,.95,.95 )
-			_panelColor=New Color( .9,.9,.9 )
-			_gutterColor=New Color( .8,.8,.8 )
-			_borderColor=New Color( .7,.7,.7 )
-			_lineColor=New Color( .95,.95,.95 )
-			_knobColor=New Color( .7,.7,.7 )
-			_hoverColor=New Color( .6,.6,.6 )
-			_activeColor=New Color( .5,.5,.5 )
-
-		Default
-				
-			_textColor=New Color( 1,1,1 )
-			_disabledColor=New Color( .5,.5,.5 )
-			_clearColor=New Color( .1,.1,.1 )
-			_contentColor=New Color( .2,.2,.2 )
-			_panelColor=New Color( .25,.25,.25 )
-			_gutterColor=New Color( .1,.1,.1 )
-			_borderColor=New Color( .1,.1,.1 )
-			_lineColor=New Color( .2,.2,.2 )
-			_knobColor=New Color( .4,.4,.4 )
-			_hoverColor=New Color( .6,.6,.6 )
-			_activeColor=New Color( .7,.7,.7 )'1,1,1 )
-			
-		End
-		
-		_defaultFont=Font.Open( App.DefaultFontName,_fontSize )
-		_defaultMonoFont=Font.Open( App.DefaultMonoFontName,_monoFontSize )
-
-		Local style:Style,state:Style
-		
-		style=Style.GetStyle( "" )
-		style.DefaultColor=_textColor
-		style.DefaultFont=_defaultFont
-
-		'Label		
-		style=New Style( "mojo.Label" )
-		style.DefaultColor=_textColor
-		style.Padding=New Recti( -8,-4,8,4 )
-		
-		'Button
-		style=New Style( "mojo.Button",Style.GetStyle( "mojo.Label" ) )
-		
-		Local icons:=LoadIcons( "asset::mojox/checkmark_icons.png",16 )
-		style.SetImage( "checkmark:unchecked",icons[0] )
-		style.SetImage( "checkmark:checked",icons[1] )
-		
-		state=style.AddState( "disabled" )
-		state.DefaultColor=_disabledColor
-		
-		state=style.AddState( "hover" )
-		state.BackgroundColor=_hoverColor
-		
-		state=style.AddState( "active" )
-		state.BackgroundColor=_activeColor
-		
-		'Menu
-		style=New Style( "mojo.Menu" )
-		style.Padding=New Recti( -2,-2,2,2 )
-		style.Border=New Recti( -1,-1,1,1 )
-		style.BackgroundColor=_panelColor
-		style.BorderColor=_borderColor
-		
-		'MenuButton
-		style=New Style( "mojo.MenuButton",Style.GetStyle( "mojo.Button" ) )
-		
-		'MenuBar
-		style=New Style( "mojo.MenuBar" )
-		style.Padding=New Recti( -2,-2,2,2 )
-		style.BackgroundColor=_panelColor
-		
-		'DockingView
-		style=New Style( "mojo.DockingView" )
-		
-		'DockView
-		style=New Style( "mojo.DockView" )
-		
-		'DragKnob
-		style=New Style( "mojo.DragKnob" )
-		style.Padding=New Recti( -3,-3,3,3 )
-		style.BackgroundColor=_knobColor
-		
-		state=style.AddState( "hover" )
-		state.BackgroundColor=_hoverColor
-		
-		state=style.AddState( "active" )
-		state.BackgroundColor=_activeColor
-		
-		'ScrollView
-		style=New Style( "mojo.ScrollView" )
-	
-		'ScrollBar
-		style=New Style( "mojo.ScrollBar" )
-		style.BackgroundColor=_gutterColor
-		
-		'ScrollKnob
-		style=New Style( "mojo.ScrollKnob" )
-		style.Padding=New Recti( -6,-6,6,6 )
-		style.Border=New Recti( -1,-1,1,1 )
-		style.BackgroundColor=_knobColor
-		
-		state=style.AddState( "hover" )
-		state.BackgroundColor=_hoverColor
-		
-		state=style.AddState( "active" )
-		state.BackgroundColor=_activeColor
-		
-		'TabView
-		style=New Style( "mojo.TabView" )
-		
-		'TabButton
-		style=New Style( "mojo.TabButton",Style.GetStyle( "mojo.Button" ) )
-		style.Border=New Recti( 0,-2,2,0 )
-		
-		state=style.AddState( "selected" )
-		state.BackgroundColor=_contentColor
-		
-		state=style.AddState( "hover" )
-		state.BackgroundColor=_hoverColor
-		
-		state=style.AddState( "active" )
-		state.BackgroundColor=_activeColor
-		
-		'HtmlView
-		style=New Style( "mojo.HtmlView" )
-
-		'TreeView
-		style=New Style( "mojo.TreeView" )
-		style.SetImage( "node:expanded",Image.Load( "asset::mojox/treenode_expanded.png" ) )
-		style.SetImage( "node:collapsed",Image.Load( "asset::mojox/treenode_collapsed.png" ) )
-		style.BackgroundColor=_contentColor
-		style.DefaultColor=_textColor
-		
-		'FileBrowser
-		style=New Style( "mojo.FileBrowser",Style.GetStyle( "mojo.TreeView" ) )
-		
-		'TextView
-		style=New Style( "mojo.TextView" )
-		style.DefaultFont=_defaultMonoFont
-		style.Padding=New Recti( -4,-4,4,4 )
-		style.BackgroundColor=_contentColor
-		style.DefaultColor=_textColor
-		
-		'Dialog
-		style=New Style( "mojo.Dialog" )
-		style.Border=New Recti( -1,-1,1,1 )
-		style.BackgroundColor=_panelColor
-		style.BorderColor=_borderColor
-		
-		'DialogTitle
-		style=New Style( "mojo.DialogTitle",Style.GetStyle( "mojo.Label" ) )
-		style.BackgroundColor=_knobColor
-		
-		style=New Style( "mojo.DialogContent" )
-		style.Padding=New Recti( -8,-8,8,4 )
-		
-		style=New Style( "mojo.DialogActions" )
-		style.Padding=New Recti( -8,-4,8,4 )
-		
-		'ToolBar
-		style=New Style( "mojo.ToolBar",Style.GetStyle( "mojo.MenuBar" ) )
-		
-		style=New Style( "mojo.ToolButton",Style.GetStyle( "mojo.Button" ) )
-		
-		'Separator
-		style=New Style( "mojo.Separator" )
-		style.Padding=New Recti( 0,0,1,1 )
-		style.Border=New Recti( -8,-8,7,7 )
-		style.BackgroundColor=_lineColor
-		
-		'TextField
-		style=New Style( "mojo.TextField",Style.GetStyle( "mojo.TextView" ) )
-		style.Padding=New Recti( -2,-2,2,2 )
-		style.Margin=New Recti( -2,-2,2,2 )
-		
-	End
-	
-	Method LoadIcons:Image[]( path:String,size:Int )
-	
-		Local pixmap:=Pixmap.Load( path )
-		If Not pixmap Return Null
-		
-		Local n:=pixmap.Width/size
-		
-		Local icons:=New Image[n]
-		
-		For Local i:=0 Until n
-			icons[i]=New Image( pixmap.Window( i*size,0,size,pixmap.Height ) )
-		Next
-		
-		Return icons
-	End
-
-	Private
-	
-	Field _name:String
-	Field _fontSize:Int
-	Field _monoFontSize:Int
-	
-	Field _textColor:Color
-	Field _defaultFont:Font
-	Field _defaultMonoFont:Font
-	
-	Field _disabledColor:Color
-	Field _clearColor:Color
-	Field _contentColor:Color
-	Field _panelColor:Color
-	Field _gutterColor:Color
-	Field _borderColor:Color
-	Field _lineColor:Color
-	Field _knobColor:Color
-	Field _hoverColor:Color
-	Field _activeColor:Color
-	
-End

+ 0 - 32
src/ted2/mojox/toolbar.monkey2

@@ -1,32 +0,0 @@
-
-Namespace mojox
-
-Class ToolButton Extends Button
-
-	Method New( action:Action )
-		Super.New( action )
-		Style=Style.GetStyle( "mojo.ToolButton" )
-	End
-	
-End
-
-Class ToolBar Extends DockingView
-
-	Method New()
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.ToolBar" )
-	End
-
-	Method AddAction( action:Action )
-		Local button:=New ToolButton( action )
-		AddView( button,"left",0 )
-	End
-	
-	
-	Method AddAction:Action( label:String="",icon:Image=Null )
-		Local action:=New Action( label,icon )
-		AddAction( action )
-		Return action
-	End
-
-End

+ 0 - 354
src/ted2/mojox/treeview.monkey2

@@ -1,354 +0,0 @@
-
-Namespace mojox
-
-Class TreeView Extends View
-
-	Field NodeClicked:Void( node:Node,event:MouseEvent )
-
-	Field NodeToggled:Void( node:Node,event:MouseEvent )
-
-	Class Node
-	
-		Method New( label:String,parent:Node=Null,index:Int=-1 )
-		
-			If parent parent.AddChild( Self,index )
-			
-			Label=label
-		End
-		
-		Property Label:String()
-		
-			Return _label
-			
-		Setter( label:String )
-		
-			_label=label
-			
-			Dirty()
-		End
-
-		Property Parent:Node()
-		
-			Return _parent
-		End
-		
-		Property NumChildren:Int()
-		
-			Return _children.Length
-		End
-		
-		Property Children:Node[]()
-		
-			Return _children.ToArray()
-		End
-	
-		Property Expanded:Bool()
-		
-			Return _expanded
-			
-		Setter( expanded:Bool )
-		
-			_expanded=expanded
-			
-			Dirty()
-		End
-		
-		Property Rect:Recti()
-		
-			Return _rect
-		End
-		
-		Property Bounds:Recti()
-		
-			Return _bounds
-		End
-		
-		Method AddChild( node:Node,index:Int=-1 )
-		
-			If node._parent Return
-			
-			If index=-1
-				index=_children.Length
-			Else
-				Assert( index>=0 And index<=_children.Length )
-			Endif
-			
-			node._parent=Self
-			
-			_children.Insert( index,node )
-			
-			node.Dirty()
-		End
-		
-		Method RemoveChildren( index1:Int,index2:Int )
-		
-			Assert( index1>=0 And index2>=index1 And index1<=_children.Length And index2<=_children.Length )
-		
-			For Local i:=index1 Until index2
-				_children[i]._parent=Null
-			Next
-			
-			_children.Erase( index1,index2 )
-			
-			Dirty()
-		End
-		
-		Method RemoveChild( node:Node )
-		
-			If node._parent<>Self Return
-			
-			_children.Remove( node )
-			
-			node._parent=Null
-			
-			Dirty()
-		End
-		
-		Method RemoveChild( index:Int )
-		
-			RemoveChild( GetChild( index ) )
-		End
-		
-		Method RemoveChildren( first:Int )
-		
-			RemoveChildren( first,_children.Length )
-		End
-
-		Method RemoveAllChildren()
-		
-			RemoveChildren( 0,_children.Length )
-		End
-
-		Method Remove()
-		
-			If _parent _parent.RemoveChild( Self )
-		End
-		
-		Method GetChild:Node( index:Int )
-		
-			If index>=0 And index<_children.Length Return _children[index]
-			
-			Return Null
-		End
-		
-		Private
-		
-		Field _parent:Node
-		Field _children:=New Stack<Node>
-		Field _label:String
-		Field _expanded:Bool
-		Field _bounds:Recti
-		Field _rect:Recti
-		Field _dirty:Bool
-		
-		Method Dirty()
-			_dirty=True
-			Local node:=_parent
-			While node
-				node._dirty=True
-				node=node._parent
-			Wend
-		End
-		
-	End
-	
-	Method New()
-		Layout="fill"
-		Style=Style.GetStyle( "mojo.TreeView" )
-		_rootNode=New Node( Null )
-	End
-	
-	Property RootNode:Node()
-	
-		Return _rootNode
-	
-	Setter( node:Node)
-	
-		_rootNode=node
-	End
-	
-	Property RootNodeVisible:Bool()
-	
-		Return _rootNodeVisible
-	
-	Setter( rootNodeVisible:Bool )
-		
-		_rootNodeVisible=rootNodeVisible
-	End
-	
-	Method FindNodeAtPoint:Node( point:Vec2i )
-	
-		Return FindNodeAtPoint( _rootNode,point )
-	End
-	
-	Property Container:View() Override
-	
-		If Not _scroller
-			_scroller=New ScrollView( Self )
-		Endif
-		Return _scroller
-	End
-	
-	Private
-	
-	Field _rootNode:Node
-	Field _rootNodeVisible:=True
-	Field _scroller:ScrollView
-	
-	Field _expandedIcon:Image
-	Field _collapsedIcon:Image
-	Field _nodeSize:Int
-		
-	Method FindNodeAtPoint:Node( node:Node,point:Vec2i )
-	
-		If node._rect.Contains( point ) Return node
-	
-		If node._expanded And node._bounds.Contains( point )
-		
-			For Local child:=Eachin node._children
-			
-				Local cnode:=FindNodeAtPoint( child,point )
-				If cnode Return cnode
-
-			Next
-
-		Endif
-		
-		Return Null
-	End
-	
-	Method MeasureNode( node:Node,origin:Vec2i,dirty:Bool )
-	
-		If Not node._dirty And Not dirty Return
-
-		node._dirty=False
-	
-		Local size:Vec2i,nodeSize:=0
-		
-		If _rootNodeVisible Or node<>_rootNode
-		
-			size=New Vec2i( Style.DefaultFont.TextWidth( node.Label )+_nodeSize,_nodeSize )
-			nodeSize=_nodeSize
-			
-		Endif
-		
-		Local rect:=New Recti( origin,origin+size )
-		
-		node._rect=rect
-		
-		If node._expanded
-		
-			origin.x+=nodeSize
-		
-			For Local child:=Eachin node._children
-			
-				origin.y=rect.Bottom
-			
-				MeasureNode( child,origin,True )
-				
-				rect|=child._bounds
-			Next
-		
-		Endif
-		
-		node._bounds=rect
-	End
-	
-	Method RenderNode( canvas:Canvas,node:Node )
-	
-		If Not node._bounds.Intersects( ClipRect ) return
-	
-		If _rootNodeVisible Or node<>_rootNode
-		
-			If node._children.Length
-			
-				Local icon:=_collapsedIcon
-				If node._expanded icon=_expandedIcon
-				
-				Local x:=(_nodeSize-icon.Width)/2
-				Local y:=(_nodeSize-icon.Height)/2
-				
-				canvas.Color=Color.White
-				canvas.DrawImage( icon,node._rect.X+x,node._rect.Y+y )
-				
-			Endif
-			
-			canvas.Color=Style.DefaultColor
-			canvas.DrawText( node._label,node._rect.X+_nodeSize,node._rect.Y )
-		
-		Endif
-			
-		If node._expanded
-
-			For Local child:=Eachin node._children
-			
-				RenderNode( canvas,child )
-				
-			Next
-		Endif
-		
-	End
-	
-	Method OnValidateStyle() Override
-	
-		_collapsedIcon=Style.GetImage( "node:collapsed" )
-		_expandedIcon=Style.GetImage( "node:expanded" )
-		
-		_nodeSize=Style.DefaultFont.Height
-		_nodeSize=Max( _nodeSize,Int( _expandedIcon.Height ) )
-		_nodeSize=Max( _nodeSize,Int( _collapsedIcon.Height ) )
-	End
-	
-	Method OnMeasure:Vec2i() Override
-	
-		If Not _rootNode Return New Vec2i( 0,0 )
-		
-		Local origin:Vec2i
-		
-		'If Not _rootNodeVisible origin=New Vec2i( -_nodeSize,-_nodeSize )
-	
-		MeasureNode( _rootNode,origin,false )
-		
-		Return _rootNode._bounds.Size
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		If Not _rootNode Return
-	
-		RenderNode( canvas,_rootNode )
-
-'		Print "TreeView ClipRect="+ClipRect.ToString()
-
-	End
-	
-	Method OnMouseEvent( event:MouseEvent) Override
-	
-		Select event.Type
-		Case EventType.MouseDown
-		
-			Local node:=FindNodeAtPoint( event.Location )
-
-			If node
-			
-				Local p:=event.Location-node._rect.Origin
-				
-				If p.x<_nodeSize And p.y<_nodeSize
-					node.Expanded=Not node._expanded
-					NodeToggled( node,event )
-				Else
-					NodeClicked( node,event )
-				Endif
-				
-			Endif
-			
-		Case EventType.MouseWheel
-		
-			Super.OnMouseEvent( event )
-			Return
-		End
-	
-	End
-	
-End
-

+ 0 - 310
src/ted2/mx2document.monkey2

@@ -1,310 +0,0 @@
-
-Namespace ted2
-
-Global Mx2Keywords:=New StringMap<String>
-
-Private
-
-Function InitKeywords()
-	Local kws:=""
-
-	kws+="Namespace;Using;Import;Extern;"
-	kws+="Public;Private;Protected;Friend;"
-	kws+="Void;Bool;Byte;UByte;Short;UShort;Int;UInt;Long;ULong;Float;Double;String;Object;Continue;Exit;"
-	kws+="New;Self;Super;Eachin;True;False;Null;Where;"
-	kws+="Alias;Const;Local;Global;Field;Method;Function;Property;Getter;Setter;Operator;Lambda;"
-	kws+="Enum;Class;Interface;Struct;Extends;Implements;Virtual;Override;Abstract;Final;Inline;"
-	kws+="Var;Varptr;Ptr;"
-	kws+="Not;Mod;And;Or;Shl;Shr;End;"
-	kws+="If;Then;Else;Elseif;Endif;"
-	kws+="While;Wend;"
-	kws+="Repeat;Until;Forever;"
-	kws+="For;To;Step;Next;"
-	kws+="Select;Case;Default;"
-	kws+="Try;Catch;Throw;Throwable;"
-	kws+="Return;Print;Static;Cast"
-	
-	For Local kw:=Eachin kws.Split( ";" )
-		Mx2Keywords[kw.ToLower()]=kw
-	Next
-End
-
-Public
-
-Class Mx2Error
-
-	Field path:String
-	Field line:Int
-	Field msg:String
-	Field removed:Bool
-	
-	Method New( path:String,line:Int,msg:String )
-		Self.path=path
-		Self.line=line
-		Self.msg=msg
-	End
-
-	Operator<=>:Int( err:Mx2Error )
-		If line<err.line Return -1
-		If line>err.line Return 1
-		Return 0
-	End
-	
-End
-
-Class Mx2TextView Extends TextView
-
-	Method New( mx2Doc:Mx2Document )
-		
-		_mx2Doc=mx2Doc
-		
-		Document=_mx2Doc.TextDocument
-		
-		GutterWidth=64
-		
-		Local _editorColors:=New Color[8]
-		
-		Select Theme.Name
-		Case "light"
-			_editorColors[COLOR_IDENT]=New Color( .1,.1,.1 )
-			_editorColors[COLOR_KEYWORD]=New Color( 0,0,1 )
-			_editorColors[COLOR_STRING]=New Color( 0,.5,0 )
-			_editorColors[COLOR_NUMBER]=New Color( 0,0,.5 )
-			_editorColors[COLOR_COMMENT]=New Color( 0,.5,.5 )
-			_editorColors[COLOR_PREPROC]=New Color( .8,.65,0 )
-			_editorColors[COLOR_OTHER]=New Color( .1,.1,.1 )
-		Default
-			_editorColors[COLOR_IDENT]=New Color( 1,1,1 )
-			_editorColors[COLOR_KEYWORD]=New Color( 1,1,0 )
-			_editorColors[COLOR_STRING]=New Color( 0,1,.5 )
-			_editorColors[COLOR_NUMBER]=New Color( 0,1,.5 )
-			_editorColors[COLOR_COMMENT]=New Color( 0,1,1 )
-			_editorColors[COLOR_PREPROC]=New Color( 1,.75,0 )
-			_editorColors[COLOR_OTHER]=New Color( 1,1,1 )
-		End
-		
-		TextColors=_editorColors
-		CursorColor=New Color( 0,.5,1 )
-		SelectionColor=New Color( .4,.4,.4 )
-	End
-	
-	Protected
-	
-	Method OnValidateStyle() Override
-	
-		Super.OnValidateStyle()
-		
-'		GutterWidth=RenderStyle.DefaultFont.TextWidth( "999999 " )
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		Local color:=canvas.Color
-	
-		Local clip:Recti
-		clip.min.x=-Frame.min.x
-		clip.min.y=-Frame.min.y
-		clip.max.x=clip.min.x+GutterWidth
-		clip.max.y=clip.min.y+ClipRect.Height
-		
-		If _mx2Doc._errors.Length
-		
-			canvas.Color=New Color( .5,0,0 )
-			
-			For Local err:=Eachin _mx2Doc._errors
-				canvas.DrawRect( 0,err.line*LineHeight,Width,LineHeight )
-			Next
-			
-		Endif
-		
-		If _mx2Doc._debugLine<>-1
-
-			Local line:=_mx2Doc._debugLine
-			If line<0 Or line>=Document.LineCount Return
-			
-			canvas.Color=New Color( .5,.5,0 )
-			canvas.DrawRect( 0,line*LineHeight,Width,LineHeight )
-			
-		Endif
-		
-		canvas.Color=color
-		
-		Super.OnRender( canvas )
-		
-		'OK, VERY ugly! Draw gutter stuff...
-		
-		Local viewport:=clip
-		viewport.min+=RenderStyle.Bounds.min
-		canvas.Viewport=viewport
-		canvas.Color=RenderStyle.BackgroundColor
-		canvas.DrawRect( 0,0,viewport.Width,viewport.Height )
-		
-		canvas.Viewport=Rect
-		
-		Local line0:=clip.Top/LineHeight
-		Local line1:=(clip.Bottom-1)/LineHeight+1
-		
-		canvas.Color=Color.Grey
-
-		For Local i:=line0 Until line1
-			canvas.DrawText( String( i+1 ),clip.X+GutterWidth-8,i*LineHeight,1,0 )
-		Next
-		
-	End
-	
-	Private
-	
-	Field _mx2Doc:Mx2Document
-	
-	Method Capitalize( typing:Bool )
-	
-		Local cursor:=Cursor
-		
-		Local state:=Document.LineState( Document.FindLine( cursor ) )
-		If state<>-1 Return
-		
-		Local text:=Text
-		Local start:=cursor
-		While start And IsIdent( text[start-1] )
-			start-=1
-		Wend
-		While start<text.Length And IsDigit( text[start] )
-			start+=1
-		Wend
-		
-		If start<text.Length 
-			Local color:=Document.Colors[start]
-			If color<>COLOR_KEYWORD And color<>COLOR_IDENT Return
-		Endif
-		
-		Local ident:=text.Slice( start,cursor )
-		If Not ident Return
-		
-		Local kw:=Mx2Keywords[ident.ToLower()]
-		If kw And kw<>ident Document.ReplaceText( Cursor-ident.Length,Cursor,kw )
-		
-	End
-	
-	Method OnKeyEvent( event:KeyEvent ) Override
-	
-		Select event.Type
-		Case EventType.KeyDown
-		
-			Select event.Key
-			Case Key.Tab,Key.Enter
-				Capitalize( True )
-			Case Key.Up,Key.Down
-				Capitalize( False )
-			End
-		
-		Case EventType.KeyChar
-		
-			If Not IsIdent( event.Text[0] )
-				Capitalize( True )
-			Endif
-		End
-
-		Super.OnKeyEvent( event )
-
-	End
-
-End
-
-Class Mx2Document Extends Ted2Document
-
-	Method New( path:String )
-		Super.New( path )
-	
-		InitKeywords()
-		
-		_textDoc=New TextDocument
-		
-		_textDoc.TextChanged=Lambda()
-			Dirty=True
-		End
-		
-		_textDoc.TextHighlighter=Mx2TextHighlighter
-		
-		_textDoc.LinesModified=Lambda( first:Int,removed:Int,inserted:Int )
-			Local put:=0
-			For Local get:=0 Until _errors.Length
-				Local err:=_errors[get]
-				If err.line>=first
-					If err.line<first+removed 
-						err.removed=True
-						Continue
-					Endif
-					err.line+=(inserted-removed)
-				Endif
-				_errors[put]=err
-				put+=1
-			Next
-			_errors.Resize( put )
-		End
-
-	
-		_textView=New Mx2TextView( Self )
-		
-	End
-	
-	Property TextDocument:TextDocument()
-	
-		Return _textDoc
-	End
-	
-	Property DebugLine:Int()
-	
-		Return _debugLine
-	
-	Setter( debugLine:Int )
-		If debugLine=_debugLine Return
-		
-		_debugLine=debugLine
-		If _debugLine=-1 Return
-
-		Local scroller:=Cast<ScrollView>( _textView.Container )
-		If Not scroller Return
-		
-		Local h:=_textView.LineHeight
-		Local y:=_debugLine*h
-		
-		scroller.EnsureVisible( New Recti( 0,y,1,y+scroller.ContentClipRect.Height/3 ) )
-	End
-	
-	Property Errors:Stack<Mx2Error>()
-	
-		Return _errors
-	End
-	
-	Private
-
-	Field _textDoc:TextDocument
-	Field _errors:=New Stack<Mx2Error>
-	Field _debugLine:Int=-1
-
-	Field _textView:TextView
-	
-	Method OnLoad:Bool() Override
-	
-		Local text:=stringio.LoadString( Path )
-		
-		_textDoc.Text=text
-		
-		Return True
-	End
-	
-	Method OnSave:Bool() Override
-	
-		Local text:=_textDoc.Text
-		
-		Return stringio.SaveString( text,Path )
-	
-	End
-	
-	Method OnCreateView:View() Override
-	
-		Return _textView
-	End
-	
-End
-

+ 0 - 147
src/ted2/mx2highlighter.monkey2

@@ -1,147 +0,0 @@
-
-Namespace ted2
-
-Using std.chartype
-
-Const COLOR_NONE:=0
-Const COLOR_IDENT:=1
-Const COLOR_KEYWORD:=2
-Const COLOR_STRING:=3
-Const COLOR_NUMBER:=4
-Const COLOR_COMMENT:=5
-Const COLOR_PREPROC:=6
-Const COLOR_OTHER:=7
-
-Function Mx2TextHighlighter:Int( text:String,colors:Byte[],sol:Int,eol:Int,state:Int )
-
-	Local i0:=sol
-	
-	Local icolor:=0
-	Local istart:=sol
-	Local preproc:=False
-	
-	If state>-1 icolor=COLOR_COMMENT
-	
-	While i0<eol
-	
-		Local start:=i0
-		Local chr:=text[i0]
-		i0+=1
-		If IsSpace( chr ) Continue
-		
-		If chr=35 And istart=sol
-			preproc=True
-			If state=-1 icolor=COLOR_PREPROC
-			Continue
-		Endif
-		
-		If preproc And (IsAlpha( chr ) Or chr=95)
-
-			While i0<eol And (IsAlpha( text[i0] ) Or IsDigit( text[i0] )  Or text[i0]=95)
-				i0+=1
-			Wend
-			
-			Local id:=text.Slice( start,i0 )
-			
-			Select id.ToLower()
-			Case "rem"
-				state+=1
-				icolor=COLOR_COMMENT
-			Case "end"
-				If state>-1 
-					state-=1
-					icolor=COLOR_COMMENT
-				Endif
-			End
-			
-			Exit
-		
-		Endif
-		
-		If state>-1 Or preproc Exit
-		
-		Local color:=icolor
-		
-		If chr=39
-		
-			i0=eol
-			color=COLOR_COMMENT
-			
-		Else If chr=34
-		
-			While i0<eol And text[i0]<>34
-				i0+=1
-			Wend
-			If i0<eol i0+=1
-			
-			color=COLOR_STRING
-			
-		Else If IsAlpha( chr ) Or chr=95
-
-			While i0<eol And (IsAlpha( text[i0] ) Or IsDigit( text[i0] )  Or text[i0]=95)
-				i0+=1
-			Wend
-			
-			Local id:=text.Slice( start,i0 )
-			
-			If preproc And istart=sol
-			
-				Select id.ToLower()
-				Case "rem"				
-					state+=1
-				Case "end"
-					state=Max( state-1,-1 )
-				End
-				
-				icolor=COLOR_COMMENT
-				
-				Exit
-			Else
-			
-				color=COLOR_IDENT
-				
-				If Mx2Keywords.Contains( id.ToLower() ) color=COLOR_KEYWORD
-			
-			Endif
-			
-		Else If IsDigit( chr )
-		
-			While i0<eol And IsDigit( text[i0] )
-				i0+=1
-			Wend
-			
-			color=COLOR_NUMBER
-			
-		Else If chr=36 And i0<eol And IsHexDigit( text[i0] )
-		
-			i0+=1
-			While i0<eol And IsHexDigit( text[i0] )
-				i0+=1
-			Wend
-			
-			color=COLOR_NUMBER
-			
-		Else
-			
-			color=COLOR_NONE
-			
-		Endif
-		
-		If color=icolor Continue
-		
-		For Local i:=istart Until start
-			colors[i]=icolor
-		Next
-		
-		icolor=color
-		istart=start
-	
-	Wend
-	
-	For Local i:=istart Until eol
-		colors[i]=icolor
-	Next
-	
-	Return state
-
-End

+ 155 - 28
src/ted2/projectview.monkey2

@@ -3,7 +3,13 @@ Namespace ted2
 
 Class ProjectView Extends ScrollView
 
-	Method New()
+	Field openProject:Action
+	
+	Field ProjectOpened:Void( dir:String )
+
+	Method New( docs:DocumentManager )
+	
+		_docs=docs
 	
 		_docker=New DockingView
 		
@@ -11,8 +17,22 @@ Class ProjectView Extends ScrollView
 		
 		_docker.ContentView=New TreeView
 		
+		openProject=New Action( "Open project" )
+		openProject.Triggered=OnOpenProject
 	End
-
+	
+	Property OpenProjects:String[]()
+	
+		Local projs:=New StringStack
+		For Local proj:=Eachin _projects.Keys
+			projs.Add( proj )
+		Next
+		
+'		projs.Add( _projects.Keys )	'Should work - FIXME
+		
+		Return projs.ToArray()
+	End
+	
 	Method OpenProject:Bool( dir:String )
 	
 		dir=StripSlashes( dir )
@@ -23,50 +43,121 @@ Class ProjectView Extends ScrollView
 	
 		Local browser:=New FileBrowser( dir )
 		
-		browser.FileClicked=Lambda( path:String,event:MouseEvent )
+		browser.FileClicked+=Lambda( path:String )
 		
-			Select event.Button
-			Case MouseButton.Left
+			If GetFileType( path )=FileType.File
 			
-				If GetFileType( path )=FileType.File
+				New Fiber( Lambda()
+					_docs.OpenDocument( path,True )
+				End )
 				
-					New Fiber( Lambda()
-					
-						MainWindow.OpenDocument( path,True )
-						MainWindow.SaveState()
-						
-					End )
-					
-				Endif
+			Endif
 			
-			Case MouseButton.Right
+		End
+		
+		browser.FileRightClicked+=Lambda( path:String )
+		
+			Local menu:=New Menu
+		
+			Select GetFileType( path )
+			Case FileType.Directory
 			
-				#rem Laters...!
-				Select GetFileType( path )
-				Case FileType.Directory
+				menu.AddAction( "New File" ).Triggered=Lambda()
 				
-					Local menu:=New Menu( path )
-					menu.AddAction( "New file" ).Triggered=Lambda()
-						Local file:=MainWindow.RequestFile( "New file","",True,path )
-						Print "File="+file
+					Local file:=RequestString( "New file name:" )
+					If Not file Return
+					
+					Local tpath:=path+"/"+file
+					
+					If GetFileType( tpath )<>FileType.None
+						Alert( "A file or directory already exists at '"+tpath+"'" )
+						Return
 					End
 					
-					menu.Open( event.Location,browser,Null )
+					If Not CreateFile( tpath )
+						Alert( "Failed to create file '"+file+"'" )
+					Endif
+					
+					browser.Update()
+					Return
+				End
+		
+				menu.AddAction( "New Folder" ).Triggered=Lambda()
 				
+					Local dir:=RequestString( "New folder name:" )
+					If Not dir Return
+					
+					Local tpath:=path+"/"+dir
+					
+					If GetFileType( tpath )<>FileType.None
+						Alert( "A file or directory already exists at '"+tpath+"'" )
+						Return
+					End
+					
+					If Not CreateDir( tpath )
+						Alert( "Failed to create folder '"+dir+"'" )
+						Return
+					Endif
+					
+					browser.Update()
+					Return
+				End
+				
+				menu.AddAction( "Delete" ).Triggered=Lambda()
+
+					If Not RequestOkay( "Really delete folder '"+path+"'?" ) Return
+					
+					If DeleteDir( path,True )
+						browser.Update()
+						Return
+					Endif
+					
+					Alert( "Failed to delete folder '"+path+"'" )
 				End
-				#end
 				
+			Case FileType.File
+			
+				menu.AddAction( "Open On Desktop" ).Triggered=Lambda()
+				
+					mojo.requesters.OpenUrl( path )
+				End
+				
+				menu.AddSeparator()
+			
+				menu.AddAction( "Delete" ).Triggered=Lambda()
+				
+					If Not RequestOkay( "Really delete file '"+path+"'?" ) return
+				
+					If DeleteFile( path )
+					
+						Local doc:=_docs.FindDocument( path )
+						
+						If doc doc.Close()
+					
+						browser.Update()
+						Return
+					Endif
+					
+					Alert( "Failed to delete file: '"+path+"'" )
+				End
+			
+			Default
+			
+				Return
 			End
+			
+			menu.Open()
 		End
 		
-		browser.RootNode.Label=StripDir( dir )+" ("+dir+")"
+		browser.RootNode.Text=StripDir( dir )+" ("+dir+")"
 		
 		_docker.AddView( browser,"top" )
 		
 		_projects[dir]=browser
 		
+		ProjectOpened( dir )
+
 		Return True
-		
 	End
 	
 	Method CloseProject( dir:String )
@@ -81,11 +172,47 @@ Class ProjectView Extends ScrollView
 		_projects.Remove( dir )
 	End
 	
+	Method SaveState( jobj:JsonObject )
+	
+		Local jarr:=New JsonArray
+		For Local it:=Eachin _projects
+			jarr.Add( New JsonString( it.Key ) )
+		Next
+		jobj["openProjects"]=jarr
+	End
+	
+	Method LoadState( jobj:JsonObject )
+	
+		If jobj.Contains( "openProjects" )
+			local arr:=jobj["openProjects"].ToArray()
+			For Local dir:=Eachin arr
+				OpenProject( dir.ToString() )
+			Next
+		Endif
+		
+	End
+	
 	Private
 	
+	Field _docs:DocumentManager
+	
 	Field _docker:=New DockingView
 	
 	Field _projects:=New StringMap<FileBrowser>
-End
-
 
+	Method OnOpenProject()
+	
+		Local future:=New Future<String>
+		
+		App.Idle+=Lambda()
+			Local dir:=RequestDir( "Select Project Directory...","" )
+			future.Set( dir )
+		End
+		
+		Local dir:=future.Get()
+		If Not dir Return
+		
+		If Not OpenProject( dir ) Return
+	End
+	
+End

+ 31 - 18
src/ted2/ted2.monkey2

@@ -1,17 +1,32 @@
 
-#Import "mojox/mojox"
+#If __HOSTOS__="windows"
+#Import "bin/wget.exe"
+#End
+
+#Import "<std>"
+#Import "<mojo>"
+#Import "<mojox>"
 
 #Import "mainwindow"
-#Import "projectview"
-#Import "debugview"
-#Import "helpview"
-#Import "finddialog"
+#Import "documentmanager"
+#import "fileactions"
+#import "editactions"
+#import "findactions"
+#import "finddialog"
+#import "buildactions"
+#import "helpactions"
+#import "debugview"
+#import "projectview"
+#import "helptree"
+#Import "modulemanager"
+#Import "gutterview"
 
 #Import "ted2document"
-#Import "txtdocument"
-#Import "mx2document"
-#Import "mx2highlighter"
-#Import "imgdocument"
+#Import "monkey2document"
+#Import "plaintextdocument"
+#Import "imagedocument"
+#import "audiodocument"
+#import "jsondocument"
 
 Namespace ted2
 
@@ -21,28 +36,26 @@ Using mojox..
 
 Function Main()
 
-'	Print "Hello World from Ted2"
-
 	ChangeDir( AppDir() )
 		
 	While GetFileType( "bin" )<>FileType.Directory Or GetFileType( "modules" )<>FileType.Directory
 
-'		Print "CurrentDir="+CurrentDir()
-			
 		If IsRootDir( CurrentDir() )
 			Print "Error initializing Ted2 - can't find working dir!"
-			libc.exit_( -1 )
+			libc.exit_( 1 )
 		Endif
 		
 		ChangeDir( ExtractDir( CurrentDir() ) )
-		
 	Wend
 	
-	New AppInstance
+	Local jobj:=JsonObject.Load( "bin/ted2.state.json" )
+	
+	Local rect:=New Recti( 16,16,960,800 )
+	If jobj And jobj.Contains( "windowRect" ) rect=ToRecti( jobj["windowRect"] )
 	
-	Theme.Load()
+	New AppInstance
 	
-	New MainWindowInstance( "Ted2",New Recti( 16,16,960,800 ),WindowFlags.Resizable|WindowFlags.Center )
+	New MainWindowInstance( "Ted2",rect,WindowFlags.Resizable,jobj )
 	
 	App.Run()
 End

+ 52 - 7
src/ted2/ted2document.monkey2

@@ -3,11 +3,17 @@ Namespace ted2
 
 Class Ted2Document
 
-	Field DirtyChanged:Void()
+	Field DirtyChanged:Void()	'also triggered by save/rename
+	
+	Field StateChanged:Void()
+
+	Field Closed:Void()
 
 	Method New( path:String )
 	
 		_path=path
+		
+		_modTime=GetFileTime( _path )
 	End
 	
 	Property Path:String()
@@ -15,6 +21,22 @@ Class Ted2Document
 		Return _path
 	End
 	
+	Property ModTime:Long()
+	
+		Return _modTime
+	End
+	
+	Property State:String()
+	
+		Return _state
+	
+	Setter( state:String )
+	
+		_state=state
+		
+		StateChanged()
+	End
+	
 	Property View:View()
 	
 		If Not _view _view=OnCreateView()
@@ -22,6 +44,11 @@ Class Ted2Document
 		Return _view
 	End
 	
+	Property TextView:TextView()
+	
+		Return OnGetTextView( View )
+	End
+	
 	Property Dirty:Bool()
 	
 		Return _dirty
@@ -37,7 +64,12 @@ Class Ted2Document
 	
 	Method Load:Bool()
 	
-		If Not OnLoad() Return False
+		If Not OnLoad() 
+			MainWindow.ReadError( _path )
+			Return False
+		Endif
+		
+		_modTime=GetFileTime( _path )
 
 		Dirty=False
 		
@@ -48,7 +80,12 @@ Class Ted2Document
 	
 		If Not _dirty Return True
 		
-		If Not OnSave() Return False
+		If Not OnSave()
+			MainWindow.WriteError( _path )
+			Return False
+		Endif
+		
+		_modTime=GetFileTime( _path )
 		
 		Dirty=False
 
@@ -65,7 +102,8 @@ Class Ted2Document
 	Method Close()
 	
 		OnClose()
-	
+		
+		Closed()
 	End
 	
 	Protected
@@ -80,18 +118,25 @@ Class Ted2Document
 		Return False
 	End
 	
-	Method OnClose() Virtual
-	End
-	
 	Method OnCreateView:View() Virtual
 	
 		Return Null
 	End
 	
+	Method OnGetTextView:TextView( view:View ) virtual
+	
+		Return Cast<TextView>( view )
+	End
+	
+	Method OnClose() Virtual
+	End
+	
 	Private
 
 	Field _dirty:Bool
 	Field _path:String
+	Field _modTime:Long
+	Field _state:String
 	Field _view:View
 	
 End

+ 0 - 104
src/ted2/txtdocument.monkey2

@@ -1,104 +0,0 @@
-
-Namespace ted2
-
-Class TxtTextView Extends TextView
-
-	Method New( doc:TxtDocument )
-
-		_doc=doc
-		
-		Document=_doc.TextDocument
-		
-		GutterWidth=64
-		CursorColor=New Color( 0,.5,1 )
-		SelectionColor=New Color( .4,.4,.4 )
-	End
-	
-	Protected
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		Super.OnRender( canvas )
-
-		'OK, VERY ugly! Draw gutter...
-		
-		Local clip:Recti
-		clip.min.x=-Frame.min.x
-		clip.min.y=-Frame.min.y
-		clip.max.x=clip.min.x+GutterWidth
-		clip.max.y=clip.min.y+ClipRect.Height
-		
-		Local viewport:=clip
-		viewport.min+=RenderStyle.Bounds.min
-		canvas.Viewport=viewport
-		canvas.Color=RenderStyle.BackgroundColor
-		canvas.DrawRect( 0,0,viewport.Width,viewport.Height )
-		
-		canvas.Viewport=Rect
-		
-		Local line0:=clip.Top/LineHeight
-		Local line1:=(clip.Bottom-1)/LineHeight+1
-		
-		canvas.Color=Color.Grey
-
-		For Local i:=line0 Until line1
-			canvas.DrawText( String( i+1 ),clip.X+GutterWidth-8,i*LineHeight,1,0 )
-		Next
-		
-	End
-	
-	Private
-	
-	Field _doc:TxtDocument
-	
-End
-
-Class TxtDocument Extends Ted2Document
-
-	Method New( path:String )
-		Super.New( path )
-
-		_textDoc=New TextDocument
-		
-		_textDoc.TextChanged=Lambda()
-			Dirty=True
-		End
-		
-		_textView=New TxtTextView( Self )
-	End
-	
-	Property TextDocument:TextDocument()
-	
-		Return _textDoc
-	End
-	
-	Protected
-	
-	Method OnLoad:Bool() Override
-	
-		Local text:=stringio.LoadString( Path )
-		
-		_textDoc.Text=text
-		
-		Return True
-	End
-	
-	Method OnSave:Bool() Override
-	
-		Local text:=_textDoc.Text
-		
-		Return stringio.SaveString( text,Path )
-	End
-	
-	Method OnCreateView:View() Override
-	
-		Return _textView
-	End
-	
-	Private
-	
-	Field _textDoc:TextDocument
-	Field _textView:TxtTextView
-	
-End
-