Browse Source

Squashed 'src/ted2go/' content from commit b8b03de1

git-subtree-dir: src/ted2go
git-subtree-split: b8b03de199b94245d08d8286361f87bdcf5bfdf7
Mark Sibly 8 years ago
commit
d2b04822e7
100 changed files with 5848 additions and 0 deletions
  1. 5 0
      .gitignore
  2. 158 0
      LiveTemplates.monkey2
  3. 1886 0
      MainWindow.monkey2
  4. 85 0
      Plugin.monkey2
  5. 219 0
      Prefs.monkey2
  6. 211 0
      ProcessReader.monkey2
  7. 38 0
      README.md
  8. 292 0
      Ted2.monkey2
  9. 50 0
      ThemeImages.monkey2
  10. 99 0
      Tuple.monkey2
  11. 668 0
      action/BuildActions.monkey2
  12. 138 0
      action/EditActions.monkey2
  13. 357 0
      action/FileActions.monkey2
  14. 479 0
      action/FindActions.monkey2
  15. 112 0
      action/HelpActions.monkey2
  16. 103 0
      action/ViewActions.monkey2
  17. 312 0
      assets/about.html
  18. 131 0
      assets/aboutTed2Go.html
  19. BIN
      assets/fonts/MesloLGSDZ-Bold.ttf
  20. BIN
      assets/fonts/Roboto-Medium.ttf
  21. BIN
      assets/fonts/RobotoMono-Medium.ttf
  22. BIN
      assets/fonts/verdana.ttf
  23. BIN
      assets/fonts/verdanab.ttf
  24. 9 0
      assets/gen/newClass.txt
  25. 30 0
      assets/liveTemplates.json
  26. 54 0
      assets/newfiles/Letterboxed_Mojo_App.monkey2
  27. 12 0
      assets/newfiles/Simple_Console_App.monkey2
  28. 33 0
      assets/newfiles/Simple_Mojo_App.monkey2
  29. 26 0
      assets/newfiles/Simple_Mojox_Gui_App.monkey2
  30. BIN
      assets/themes/cancel.png
  31. BIN
      assets/themes/codeicons/alias.png
  32. BIN
      assets/themes/codeicons/annotation.png
  33. BIN
      assets/themes/codeicons/class.png
  34. BIN
      assets/themes/codeicons/class_private.png
  35. BIN
      assets/themes/codeicons/class_protected.png
  36. BIN
      assets/themes/codeicons/code_template.png
  37. BIN
      assets/themes/codeicons/const.png
  38. BIN
      assets/themes/codeicons/constructor.png
  39. BIN
      assets/themes/codeicons/constructor_private.png
  40. BIN
      assets/themes/codeicons/constructor_protected.png
  41. BIN
      assets/themes/codeicons/enum.png
  42. BIN
      assets/themes/codeicons/enum_private.png
  43. BIN
      assets/themes/codeicons/enum_protected.png
  44. BIN
      assets/themes/codeicons/error.png
  45. BIN
      assets/themes/codeicons/field.png
  46. BIN
      assets/themes/codeicons/field_func.png
  47. BIN
      assets/themes/codeicons/field_private.png
  48. BIN
      assets/themes/codeicons/field_protected.png
  49. BIN
      assets/themes/codeicons/field_static.png
  50. BIN
      assets/themes/codeicons/field_static_private.png
  51. BIN
      assets/themes/codeicons/field_static_protected.png
  52. BIN
      assets/themes/codeicons/folder.png
  53. BIN
      assets/themes/codeicons/interface.png
  54. BIN
      assets/themes/codeicons/keyword.png
  55. BIN
      assets/themes/codeicons/local.png
  56. BIN
      assets/themes/codeicons/method.png
  57. BIN
      assets/themes/codeicons/method_private.png
  58. BIN
      assets/themes/codeicons/method_protected.png
  59. BIN
      assets/themes/codeicons/method_static.png
  60. BIN
      assets/themes/codeicons/method_static_private.png
  61. BIN
      assets/themes/codeicons/method_static_protected.png
  62. BIN
      assets/themes/codeicons/operator.png
  63. BIN
      assets/themes/codeicons/other.png
  64. BIN
      assets/themes/codeicons/package.png
  65. BIN
      assets/themes/codeicons/property.png
  66. BIN
      assets/themes/codeicons/property_private.png
  67. BIN
      assets/themes/codeicons/property_protected.png
  68. BIN
      assets/themes/codeicons/struct.png
  69. BIN
      assets/themes/codeicons/struct_private.png
  70. BIN
      assets/themes/codeicons/struct_protected.png
  71. BIN
      assets/themes/codeicons/warning.png
  72. BIN
      assets/themes/debug_icons.png
  73. 341 0
      assets/themes/default-tmp.json
  74. BIN
      assets/themes/docbar/back.png
  75. BIN
      assets/themes/docbar/forward.png
  76. BIN
      assets/themes/docbar/home.png
  77. BIN
      assets/themes/editorbar/back.png
  78. BIN
      assets/themes/editorbar/comment.png
  79. BIN
      assets/themes/editorbar/find_next.png
  80. BIN
      assets/themes/editorbar/find_previous.png
  81. BIN
      assets/themes/editorbar/find_selection.png
  82. BIN
      assets/themes/editorbar/forward.png
  83. BIN
      assets/themes/editorbar/last_edit.png
  84. BIN
      assets/themes/editorbar/next_bookmark.png
  85. BIN
      assets/themes/editorbar/previous_bookmark.png
  86. BIN
      assets/themes/editorbar/shift_left.png
  87. BIN
      assets/themes/editorbar/shift_right.png
  88. BIN
      assets/themes/editorbar/toggle_bookmark.png
  89. BIN
      assets/themes/editorbar/uncomment.png
  90. BIN
      assets/themes/hollow_assets/checkbox_icons.png
  91. BIN
      assets/themes/hollow_assets/dialog_skin.png
  92. BIN
      assets/themes/hollow_assets/progressbar_icons.png
  93. BIN
      assets/themes/hollow_assets/tabclose_icons.png
  94. BIN
      assets/themes/hollow_assets/treeview_icons.png
  95. BIN
      assets/themes/irc/blink.png
  96. BIN
      assets/themes/irc/important.png
  97. BIN
      assets/themes/irc/notice.png
  98. BIN
      assets/themes/outputbar/clean.png
  99. BIN
      assets/themes/outputbar/wrap.png
  100. BIN
      assets/themes/prime_assets/checkbox_icons.png

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+
+*.bak
+*.buildv*
+*.products/
+*.app

+ 158 - 0
LiveTemplates.monkey2

@@ -0,0 +1,158 @@
+
+Namespace ted2go
+
+
+#Import "assets/liveTemplates.json"
+
+Const LiveTemplates:=New LiveTemplatesClass
+
+Class LiveTemplatesClass
+	
+	Field DataChanged:Void( lang:String )
+	
+	Method Load()
+		
+		' merge two files
+		Load( DefaultPath )
+		Load( CustomPath )
+	End
+	
+	Method Save()
+		
+		If Not _dirty Return
+		
+		_dirty=False
+		NotifyDataChanged()
+		
+		Local json:=New JsonObject
+		
+		For Local map:=Eachin _items.All()
+			Local obj:=New JsonObject
+			json[map.Key]=obj
+			For Local i:=Eachin map.Value.All()
+				obj[i.Key]=New JsonString( i.Value )
+			Next
+		Next
+		
+		Local txt:=json.ToJson()
+		SaveString( txt,DefaultPath )
+		SaveString( txt,CustomPath )
+	End
+	
+	Operator []:StringMap<String>( fileType:String )
+	
+		Return _items[fileType]
+	End
+		
+	Operator []:String( fileType:String,name:String )
+	
+		Local map:=_items[fileType]
+		Return map ? map[name] Else Null
+	End
+	
+	Operator []=( fileType:String,name:String,value:String )
+	
+		Local map:=_items[fileType]
+		If map
+			map[name]=value
+			OnChanged( fileType )
+		Endif
+	End
+	
+	Method All:StringMap<StringMap<String>>.Iterator()
+	
+		Return _items.All()
+	End
+	
+	Method All:StringMap<String>.Iterator( fileType:String )
+		
+		Local map:=_items[fileType]
+		Return map ? map.All() Else Null
+	End
+	
+	Method Add( fileType:String,name:String,value:String )
+	
+		Local map:=_items[fileType]
+		If map 
+			map[name]=value
+			OnChanged( fileType )
+		Endif
+	End
+	
+	Method Remove( fileType:String,name:String )
+	
+		Local map:=_items[fileType]
+		If map
+			map.Remove( name )
+			OnChanged( fileType )
+		Endif
+	End
+	
+	
+	Private
+	
+	Field _items:=New StringMap<StringMap<String>>
+	Field _dirty:Bool
+	
+	Property DefaultPath:String()
+		Return "asset::liveTemplates.json"
+	End
+	
+	Property CustomPath:String()
+		Return Prefs.IdeHomeDir+"customTemplates.json"
+	End
+	
+	Method Load( jsonPath:String )
+		
+		If Not FileExists( jsonPath ) Return
+			
+		Local langs:=Json_LoadObject( jsonPath ).All()
+		For Local i:=Eachin langs
+			Local lang:=i.Key
+			Local map:=New StringMap<String>
+			_items[lang]=map
+			Local all:=i.Value.ToObject().All()
+			For Local j:=Eachin all
+				map[j.Key]=j.Value.ToString().Replace( "~r~n","~n" ).Replace( "~r","~n" )
+			Next
+		Next
+		NotifyDataChanged()
+	End
+	
+	Method OnChanged( lang:String )
+		
+		_dirty=True
+	End
+	
+	Method NotifyDataChanged()
+	
+		For Local it:=Eachin All()
+			DataChanged( it.Key )
+		Next
+	End
+	
+End
+
+
+Class TemplateListViewItem Extends ListViewItem
+	
+	Field name:String
+	Field value:String
+	
+	Method New( name:String,value:String )
+		
+		Super.New( GetCaption( name,value ) )
+		
+		Self.name=name
+		Self.value=value
+	End
+	
+	
+	Private
+	
+	Method GetCaption:String( name:String,value:String )
+		
+		Local s:=value.Replace( "~n"," ... " ).Replace( "~t","" ).Replace( "${Cursor}","" )
+		Return name+"   "+s
+	End
+End

+ 1886 - 0
MainWindow.monkey2

@@ -0,0 +1,1886 @@
+
+Namespace ted2go
+
+
+#Import "assets/about.html@/ted2"
+#Import "assets/aboutTed2Go.html@/ted2"
+
+#Import "assets/themes/@/themes"
+
+#Import "assets/newfiles/@/ted2/newfiles"
+
+#Import "assets/fonts/@/fonts"
+
+#Import "assets/themes/irc/@/themes/irc"
+
+
+Global MainWindow:MainWindowInstance
+
+Class MainWindowInstance Extends Window
+	
+	Field SizeChanged:Void()
+	Field Rendered:Void( canvas:Canvas )
+	
+	Method New( title:String,rect:Recti,flags:WindowFlags,jobj:JsonObject )
+		Super.New( title,rect,flags )
+		
+		MainWindow=Self
+		
+		UpdateToolsPaths()
+		
+		LiveTemplates.Load()
+		
+		_tabsWrap=New DraggableTabs
+		
+		_docsTabView=New TabViewExt( TabViewFlags.DraggableTabs|TabViewFlags.ClosableTabs )
+		
+		_recentFilesMenu=New MenuExt( "Recent files" )
+		_recentProjectsMenu=New MenuExt( "Recent projects" )
+		_closeProjectMenu=New MenuExt( "Close project" )
+		
+		_docBrowser=New DockingView
+		
+		_docsManager=New DocumentManager( _docsTabView,_docBrowser )
+
+		_docsManager.CurrentDocumentChanged+=Lambda()
+			
+			UpdateKeyView()
+			CodeDocument.HideAutocomplete()
+			
+			Local doc:=Cast<CodeTextView>( _docsManager.CurrentTextView )
+			Local mode:=doc ? doc.OverwriteMode Else False
+			OverwriteTextMode=mode
+			
+			_findReplaceView.CodeView=Cast<CodeTextView>( _docsManager.CurrentTextView )
+		End
+		
+		_docsManager.DocumentDoubleClicked+=Lambda( doc:Ted2Document )
+		
+			_buildActions.LockBuildFile()
+		End
+		
+		App.FileDropped+=Lambda( path:String )
+			
+			OnFileDropped( path )
+		End
+
+		_docsManager.DocumentAdded+=Lambda( doc:Ted2Document )
+			AddRecentFile( doc.Path )
+			SaveState()
+		End
+
+		_docsManager.DocumentRemoved+=Lambda( doc:Ted2Document )
+			If IsTmpPath( doc.Path ) DeleteFile( doc.Path )
+			SaveState()
+		End
+		
+		'IRC tab
+		
+		_ircView=New IRCView
+		_ircView.introScreen.Text="Hang out with other Monkey 2 users"
+		_ircView.introScreen.OnNickChange+=Lambda( nick:String )
+			Prefs.IrcNickname=nick
+		End
+		
+		SetupChatTab()
+		
+		If Prefs.IrcConnect Then _ircView.introScreen.Connect()
+		
+		'Build tab
+		
+		_buildConsole=New ConsoleExt
+		
+		'Output tab
+		
+		_outputConsole=New ConsoleExt
+		Local bar:=New ToolBarExt
+		bar.MaxSize=New Vec2i( 300,30 )
+		
+		Local label:=New Label( "Filter:" )
+		bar.AddView( label,"left" )
+		Local editFilter:=New TextFieldExt
+		editFilter.Style=GetStyle( "TextFieldBordered" )
+		editFilter.CursorType=CursorType.Line
+		editFilter.CursorBlinkRate=2.5
+		bar.AddView( editFilter,"left",200 )
+		editFilter.TextChanged+=Lambda()
+		
+			Local t:=editFilter.Text
+			_outputConsole.SetFilter( t )
+		End
+		
+		bar.AddSeparator()
+		
+		bar.AddIconicButton(
+			ThemeImages.Get( "outputbar/clean.png" ),
+			Lambda()
+				_outputConsole.ClearAll()
+			End,
+			"Clear all" )
+		
+		Local it:=bar.AddIconicButton(
+			ThemeImages.Get( "outputbar/wrap.png" ),
+			Lambda()
+				_outputConsole.WordWrap=Not _outputConsole.WordWrap
+			End,
+			"Word wrap" )
+		it.ToggleMode=True
+		
+		_outputConsoleView=New DockingView
+		_outputConsoleView.AddView( bar,"top" )
+		_outputConsoleView.ContentView=_outputConsole
+		
+		
+		'Find tab
+		
+		_findConsole=New TreeViewExt
+		_findConsole.NodeClicked+=Lambda( node:TreeView.Node )
+		
+			Local n:=Cast<NodeWithData<FileJumpData>>( node )
+			If Not n Return
+			
+			Local data:=n.data
+			
+			Local doc:=_docsManager.OpenDocument( data.path,True )
+			If Not doc Return
+			
+			Local tv:=doc.TextView
+			If Not tv Return
+			
+			UpdateWindow( False )
+			
+			tv.SelectText( data.pos,data.pos+data.len ) 'set cursor here
+		End
+		
+		'Help tab
+		
+		_helpView=New HtmlViewExt
+		_docsConsole=New DockingView
+		bar=New ToolBarExt
+		bar.MaxSize=New Vec2i( 300,30 )
+		bar.AddIconicButton(
+			ThemeImages.Get( "docbar/home.png" ),
+			Lambda()
+				_helpView.ClearHistory()
+				_helpView.Navigate( AboutPagePath )
+			End,
+			"Home" )
+		bar.AddIconicButton(
+			ThemeImages.Get( "docbar/back.png" ),
+			Lambda()
+				_helpView.Back()
+			End,
+			"Back" )
+		bar.AddIconicButton(
+			ThemeImages.Get( "docbar/forward.png" ),
+			Lambda()
+				_helpView.Forward()
+			End,
+			"Forward" )
+		bar.AddSeparator()
+		bar.AddSeparator()
+		label=New Label
+		
+		bar.ContentView=label
+		
+		_helpView.Navigated+=Lambda( url:String )
+			
+			label.Text=url
+		End
+		
+		_helpTree=New HelpTreeView( _helpView )
+		_docsConsole.AddView( _helpTree,"right",200,True )
+		
+		_docsConsole.AddView( bar,"top" )
+		_docsConsole.ContentView=_helpView
+		
+		_helpSwitcher=New ToolButtonExt( New Action( "<" ) )
+		bar.AddView( New SpacerView( 6,0 ),"right" ) ' right offset
+		bar.AddView( _helpSwitcher,"right" )
+		_helpSwitcher.Clicked=Lambda()
+		
+			_helpTree.Visible=Not _helpTree.Visible
+			_helpSwitcher.Text=_helpTree.Visible ? ">" Else "<"
+			_helpSwitcher.Hint=_helpTree.Visible ? "Hide docs index" Else "Show docs index"
+		End
+		_helpTree.Visible=False
+		_helpSwitcher.Clicked() 'show at startup
+		
+		_helpView.Navigate( AboutPagePath )
+		
+		
+		_debugView=New DebugView( _docsManager,_outputConsole )
+		
+		_buildActions=New BuildActions( _docsManager,_buildConsole,_debugView )
+		_buildActions.ErrorsOccured+=Lambda( errors:BuildError[] )
+			ShowBuildConsole( True )
+			_buildActions.GotoError( errors[0] )
+			
+			_buildErrorsList.Clear()
+			For Local err:=Eachin errors
+				_buildErrorsList.AddItem( New BuildErrorListViewItem( err ) )
+			Next
+			_buildErrorsList.Visible=True
+		End
+		
+		' ProjectView
+		'
+		_projectView=New ProjectView( _docsManager,_buildActions )
+		' project opened
+		_projectView.ProjectOpened+=Lambda( dir:String )
+			AddRecentProject( dir )
+			SaveState()
+		End
+		' project closed
+		_projectView.ProjectClosed+=OnProjectClosed
+		' find in folder
+		_projectView.RequestedFindInFolder+=Lambda( folder:String )
+			_findActions.FindInFiles( folder )
+		End
+		
+		_fileActions=New FileActions( _docsManager )
+		_editActions=New EditActions( _docsManager )
+		_findActions=New FindActions( _docsManager,_projectView,_findConsole )
+		_helpActions=New HelpActions
+		_viewActions=New ViewActions( _docsManager )
+		
+		_tabMenu=New Menu
+		_tabMenu.AddAction( _fileActions.close )
+		_tabMenu.AddAction( _fileActions.closeOthers )
+		_tabMenu.AddAction( _fileActions.closeToRight )
+		_tabMenu.AddSeparator()
+		_tabMenu.AddAction( _fileActions.save )
+		_tabMenu.AddAction( _fileActions.saveAs )
+		_tabMenu.AddSeparator()
+		_tabMenu.AddAction( _buildActions.lockBuildFile )
+		
+		_docsTabView.RightClicked+=Lambda()
+			_tabMenu.Open()
+		End
+		
+		_docsTabView.CloseClicked+=Lambda( index:Int )
+
+			Local doc:=_docsManager.FindDocument( _docsTabView.TabView( index ) )
+			If Not doc.Dirty And Not IsTmpPath( doc.Path )
+				doc.Close()
+				Return
+			Endif
+			_docsManager.CurrentDocument=doc
+			_fileActions.close.Trigger()
+		End
+
+		
+		'File menu
+		'
+		_templateFiles=New MenuExt( "Templates" )
+		Local p:=AssetsDir()+"ted2/newfiles/"
+		For Local f:=Eachin LoadDir( p )
+			Local src:=stringio.LoadString( p+f )
+			_templateFiles.AddAction( StripExt( f.Replace( "_"," " ) ) ).Triggered=Lambda()
+				Local path:=AllocTmpPath( "untitled",ExtractExt( f ) )
+				If Not path Return
+				SaveString( src,path )
+				Local doc:=_docsManager.OpenDocument( path,True )
+			End
+		Next
+		
+		_fileMenu=New MenuExt( "File" )
+		_fileMenu.AddAction( _fileActions.new_ )
+		_fileMenu.AddAction( _fileActions.open )
+		_fileMenu.AddSubMenu( _recentFilesMenu )
+		_fileMenu.AddSubMenu( _templateFiles )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _fileActions.close )
+		_fileMenu.AddAction( _fileActions.closeOthers )
+		_fileMenu.AddAction( _fileActions.closeToRight )
+		_fileMenu.AddAction( _fileActions.closeAll )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _fileActions.save )
+		_fileMenu.AddAction( _fileActions.saveAs )
+		_fileMenu.AddAction( _fileActions.saveAll )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _projectView.openProject )
+		_fileMenu.AddSubMenu( _recentProjectsMenu )
+		_fileMenu.AddSubMenu( _closeProjectMenu )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _fileActions.prefs )
+		_fileMenu.AddSeparator()
+		_fileMenu.AddAction( _fileActions.quit )
+		
+		'Edit menu
+		'
+		_editMenu=New MenuExt( "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( _editActions.wordWrap )
+		
+		'Find menu
+		'
+		_findMenu=New MenuExt( "Find" )
+		_findMenu.AddAction( _findActions.find )
+		_findMenu.AddAction( _findActions.replace )
+		_findMenu.AddAction( _findActions.findNext )
+		_findMenu.AddAction( _findActions.findPrevious )
+		_findMenu.AddSeparator()
+		_findMenu.AddAction( _findActions.findInFiles )
+		
+		'View menu
+		'
+		_viewMenu=New MenuExt( "View" )
+		_viewMenu.AddAction( _viewActions.gotoLine )
+		_viewMenu.AddAction( _viewActions.gotoDeclaration )
+		_viewMenu.AddSeparator()
+		_viewMenu.AddAction( _viewActions.comment )
+		_viewMenu.AddAction( _viewActions.uncomment )
+		_viewMenu.AddSeparator()
+		_viewMenu.AddAction( _viewActions.goBack )
+		_viewMenu.AddAction( _viewActions.goForward )
+		
+		'Build menu
+		'
+		_forceStop=New Action( "Force Stop" )
+		_forceStop.Triggered=OnForceStop
+		_forceStop.HotKey=Key.F5
+		_forceStop.HotKeyModifiers=Modifier.Shift
+		
+		'
+		_buildActions.PreBuild+=OnPreBuild
+		_buildActions.PreSemant+=OnPreSemant
+		_buildActions.PreBuildModules+=OnPreBuildModules
+		
+		_buildMenu=New MenuExt( "Build" )
+		_buildMenu.AddAction( _buildActions.buildAndRun )
+		_buildMenu.AddAction( _buildActions.build )
+		_buildMenu.AddAction( _buildActions.semant )
+		_buildMenu.AddAction( _buildActions.debugApp )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddSubMenu( _buildActions.targetMenu )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _forceStop )
+		_buildMenu.AddAction( _buildActions.nextError )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _buildActions.lockBuildFile )
+		_buildMenu.AddSeparator()
+		_buildMenu.AddAction( _buildActions.updateModules )
+		_buildMenu.AddAction( _buildActions.moduleManager )
+		
+		'Window menu
+		'
+		_windowMenu=New MenuExt( "Window" )
+		_windowMenu.AddAction( _docsManager.nextDocument )
+		_windowMenu.AddAction( _docsManager.prevDocument )
+		_windowMenu.AddSeparator()
+		
+		_themesMenu=CreateThemesMenu( "Themes" )
+		
+		AddZoomActions( _windowMenu )
+		_windowMenu.AddSeparator()
+		_windowMenu.AddSubMenu( _themesMenu )
+		
+		
+		'Help menu
+		'
+		_helpMenu=New MenuExt( "Help" )
+		_helpMenu.AddAction( _helpActions.quickHelp )
+		_helpMenu.AddAction( _helpActions.viewManuals )
+		If IsBananasShowcaseAvailable() Then _helpMenu.AddAction( _helpActions.bananas )
+		_helpMenu.AddSeparator()
+		_helpMenu.AddAction( _buildActions.rebuildHelp )
+		_helpMenu.AddSeparator()
+'		_helpMenu.AddAction( _helpActions.onlineHelp )
+		_helpMenu.AddAction( _helpActions.mx2homepage )
+		_helpMenu.AddAction( _helpActions.uploadModules )
+		_helpMenu.AddSeparator()
+		_helpMenu.AddAction( _helpActions.about )
+		_helpMenu.AddAction( _helpActions.aboutTed2go )
+		_helpMenu.AddSeparator()
+		_helpMenu.AddAction( _helpActions.makeBetter )
+		
+		'Menu bar
+		'
+		_menuBar=New MenuBarExt
+		_menuBar.AddMenu( _fileMenu )
+		_menuBar.AddMenu( _editMenu )
+		_menuBar.AddMenu( _findMenu )
+		_menuBar.AddMenu( _viewMenu )
+		_menuBar.AddMenu( _buildMenu )
+		_menuBar.AddMenu( _windowMenu )
+		_menuBar.AddMenu( _helpMenu )
+		
+		_buildErrorsList=New ListViewExt
+		_buildErrorsList.Visible=False
+		_buildErrorsList.OnItemChoosen+=Lambda()
+			Local item:=Cast<BuildErrorListViewItem>( _buildErrorsList.CurrentItem )
+			_buildActions.GotoError( item.error )
+		End
+		
+		_buildConsoleView=New DockingView
+		_buildConsoleView.AddView( _buildErrorsList,"right","400",True )
+		_buildConsoleView.ContentView=_buildConsole
+		
+		_statusBar=New StatusBarView
+		
+		_contentView=New DockingView
+		_contentView.AddView( _menuBar,"top" )
+		
+		ArrangeElements()
+		
+		ContentView=_contentView
+
+		OnCreatePlugins() 'init plugins before loadstate, to register doctypes before open last opened files
+		
+		LoadState( jobj )
+		
+		App.MouseEventFilter+=ThemeScaleMouseFilter
+		
+		App.Idle+=OnAppIdle
+		
+		CheckFirstStart()
+		
+		_enableSaving=True
+		
+	End
+	
+	Field PrefsChanged:Void()
+	Method OnPrefsChanged()
+		
+		ArrangeElements()
+		PrefsChanged()
+		
+		SetupChatTab()
+		
+	End
+	
+	Method GainFocus()
+		
+		'Local event:=New WindowEvent( EventType.WindowGainedFocus,Self )
+		'OnWindowEvent( event )
+		
+		'SendWindowEvent( event )
+		'SDL_RaiseWindow( SDLWindow )
+	End
+	
+	Method HideFindPanel:Bool()
+		
+		If Not _findReplaceView.Visible Return False
+		
+		_findReplaceView.CodeView=Null
+		_findReplaceView.Visible=False
+		UpdateKeyView()
+		
+		Return True
+	End
+	
+	Method ShowFind( what:String="" )
+		
+		_findReplaceView.CodeView=Cast<CodeTextView>( _docsManager.CurrentTextView )
+		
+		Local arr:=what.Split( "~n" )
+		If arr.Length>1
+			what=""
+		Endif
+		
+		If _findReplaceView.Visible And Not what
+			what=_findReplaceView.FindText
+		Endif
+		_findReplaceView.Visible=True
+		_findReplaceView.FindText=what
+		_findReplaceView.Mode=FindReplaceView.Kind.Find
+		_findReplaceView.Activate()
+	End
+	
+	Method ShowReplace( what:String="" )
+		
+		ShowFind( what )
+		_findReplaceView.Mode=FindReplaceView.Kind.Replace
+	End
+	
+	Method OnFind()
+		_findActions.find.Trigger()
+	End
+	
+	Method OnFindPrev()
+		_findActions.findPrevious.Trigger()
+	End
+	
+	Method OnFindNext()
+		_findActions.findNext.Trigger()
+	End
+	
+	Method OnForceStop()
+	
+		If _buildConsole.Running
+			_buildConsole.Terminate()
+		Endif
+		_debugView.KillApp()
+		HideStatusBarProgress()
+		RestoreConsoleVisibility()
+		If _outputConsole.Running
+			_outputConsole.Terminate()
+		Endif
+	End
+	
+	Property Mx2ccPath:String()
+	
+		Return _mx2cc
+	End
+	
+	Property ModsPath:String()
+	
+		Return _modsDir
+	End
+	
+	Property OverwriteTextMode:Bool()
+	
+		Return _ovdMode
+	Setter( value:Bool )
+		
+		If value=_ovdMode Return
+		_ovdMode=value
+		
+		Local doc:=Cast<CodeTextView>( _docsManager.CurrentTextView )
+		If doc
+			doc.OverwriteMode=_ovdMode
+		Else
+			_ovdMode=False
+		Endif
+		
+		SetStatusBarInsertMode( Not _ovdMode )
+	End
+	
+	Property DocsManager:DocumentManager()
+	
+		Return _docsManager
+	End
+	
+	Property LockedDocument:CodeDocument()
+	
+		Return _buildActions.LockedDocument
+	End
+	
+	Property IsTerminating:Bool()
+		
+		Return _isTerminating
+	End
+	
+	Property ThemeName:String()
+		
+		Return _theme
+	Setter( value:String )
+		
+		_theme=value
+	End
+	
+	Property AboutPagePath:String()
+		
+		Local path:=Prefs.MonkeyRootPath+"ABOUT.HTML"
+'		If Not IsFileExists( path )
+'			path="asset::ted2/about.html"
+'		Endif
+		Return path
+	End
+	
+	Method Terminate()
+		
+		_isTerminating=True
+		SaveState()
+		_enableSaving=False
+		OnForceStop() ' kill build process if started
+		If _ircView Then _ircView.Quit("Closing Ted2Go")
+		
+		' waiting for started processes if any
+		ParsersManager.DisableAll()
+		Local future:=New Future<Bool>
+		New Fiber( Lambda()
+			ProcessReader.WaitingForStopAll( future )
+		End )
+		future.Get()
+		
+		App.Terminate()
+	End
+
+	'Use these as macos still seems to have problems running requesters on a fiber - stacksize?
+	'
+	Method RequestFile:String( title:String,path:String,save:Bool,filter:String="" )
+	
+		Local future:=New Future<String>
+		
+		If Not filter Then filter="Monkey2 files:monkey2;Text files:txt;Image files:png,jpg,jpeg;All files:*"
+		
+		App.Idle+=Lambda()
+			
+			Local s:=requesters.RequestFile( title,filter,save,path )
+			future.Set( s )
+		End
+		
+		Return future.Get()
+	End
+
+	Method RequestDir:String( title:String,dir:String )
+		
+		Local future:=New Future<String>
+		
+		App.Idle+=Lambda()
+			future.Set( requesters.RequestDir( title,dir ) )
+		End
+		
+		Return future.Get()
+	End
+	
+	Method AllocTmpPath:String( ident:String,ext:String )
+	
+		For Local i:=1 Until 100
+			Local path:=_tmp+ident+i+ext
+			If GetFileType( path )<>FileType.None Continue
+			If CreateFile( path ) Return path
+		Next
+
+		Return ""
+	End
+	
+	Method UpdateToolsPaths()
+		
+		_tmp=RealPath( "tmp/" )
+		
+#If __TARGET__="macos"
+		_mx2cc="bin/mx2cc_macos"
+#Else If __TARGET__="windows"
+		_mx2cc="bin/mx2cc_windows.exe"
+#Else If __TARGET__="raspbian"
+		_mx2cc="bin/mx2cc_raspbian"
+#Else
+		_mx2cc="bin/mx2cc_linux"
+#Endif
+		_mx2cc=RealPath( _mx2cc )
+		
+		_modsDir=RealPath( "modules/" )
+	End
+	
+	Method StoreConsoleVisibility()
+	
+		'If Prefs.SiblyMode return
+		
+		'_storedConsoleVisible=_consolesTabView.Visible
+		'_consoleVisibleCounter=0
+	End
+	
+	Method RestoreConsoleVisibility()
+	
+		'If Prefs.SiblyMode Return
+	
+		'If _consoleVisibleCounter > 0 Return
+		'_consolesTabView.Visible=_storedConsoleVisible
+		'RequestRender()
+	End
+	
+	Method IsTmpPath:Bool( path:String )
+
+		Return path.StartsWith( _tmp )
+	End
+	
+	Method SetStatusBarActive( active:Bool )
+	
+		_statusBar.SetActiveState( active )
+	End
+	
+	Method ShowStatusBarText( text:String,append:Bool=False )
+	
+		_statusBar.SetText( text,append )
+	End
+	
+	Method SetStatusBarInsertMode( ins:Bool )
+	
+		_statusBar.SetInsMode( ins )
+	End
+	
+	Method ShowStatusBarLineInfo( tv:TextView )
+		
+		Local line:=tv.Document.FindLine( tv.Cursor )
+		Local pos:=tv.Cursor-tv.Document.StartOfLine( line )
+		line+=1
+		pos+=1
+		_statusBar.SetLineInfo( "Ln : "+line+"    Col : "+pos )
+	End
+	
+	Method ShowStatusBarProgress( cancelCallback:Void(),cancelIconOnly:Bool=False )
+	
+		_statusBar.Cancelled=cancelCallback
+		_statusBar.ShowProgress( cancelIconOnly )
+	End
+	
+	Method HideStatusBarProgress()
+	
+		_statusBar.HideProgress()
+	End
+	
+	
+	Private
+	
+	Method GetFindDock:DockingView()
+		
+		If _findReplaceView Return _findReplaceView
+		
+		_findReplaceView=New FindReplaceView( _findActions )
+		
+		_findReplaceView.RequestedFind+=Lambda( opt:FindOptions )
+			
+			_findActions.options=opt
+			If opt.goNext
+				_findActions.findNext.Triggered()
+			Else
+				_findActions.findPrevious.Triggered()
+			Endif
+		End
+		
+		_findReplaceView.RequestedReplace+=Lambda( opt:FindOptions )
+		
+			_findActions.options=opt
+			If opt.all
+				_findActions.replaceAll.Triggered()
+			Else
+				_findActions.replaceNext.Triggered()
+			Endif
+		End
+		
+		Return _findReplaceView
+	End
+	
+	Method GetMainToolBar:ToolBarExt()
+		
+		If _toolBar Return _toolBar
+		
+		'Tool Bar
+		'
+		Local newTitle:=GetActionTextWithShortcut( _fileActions.new_ )
+		Local openTitle:=GetActionTextWithShortcut( _fileActions.open )
+		Local saveTitle:=GetActionTextWithShortcut( _fileActions.save )
+		Local saveAllTitle:=GetActionTextWithShortcut( _fileActions.saveAll )
+		Local undoTitle:=GetActionTextWithShortcut( _editActions.undo )
+		Local redoTitle:=GetActionTextWithShortcut( _editActions.redo )
+		Local runTitle:=GetActionTextWithShortcut( _buildActions.buildAndRun )
+		Local buildTitle:=GetActionTextWithShortcut( _buildActions.build )
+		Local checkTitle:=GetActionTextWithShortcut( _buildActions.semant )
+		Local findTitle:=GetActionTextWithShortcut( _findActions.find )
+		Local debugTitle:=GetActionTextWithShortcut( _buildActions.debugApp )
+		Local cutTitle:=GetActionTextWithShortcut( _editActions.cut )
+		Local copyTitle:=GetActionTextWithShortcut( _editActions.copy )
+		Local pasteTitle:=GetActionTextWithShortcut( _editActions.paste )
+		Local goBackTitle:=GetActionTextWithShortcut( _viewActions.goBack )
+		Local goForwTitle:=GetActionTextWithShortcut( _viewActions.goForward )
+		
+		_toolBar=New ToolBarExt
+		_toolBar.Style=GetStyle( "MainToolBar" )
+		_toolBar.MaxSize=New Vec2i( 10000,40 )
+		
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/back.png" ),_viewActions.goBack.Triggered,goBackTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/forward.png" ),_viewActions.goForward.Triggered,goForwTitle )
+		_toolBar.AddSeparator()
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/new_file.png" ),_fileActions.new_.Triggered,newTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/open_file.png" ),_fileActions.open.Triggered,openTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/open_project.png" ),_projectView.openProject.Triggered,"Open project..." )
+		Local icons:=New Image[]( ThemeImages.Get( "toolbar/save.png" ),ThemeImages.Get( "toolbar/save_dirty.png" ) )
+		_saveItem=_toolBar.AddIconicButton( icons,_fileActions.save.Triggered,saveTitle )
+		icons=New Image[]( ThemeImages.Get( "toolbar/save_all.png" ),ThemeImages.Get( "toolbar/save_all_dirty.png" ) )
+		_saveAllItem=_toolBar.AddIconicButton( icons,_fileActions.saveAll.Triggered,saveAllTitle )
+		_toolBar.AddSeparator()
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/cut.png" ),_editActions.cut.Triggered,cutTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/copy.png" ),_editActions.copy.Triggered,copyTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/paste.png" ),_editActions.paste.Triggered,pasteTitle )
+		_toolBar.AddSeparator()
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/undo.png" ),_editActions.undo.Triggered,undoTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/redo.png" ),_editActions.redo.Triggered,redoTitle )
+		_toolBar.AddSeparator()
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/check.png" ),_buildActions.semant.Triggered,checkTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/build.png" ),_buildActions.build.Triggered,buildTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/run.png" ),_buildActions.buildAndRun.Triggered,runTitle )
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/debug.png" ),_buildActions.debugApp.Triggered,debugTitle )
+		_toolBar.AddSeparator()
+		
+		Local act:=Lambda()
+			_buildActions.targetMenu.Open()
+		End
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/options.png" ),act,"Target settings" )
+		_toolBar.AddSeparator()
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/find.png" ),_findActions.find.Triggered,findTitle )
+		
+		Return _toolBar
+	End
+	
+	Method DeleteTmps()
+	
+		For Local f:=Eachin LoadDir( _tmp )
+			Local path:=_tmp+f
+			If GetFileType( path )=FileType.File
+				If Not _docsManager.FindDocument( path ) DeleteFile( path )
+			Else
+				DeleteDir( path,True )
+			Endif
+		Next
+		
+	End
+	
+	Method CheckFirstStart()
+		
+		If GetFileType( "bin/ted2.state.json" )=FileType.None
+			_helpActions.about.Trigger()
+			ShowBananasShowcase()
+		Endif
+	End
+	
+	
+	Public
+	
+	Method ShowProjectView()
+		
+		_tabsWrap.tabs["Project"].Activate()
+	End
+	
+	Method ShowDebugView()
+		
+		_tabsWrap.tabs["Debug"].Activate()
+	End
+	
+	Method ShowBuildConsole( vis:Bool=True )
+		
+		Local tab:=_tabsWrap.tabs["Build"]
+		tab.Activate()
+		If vis tab.ParentDock.Visible=True
+	End
+	
+	Method ShowOutputConsole( vis:Bool=True )
+		
+		Local tab:=_tabsWrap.tabs["Output"]
+		tab.Activate()
+		If vis tab.ParentDock.Visible=True
+	End
+	
+	Method ShowHelpView()
+		
+		Local tab:=_tabsWrap.tabs["Docs"]
+		tab.Activate()
+		tab.ParentDock.Visible=True
+	End
+	
+	Method ShowFindResults()
+		
+		Local tab:=_tabsWrap.tabs["Find"]
+		tab.Activate()
+		tab.ParentDock.Visible=True
+	End
+	
+	Method ShowFindInDocs()
+		
+		Local doc:=Cast<CodeDocumentView>( _docsManager.CurrentTextView )
+		If Not doc Return
+		
+		Local ident:=doc.WordAtCursor
+		Print "ident: "+ident
+		_helpTree.QuickHelp( ident )
+		_helpTree.Visible=False
+		_helpSwitcher.Clicked()
+		_tabsWrap.tabs["Docs"].Activate()
+	End
+	
+	Method ShowQuickHelp()
+		
+		Local doc:=Cast<CodeDocumentView>( _docsManager.CurrentTextView )
+		If Not doc Return
+		
+		Local ident:=doc.FullIdentAtCursor
+		
+		If Not ident Return
+		
+		Local parser:=ParsersManager.Get( doc.FileType )
+		Local item:=parser.ItemAtScope( ident,doc.FilePath,doc.LineNumAtCursor )
+		If item
+			Local s:=item.Namespac
+			If s
+				Local i:=s.Find( "." )
+				If i<>-1 Then s=s.Slice( 0,i )
+			Endif
+			Local ident2:="",parentIdent:=""
+			ident=s+":"+item.Namespac+"."
+			If item.Parent
+				If item.Parent.IsLikeClass
+					parentIdent=item.Parent.Ident
+					ident2=s+":"+parentIdent+"."+item.Ident
+				Endif
+				ident+=item.Parent.Ident+"."
+			Endif
+			ident+=item.Ident
+			
+			If ident=_helpIdent
+				If item.IsModuleMember
+					Local url:=_helpTree.PageUrl( ident )
+					If GetFileType( url )<>FileType.File Then url=_helpTree.PageUrl( ident2 )
+					
+					If GetFileType( url )<>FileType.File
+						Local ext:=ExtractExt( url )
+						Repeat
+							Local i:=url.FindLast( "-" )
+							If i=-1
+								url=""
+								Exit
+							Endif
+							url=url.Slice( 0,i )+ext
+						Forever
+					Endif
+					If url ShowHelp( url )
+				Else
+					GotoCodePosition( item.FilePath,item.ScopeStartPos )
+				Endif
+			Else
+				Local nmspace:=item.Namespac
+				If parentIdent Then nmspace+="."+parentIdent
+				Local ext:=item.IsExtension ? "(ext) " Else ""
+				ShowStatusBarText( ext+"("+item.KindStr+") "+item.Text+"    |  "+nmspace+"  |  "+StripDir( item.FilePath )+"  |  line "+(item.ScopeStartPos.x+1) )
+			Endif
+			
+			_helpIdent=ident
+			
+		ElseIf KeywordsManager.Get( doc.FileType ).Contains( ident )
+			
+			ShowStatusBarText( "(keyword) "+ident )
+		
+		Else
+			
+			ShowFindInDocs()
+			
+		Endif
+		
+	End
+	
+	Method ShowHelp( url:String )
+		
+		ShowHelpView()
+		_helpView.Navigate( url )
+		_helpView.Scroll=New Vec2i( 0,0 )
+	End
+	
+	Method ShowEditorMenu( tv:TextView )
+		
+		If Not tv Then tv=_docsManager.CurrentTextView
+		If Not tv Return
+		
+		If Not _editorMenu
+			_editorMenu=New MenuExt
+			_editorMenu.AddAction( _viewActions.gotoDeclaration )
+			_editorMenu.AddSeparator()
+			_editorMenu.AddAction( _editActions.cut )
+			_editorMenu.AddAction( _editActions.copy )
+			_editorMenu.AddAction( _editActions.paste )
+		Endif
+		
+		_editorMenu.Open()
+	End
+	
+	Method UpdateHelpTree()
+		_helpTree.Update()
+	End
+	
+	Method ShowBananasShowcase()
+		OpenDocument( Prefs.MonkeyRootPath+"bananas/ted2go-showcase/all.bananas" )
+	End
+	
+	Method ReadError( path:String )
+		Alert( "I/O Error reading file '"+path+"'" )
+	End
+	
+	Method WriteError( path:String )
+		Alert( "I/O Error writing file '"+path+"'" )
+	End
+
+	Method UpdateKeyView()
+
+		Local doc:=_docsManager.CurrentDocument
+		If Not doc Return
+		
+		If doc.TextView
+			doc.TextView.MakeKeyView()
+			ShowStatusBarLineInfo( doc.TextView )
+		Else
+			doc.View.MakeKeyView()
+		Endif
+	End
+	
+	Method GotoCodePosition( docPath:String, pos:Vec2i )
+		
+		Local doc:=Cast<CodeDocument>( _docsManager.OpenDocument( docPath,True ) )
+		If Not doc Return
+		
+		Local tv := Cast<CodeTextView>( doc.TextView )
+		If Not tv Return
+		
+		UpdateWindow( False )
+		
+		tv.GotoPosition( pos )
+		tv.MakeKeyView()
+	End
+	
+	Method GotoDeclaration()
+	
+		Local doc:=Cast<CodeDocument>( _docsManager.CurrentDocument )
+		If Not doc Return
+		
+		doc.GotoDeclaration()
+		doc.TextView.MakeKeyView()
+	End
+	
+	Method GotoLine()
+		
+		Local tv:=_docsManager.CurrentTextView
+		If Not tv Return
+		
+		New Fiber( Lambda()
+			
+			Local line:=RequestInt( "Goto line:","Goto line",tv.CursorLine+1,0,1,tv.Document.NumLines )
+			
+			If line Then tv.GotoLine( line-1 )
+			
+			tv.MakeKeyView()
+			
+		End )
+		
+	End
+	
+	Method SaveState()
+	
+		If Not _enableSaving Return
+
+		Local jobj:=New JsonObject
+		
+		jobj["windowRect"]=ToJson( Frame )
+		
+		SaveTabsState( jobj )
+		
+		Local jdocs:=New JsonObject
+		jobj["docsTab"]=jdocs
+		
+		jdocs["indexerVisible"]=New JsonBool( _helpTree.Visible )
+		jdocs["indexerSize"]=New JsonString( _docsConsole.GetViewSize( _helpTree ) )
+		
+		Local recent:=New JsonArray
+		For Local path:=Eachin _recentFiles
+			recent.Add( New JsonString( path ) )
+		End
+		jobj["recentFiles"]=recent
+		
+		recent=New JsonArray
+		For Local path:=Eachin _recentProjects
+			recent.Add( New JsonString( path ) )
+		End
+		jobj["recentProjects"]=recent
+		
+		jobj["theme"]=New JsonString( ThemeName )
+		
+		jobj["themeScale"]=New JsonNumber( App.Theme.Scale.y )
+		
+		If _mx2ccDir jobj["mx2ccDir"]=New JsonString( _mx2ccDir )
+		
+		_docsManager.SaveState( jobj )
+		_buildActions.SaveState( jobj )
+		_projectView.SaveState( jobj )
+		
+		Prefs.SaveState( jobj )
+		
+		SaveString( jobj.ToJson(),"bin/ted2.state.json" )
+	End
+
+	Method OpenDocument( path:String,lockIt:Bool=False )
+	
+		_docsManager.OpenDocument( path,True )
+		If lockIt Then _buildActions.LockBuildFile()
+		UpdateWindow( True )
+	End
+	
+	Method GetActionFind:Action()
+	
+		Return _findActions.find
+	End
+	
+	Method GetActionComment:Action()
+	
+		Return _viewActions.comment
+	End
+	
+	Method GetActionUncomment:Action()
+	
+		Return _viewActions.uncomment
+	End
+	
+
+	Private
+	
+	Field _inited:=False
+	Field _helpIdent:String
+	
+	Method OnRender( canvas:Canvas ) Override
+		
+		If Not _inited
+			_inited=True
+			OnInit()
+		Endif
+		
+		Super.OnRender( canvas )
+		
+		If _resized
+			_resized=False
+			SizeChanged()
+		Endif
+		
+		UpdateIrcIcon()
+		
+		Rendered( canvas )
+	End
+	
+	Method OnInit()
+		
+		' need to make visible after layout
+		_docsTabView.EnsureVisibleCurrentTab()
+	End
+	
+	Method OnFileDropped( path:String )
+		
+		If FileExists( path )
+			_docsManager.OpenDocument( path,True )
+		Else
+			_projectView.OpenProject( path )
+		Endif
+	End
+	
+	Method OnAppClose()
+		
+		_fileActions.quit.Trigger()
+	End
+	
+	Method OnPreBuild()
+		
+		OnForceStop()
+		_buildErrorsList.Visible=False
+	End
+	
+	Method OnPreSemant()
+	
+		_buildErrorsList.Visible=False
+	End
+	
+	Method OnPreBuildModules()
+	
+		_buildErrorsList.Visible=False
+	End
+	
+	Method OnProjectClosed( dir:String )
+		
+		UpdateCloseProjectMenu( dir )
+		
+		Local list:=New Stack<Ted2Document>
+		' close all related files
+		For Local doc:=Eachin _docsManager.OpenDocuments
+			If doc.Path.StartsWith( dir ) Then list.Add( doc )
+		Next
+		
+		_fileActions.CloseFiles( list.ToArray() )
+		
+		SaveState()
+	End
+	
+	Method OnResized()
+		
+		' just set a flag here.
+		' SizeChanged event will be called inside of OnRender to take re-layout effect.
+		_resized=True
+	End
+	
+	Method SetupChatTab()
+		
+		If Not _ircView Return
+		
+		_ircView.ircHandler.OnMessage+=Self.OnChatMessage
+		
+		Local intro:=_ircView.introScreen
+		
+		If intro.IsConnected Return
+		
+		Local nick:=Prefs.IrcNickname
+		Local server:=Prefs.IrcServer
+		Local port:=Prefs.IrcPort
+		Local rooms:=Prefs.IrcRooms
+		intro.AddOnlyServer( nick,server,server,port,rooms )
+		
+	End
+	
+	Method OnChatTabActiveChanged()
+		
+		Local tab:=_tabsWrap.tabs["Chat"]
+		
+		If Not tab.IsActive Return
+		
+		tab.Icon=Null
+		
+		_ircNotifyIcon=0
+		
+		HideHint()
+		
+	End
+	
+	Method OnChatMessage( message:IRCMessage, container:IRCMessageContainer, server:IRCServer )
+		
+		If message.type<>"PRIVMSG" Or _tabsWrap.tabs["Chat"].IsActive Return
+		
+		'Show notice icon
+		If message.text.Contains(server.nickname) Then
+			
+			If _ircNotifyIcon<=1 Then
+				
+				_ircNotifyIcon=2
+				
+				Local mentionStr:String
+				mentionStr=server.nickname+" was mentioned by "
+				mentionStr+=message.fromUser+" in "
+				mentionStr+=container.name
+				
+				Local dock:=_tabsWrap.tabs["Chat"].ParentDock '_tabsWrap.docks["bottom"]
+				ShowHint( mentionStr, New Vec2i( 0, -GetStyle( "Hint" ).Font.Height*4 ), dock, 20000 )
+				
+			Endif
+			
+		Else
+			
+			If _ircNotifyIcon<=0 Then _ircNotifyIcon=1
+			
+		Endif
+		
+	End
+	
+	Method UpdateIrcIcon()
+		
+		If _ircNotifyIcon<=0 Then Return
+		
+		Local time:Int=Int(Millisecs()*0.0025)
+		
+		If time=_ircIconBlink Then Return
+		_ircIconBlink=time
+		
+		Local tab:=_tabsWrap.tabs["Chat"]
+		
+		If time Mod 2 Then
+			Select _ircNotifyIcon
+				
+				Case 1
+					tab.Icon=App.Theme.OpenImage( "irc/notice.png" )
+					
+				Case 2
+					tab.Icon=App.Theme.OpenImage( "irc/important.png" )
+			End
+		Else
+			tab.Icon=App.Theme.OpenImage( "irc/blink.png" )
+		Endif
+		
+	End
+	
+	Method InitTabs()
+		
+		If Not _tabsWrap.tabs.Empty Return
+		
+		_tabsWrap.AddTab( "Project",_projectView )
+		_tabsWrap.AddTab( "Debug",_debugView )
+		_tabsWrap.AddTab( "Source",_docBrowser )
+		_tabsWrap.AddTab( "Build",_buildConsoleView )
+		_tabsWrap.AddTab( "Output",_outputConsoleView )
+		_tabsWrap.AddTab( "Docs",_docsConsole )
+		_tabsWrap.AddTab( "Find",_findConsole )
+		_tabsWrap.AddTab( "Chat",_ircView )
+		
+		_tabsWrap.tabs["Chat"].ActiveChanged+=OnChatTabActiveChanged
+	End
+	
+	Method ArrangeElements()
+		
+		InitTabs()
+		
+		_contentView.RemoveView( _toolBar )
+		_contentView.RemoveView( _statusBar )
+		_contentView.RemoveView( _findReplaceView )
+		
+		_tabsWrap.DetachFromParent()
+		
+		If Prefs.MainToolBarVisible
+			_toolBar=GetMainToolBar()
+			_contentView.AddView( _toolBar,"top" )
+		Endif
+		
+		_contentView.AddView( _statusBar,"bottom" )
+		
+		_tabsWrap.AttachToParent( _contentView )
+		
+		Local d:=GetFindDock()
+		d.Visible=False
+		_contentView.AddView( d,"bottom" )
+		
+		_contentView.ContentView=_docsTabView
+		
+		
+	End
+	
+	Method LoadTabsState( jobj:JsonObject )
+		
+		Global places:=New StringMap<StringStack>
+		' defaults
+		Local s:=""
+		places["left"]=New StringStack
+		s="Project,Source,Debug,Help"
+		places["right"]=New StringStack( s.Split( "," ) )
+		s="Build,Output,Docs,Find,Chat"
+		places["bottom"]=New StringStack( s.Split( "," ) )
+		
+		Global actives:=New StringMap<String>
+		' defaults
+		actives["left"]="Project"
+		actives["right"]="Project"
+		actives["bottom"]="Docs"
+		
+		Local edges:=DraggableTabs.Edges
+		
+		' put views
+		For Local edge:=Eachin edges
+			Local val:=Json_FindValue( jobj.Data,"tabsDocks/"+edge+"Tabs" )
+			If val And val<>JsonValue.NullValue
+				For Local v:=Eachin val.ToArray().All()
+					Local key:=v.ToString()
+					' remove from defaults
+					For Local e:=Eachin edges
+						places[e].Remove( key )
+					Next
+					'
+					Local tab:=_tabsWrap.tabs[key]
+					If tab Then _tabsWrap.docks[edge].AddTab( tab )
+				Next
+			Endif
+		Next
+		
+		' put default if any
+		For Local edge:=Eachin edges
+			For Local name:=Eachin places[edge]
+				Local tab:=_tabsWrap.tabs[name]
+				If tab Then _tabsWrap.docks[edge].AddTab( tab )
+			Next
+		Next
+		
+		For Local edge:=Eachin edges
+			' set active
+			Local val:=Json_FindValue( jobj.Data,"tabsDocks/"+edge+"Active" )
+			If val
+				actives[edge]=val.ToString()
+			Endif
+			Local tab:=_tabsWrap.tabs[actives[edge]]
+			If tab Then tab.Activate()
+			' set sizes
+			Local sz:=Json_FindValue( jobj.Data,"tabsDocks/"+edge+"Size" )
+			If sz
+				_tabsWrap.sizes[edge]=sz.ToString()
+			Endif
+			Local dock:=_tabsWrap.docks[edge]
+			_contentView.SetViewSize( dock,_tabsWrap.sizes[edge] )
+			' set visibility
+			Local vis:=Json_FindValue( jobj.Data,"tabsDocks/"+edge+"Visible" )
+			If vis
+				dock.Visible=vis.ToBool()
+			Endif
+			dock.Visible=dock.Visible And (dock.NumTabs>0)
+		Next
+		
+	End
+	
+	Method SaveTabsState( jobj:JsonObject )
+	
+		Local jj:=New JsonObject
+		jobj["tabsDocks"]=jj
+		
+		Local edges:=DraggableTabs.Edges
+		
+		For Local edge:=Eachin edges
+			Local dock:=_tabsWrap.docks[edge]
+			jj[edge+"Tabs"]=JsonArray.Create( dock.TabsNames )
+			jj[edge+"Active"]=New JsonString( dock.ActiveName )
+			jj[edge+"Visible"]=New JsonBool( dock.Visible )
+			jj[edge+"Size"]=New JsonString( _tabsWrap.GetDockSize( dock ) )
+		Next
+	End
+	
+	Method LoadState( jobj:JsonObject )
+	
+		LoadTabsState( jobj )
+		
+		If jobj.Contains( "docsTab" )
+			Local jdocs:=jobj.GetObject( "docsTab" )
+			Local size:=jdocs.GetString( "indexerSize" )
+			_docsConsole.SetViewSize( _helpTree,size )
+			Local vis:=jdocs.GetBool( "indexerVisible" )
+			_helpTree.Visible=Not vis
+			_helpSwitcher.Clicked()
+		Endif
+		
+		If jobj.Contains( "recentFiles" )
+			For Local file:=Eachin jobj.GetArray( "recentFiles" )
+				Local path:=file.ToString()
+				If GetFileType( path )<>FileType.File Continue
+				_recentFiles.Push( path )
+			Next
+		End
+		
+		If jobj.Contains( "recentProjects" )
+			For Local file:=Eachin jobj.GetArray( "recentProjects" )
+				Local path:=file.ToString()
+				If GetFileType( path )<>FileType.Directory Continue
+				_recentProjects.Push( path )
+			Next
+		End
+		
+		If jobj.Contains( "theme" ) ThemeName=jobj.GetString( "theme" )
+		
+		If jobj.Contains( "themeScale" )
+			_themeScale=jobj.GetNumber( "themeScale" )
+			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+		Endif
+		
+		If jobj.Contains( "mx2ccDir" )
+			_mx2ccDir=jobj.GetString( "mx2ccDir" )
+			If Not _mx2ccDir.EndsWith( "/" ) _mx2ccDir+="/"
+			_mx2cc=_mx2ccDir+StripDir( _mx2cc )
+		Endif
+		
+		App.Idle+=Lambda() 'delay execution
+			
+			_docsManager.LoadState( jobj )
+			_buildActions.LoadState( jobj )
+			_projectView.LoadState( jobj )
+		 
+			If Not _projectView.OpenProjects _projectView.OpenProject( CurrentDir() )
+			
+			UpdateRecentFilesMenu()
+			UpdateRecentProjectsMenu()
+			UpdateCloseProjectMenu()
+
+			DeleteTmps()
+			
+		End
+	End
+	
+	
+	Protected
+	
+	Method OnKeyEvent( event:KeyEvent ) Override
+	
+		Select event.Type
+		Case EventType.KeyDown
+			
+			Select event.Key
+			Case Key.Escape
+				
+				' hide find / replace panel
+				If HideFindPanel()
+					Return
+				Endif
+				
+				Local dock:TabViewExt
+				' show / hide left & right docks
+				If event.Modifiers & Modifier.Shift
+					
+					dock=_tabsWrap.docks["left"]
+					If dock.NumTabs>0 Then dock.Visible=Not dock.Visible
+					
+					dock=_tabsWrap.docks["right"]
+					If dock.NumTabs>0 Then dock.Visible=Not dock.Visible
+					
+				Else ' bottom dock
+					
+					dock=_tabsWrap.docks["bottom"]
+					If dock.NumTabs>0 Then dock.Visible=Not dock.Visible
+					
+					_consoleVisibleCounter+=1
+				Endif
+				
+			End
+		End
+	End
+	
+	Method OnWindowEvent( event:WindowEvent ) Override
+
+		Select event.Type
+			
+			Case EventType.WindowClose
+				OnAppClose()
+			
+			Case EventType.WindowResized
+				OnResized()
+			
+			Default
+				Super.OnWindowEvent( event )
+			
+		End
+	End
+	
+	
+	Private
+
+	Field _tmp:String
+	Field _mx2cc:String
+	Field _mx2ccDir:String
+	Field _modsDir:String
+	
+	Field _toolBar:ToolBarExt
+	Field _saveItem:MultiIconToolButton
+	Field _saveAllItem:MultiIconToolButton
+	Field _docsManager:DocumentManager
+	Field _fileActions:FileActions
+	Field _editActions:EditActions
+	Field _findActions:FindActions
+	Field _buildActions:BuildActions
+	Field _helpActions:HelpActions
+	Field _viewActions:ViewActions
+	
+	Field _ircView:IRCView
+	Field _buildConsole:ConsoleExt
+	Field _buildErrorsList:ListViewExt
+	Field _buildConsoleView:DockingView
+	Field _outputConsole:ConsoleExt
+	Field _outputConsoleView:DockingView
+	Field _helpView:HtmlViewExt
+	Field _docsConsole:DockingView
+	Field _findConsole:TreeViewExt
+	
+	Field _projectView:ProjectView
+	Field _docBrowser:DockingView
+	Field _debugView:DebugView
+	Field _helpTree:HelpTreeView
+	Field _helpSwitcher:ToolButtonExt
+	
+	'Field _ircTabView:TabView
+	Field _docsTabView:TabViewExt
+	Field _consolesTabView2:TabView
+	Field _browsersTabView2:TabView
+	
+	Field _ircNotifyIcon:Int
+	Field _ircIconBlink:Int
+	
+	Field _forceStop:Action
+
+	Field _tabMenu:Menu
+	Field _templateFiles:MenuExt
+	Field _fileMenu:MenuExt
+	Field _editMenu:MenuExt
+	Field _findMenu:MenuExt
+	Field _viewMenu:MenuExt
+	Field _buildMenu:MenuExt
+	Field _windowMenu:MenuExt
+	Field _helpMenu:MenuExt
+	Field _menuBar:MenuBarExt
+	Field _editorMenu:MenuExt
+	Field _themesMenu:MenuExt
+	
+	Field _theme:="default"
+	Field _themeScale:=1.0
+	
+	Field _contentView:DockingView
+	
+	Field _recentFiles:=New StringStack
+	Field _recentProjects:=New StringStack
+	
+	Field _recentFilesMenu:MenuExt
+	Field _recentProjectsMenu:MenuExt
+	Field _closeProjectMenu:MenuExt
+	Field _statusBar:StatusBarView
+	Field _ovdMode:=False
+	Field _storedConsoleVisible:Bool
+	Field _consoleVisibleCounter:=0
+	Field _isTerminating:Bool
+	Field _enableSaving:Bool
+	Field _resized:Bool
+	Field _findReplaceView:FindReplaceView
+	Field _tabsWrap:=New DraggableTabs
+	
+	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 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 AddRecentFile( path:String )
+	
+		_recentFiles.Remove( path )
+		_recentFiles.Insert( 0,path )
+		
+		If _recentFiles.Length>20 Then _recentFiles.Resize( 20 )
+		
+		UpdateRecentFilesMenu()
+	End
+	
+	Method AddRecentProject( path:String )
+	
+		_recentProjects.Remove( path )
+		_recentProjects.Insert( 0,path )
+	
+		If _recentProjects.Length>10 Then _recentProjects.Resize( 10 )
+		
+		UpdateRecentProjectsMenu()
+		UpdateCloseProjectMenu( path )
+	End
+	
+	Method UpdateRecentFilesMenu()
+	
+		_recentFilesMenu.Clear()
+		
+		Local recents:=New StringStack
+		
+		For Local path:=Eachin _recentFiles
+			If GetFileType( path )<>FileType.File Continue
+		
+			_recentFilesMenu.AddAction( path ).Triggered=Lambda()
+				_docsManager.OpenDocument( path,True )
+			End
+			
+			recents.Add( path )
+		Next
+		
+		_recentFiles=recents
+	End
+	
+	Method UpdateRecentProjectsMenu()
+	
+		_recentProjectsMenu.Clear()
+	
+		Local recents:=New StringStack
+	
+		For Local path:=Eachin _recentProjects
+			If GetFileType( path )<>FileType.Directory Continue
+	
+			_recentProjectsMenu.AddAction( path ).Triggered=Lambda()
+				_projectView.OpenProject( path )
+			End
+	
+			recents.Add( path )
+		Next
+	
+		_recentProjects=recents
+	End
+	
+	Method UpdateCloseProjectMenu( dir:String="" )
+	
+		_closeProjectMenu.Clear()
+		
+		For Local dir:=Eachin _projectView.OpenProjects
+		
+			_closeProjectMenu.AddAction( dir ).Triggered=Lambda()
+			
+				_projectView.CloseProject( dir )
+				
+				UpdateCloseProjectMenu()
+			End
+			
+		Next
+	End
+	
+	Method AddZoomActions( menu:MenuExt )
+		
+		menu.AddAction( "Zoom in" ).Triggered=Lambda()
+			If _themeScale>=4 Return
+			
+			_themeScale+=.125
+
+			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+		End
+		
+		menu.AddAction( "Zoom out" ).Triggered=Lambda()
+			If _themeScale<=.5 Return
+			
+			_themeScale-=.125
+
+			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+		End
+		
+		menu.AddAction( "Reset zoom" ).Triggered=Lambda()
+		
+			_themeScale=1
+			
+			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+		End
+	End
+
+	Method ThemeScaleMouseFilter( event:MouseEvent )
+	
+		If event.Eaten Return
+			
+		If event.Type=EventType.MouseWheel And event.Modifiers & Modifier.Menu
+			
+			If event.Wheel.y>0
+				If _themeScale<4 _themeScale+=0.125
+			Else
+				If _themeScale>.5 _themeScale-=0.125
+			Endif
+				
+			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+
+			event.Eat()
+				
+		Else If event.Type=EventType.MouseDown And event.Button=MouseButton.Middle And event.Modifiers & Modifier.Menu
+			
+			_themeScale=1
+
+			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+			
+			event.Eat()
+		Endif
+		
+	End
+	
+	Method CreateThemesMenu:MenuExt( text:String )
+	
+		Local menu:=New MenuExt( text )
+		
+		Local themes:=JsonObject.Load( "theme::themes.json" )
+		If Not themes Return menu
+		
+		For Local it:=Eachin themes
+			Local name:=it.Key
+			Local value:=it.Value.ToString()
+			menu.AddAction( name ).Triggered=Lambda()
+				
+				If value=ThemeName Return
+				
+				ThemeName=value
+				
+				App.Theme.Load( _theme,New Vec2f( _themeScale ) )
+				SaveState()
+			End
+		Next
+		
+		Return menu
+	End
+		
+	Method OnAppIdle()
+		
+		_docsManager.Update()
+		_fileActions.Update()
+		_editActions.Update()
+		_findActions.Update()
+		_buildActions.Update()
+		
+		_forceStop.Enabled=_buildConsole.Running Or _outputConsole.Running
+	
+		_saveItem.SetIcon( _fileActions.save.Enabled ? 1 Else 0 )
+		_saveAllItem.SetIcon( _fileActions.saveAll.Enabled ? 1 Else 0 )
+		
+		App.Idle+=OnAppIdle
+		
+	End
+	
+End
+
+
+Private
+
+Class DraggableTabs
+	
+	Const Edges:=New String[]( "left","right","bottom" )
+	
+	Field tabs:=New StringMap<TabButtonExt>
+	Field docks:=New StringMap<TabViewExt>
+	Field sizes:=New StringMap<String>
+	
+	Method New()
+		
+		sizes["left"]="300"
+		sizes["right"]="300"
+		sizes["bottom"]="250"
+		
+		_docksArray=New TabViewExt[Edges.Length]
+		Local i:=0
+		For Local edge:=Eachin Edges
+			docks[edge]=New TabViewExt
+			_docksArray[i]=docks[edge]
+			i+=1
+		Next
+	End
+	
+	Method AttachToParent( view:DockingView )
+		
+		For Local edge:=Eachin Edges
+			view.AddView( docks[edge],edge,sizes[edge],True )
+		Next
+		_parent=view
+	End
+	
+	Method DetachFromParent()
+		
+		If Not _parent Return
+		
+		For Local edge:=Eachin Edges
+			_parent.RemoveView( docks[edge] )
+		Next
+	End
+	
+	Method AddTab( name:String,view:View )
+		
+		tabs[name]=TabViewExt.CreateDraggableTab( name,view,_docksArray )
+	End
+	
+	Method GetDockSize:String( dock:TabViewExt )
+		
+		Return _parent.GetViewSize( dock )
+	End
+	
+	Property AllDocks:TabViewExt[]()
+		Return _docksArray
+	End
+	
+	Private
+	
+	Field _docksArray:TabViewExt[]
+	Field _parent:DockingView
+	
+End
+
+
+Function OnCreatePlugins()
+	
+	#rem
+	Local dialog:=New ProgressDialog( "Parsing modules...","+" )
+	dialog.MinSize=New Vec2i( 256,128 )
+	dialog.Open()
+	
+	Local onParse:=Lambda( file:String )
+		dialog.Text=StripExt( StripDir( file ) )+"~n~nYou can work while parsing."
+	End
+	
+	Monkey2Parser.OnParseModule+=onParse
+	
+	Monkey2Parser.OnDoneParseModules += Lambda()
+		dialog.Close()
+		Monkey2Parser.OnParseModule-=onParse
+	End
+	#end
+	
+	For Local plugin:=Eachin Plugin.PluginsOfType<Plugin>()
+		PluginBridge.OnCreate(plugin)
+	Next
+	
+End
+
+
+Class PluginBridge Extends Plugin
+
+	Function OnCreate(plugin:Plugin)
+		plugin.OnCreate() 'use protected method
+	End
+	
+End

+ 85 - 0
Plugin.monkey2

@@ -0,0 +1,85 @@
+
+Namespace ted2go
+
+
+Class Plugin
+
+	Property Name:String() Virtual
+	
+		Return "<untitled plugin>"
+	End
+	
+	Function PluginsOfType<T>:T[]() Where T Extends Plugin
+		
+		Return Plugins<T>.Plugins().ToArray()
+	End
+	
+	
+	Protected
+	
+	Method New()
+
+		AddPlugin( Self )
+	End
+	
+	Method AddPlugin<T>( plugin:T ) Where T Extends Plugin
+	
+		Plugins<T>.Plugins().Add( plugin )
+	End
+	
+	Method OnCreate() Virtual
+	
+	End
+
+
+	Private
+	
+	Struct Plugins<T>
+		Global _plugins:Stack<T>
+		
+		Function Plugins:Stack<T>()
+			If Not _plugins _plugins=New Stack<T>
+			Return _plugins
+		End
+	End
+
+End
+
+
+Class PluginDependsOnFileType Extends Plugin Implements IDependsOnFileType
+
+	Property Name:String() Override
+		Return "PluginDependsOnFileType"
+	End
+	
+	Method New()
+		_types = New String[]("*")
+	End
+	
+	Method GetFileTypes:String[]() Virtual
+		Return _types
+	End
+	
+	Method GetMainFileType:String() Virtual
+		Return _types[0]
+	End
+
+	Method CheckFileTypeSuitability:Bool( fileType:String )
+		If GetMainFileType() = "*" Return True 'any files
+		Return Utils.ArrayContains( GetFileTypes(),fileType )
+	End
+	
+	
+	Protected
+	
+	Field _types:String[]
+			
+End
+
+
+Interface IDependsOnFileType
+
+	Method GetFileTypes:String[]()
+	Method GetMainFileType:String()
+	
+End

+ 219 - 0
Prefs.monkey2

@@ -0,0 +1,219 @@
+Namespace ted2go
+
+
+Const Prefs:=New PrefsInstance
+
+Class PrefsInstance
+	
+	' AutoCompletion
+	Field AcEnabled:=True
+	Field AcKeywordsOnly:=False
+	Field AcShowAfter:=2
+	Field AcUseTab:=True
+	Field AcUseEnter:=False
+	Field AcUseSpace:=False
+	Field AcUseDot:=False
+	Field AcNewLineByEnter:=True
+	Field AcStrongFirstChar:=True
+	Field AcUseLiveTemplates:=True
+	'
+	Field MainToolBarVisible:=True
+	Field MainProjectIcons:=True
+	'
+	Field IrcNickname:String
+	Field IrcServer:="irc.freenode.net"
+	Field IrcPort:=6667
+	Field IrcRooms:="#monkey2" '#mojox#mojo2d
+	Field IrcConnect:Bool=False
+	'
+	Field EditorToolBarVisible:=False
+	Field EditorGutterVisible:=True
+	Field EditorShowWhiteSpaces:=False
+	Field EditorFontPath:String
+	Field EditorFontSize:=16
+	Field EditorShowEvery10LineNumber:=True
+	Field EditorCodeMapVisible:=True
+	Field EditorAutoIndent:=True
+	Field EditorAutoPairs:=True
+	Field EditorSurroundSelection:=True
+	'
+	Field SourceSortByType:=True
+	Field SourceShowInherited:=False
+	'
+	Field MonkeyRootPath:String
+	Field IdeHomeDir:String
+	'	
+	Field SiblyMode:Bool
+	
+	Property FindFilesFilter:String()
+		Return _findFilter
+	Setter( value:String )
+		
+		_findFilter=value
+		SaveLocalState()
+	End
+	
+	Method LoadState( json:JsonObject )
+		
+		If json.Contains( "irc" )
+			
+			Local j2:=json["irc"].ToObject()
+			IrcNickname=Json_GetString( j2,"nickname",IrcNickname )
+			IrcServer=Json_GetString( j2,"server",IrcServer )
+			IrcPort=Json_GetInt( j2,"port",IrcPort )
+			IrcRooms=Json_GetString( j2,"rooms",IrcRooms )
+			IrcConnect=Json_GetBool( j2,"connect",IrcConnect )
+			
+		Endif
+		
+		If json.Contains( "main" )
+			
+			Local j2:=json["main"].ToObject()
+			MainToolBarVisible=Json_GetBool( j2,"toolBarVisible",MainToolBarVisible )
+			MainProjectIcons=Json_GetBool( j2,"projectIcons",MainProjectIcons )
+      
+		Endif
+		
+		If json.Contains( "completion" )
+		
+			Local j2:=json["completion"].ToObject()
+			AcEnabled=j2["enabled"].ToBool()
+			AcKeywordsOnly=j2["keywordsOnly"].ToBool()
+			AcShowAfter=j2["showAfter"].ToNumber()
+			AcUseTab=j2["useTab"].ToBool()
+			AcUseEnter=j2["useEnter"].ToBool()
+			AcUseSpace=Json_GetBool( j2,"useSpace",AcUseSpace )
+			AcUseDot=Json_GetBool( j2,"useDot",AcUseDot )
+			AcNewLineByEnter=Json_GetBool( j2,"newLineByEnter",AcNewLineByEnter )
+			AcUseLiveTemplates=Json_GetBool( j2,"useLiveTemplates",AcUseLiveTemplates )
+			
+		Endif
+		
+		If json.Contains( "editor" )
+		
+			Local j2:=json["editor"].ToObject()
+			EditorToolBarVisible=j2["toolBarVisible"].ToBool()
+			EditorGutterVisible=j2["gutterVisible"].ToBool()
+			EditorShowWhiteSpaces=Json_GetBool( j2,"showWhiteSpaces",EditorShowWhiteSpaces )
+			EditorFontPath=Json_GetString( j2,"fontPath", EditorFontPath )
+			EditorFontSize=Json_GetInt( j2,"fontSize",EditorFontSize )
+			EditorShowEvery10LineNumber=Json_GetBool( j2,"showEvery10",EditorShowEvery10LineNumber )
+			EditorCodeMapVisible=Json_GetBool( j2,"codeMapVisible",EditorCodeMapVisible )
+			EditorAutoIndent=Json_GetBool( j2,"autoIndent",EditorAutoIndent )
+			EditorAutoPairs=Json_GetBool( j2,"autoPairs",EditorAutoPairs )
+			EditorSurroundSelection=Json_GetBool( j2,"surroundSelection",EditorSurroundSelection )
+			
+		Endif
+		
+		If json.Contains( "source" )
+		
+			Local j2:=json["source"].ToObject()
+			SourceSortByType=j2["sortByType"].ToBool()
+			SourceShowInherited=j2["showInherited"].ToBool()
+			
+		Endif
+		
+		If json.Contains( "siblyMode" )
+		
+			SiblyMode=json["siblyMode"].ToBool()
+		End
+	
+	End
+	
+	Method SaveState( json:JsonObject )
+		
+		Local j:=New JsonObject
+		json["main"]=j
+		j["toolBarVisible"]=New JsonBool( MainToolBarVisible )
+		j["projectIcons"]=New JsonBool( MainProjectIcons )
+		
+		j=New JsonObject
+		json["irc"]=j
+		j["nickname"]=New JsonString( IrcNickname )
+		j["server"]=New JsonString( IrcServer )
+		j["port"]=New JsonNumber( IrcPort )
+		j["rooms"]=New JsonString( IrcRooms )
+		j["connect"]=New JsonBool( IrcConnect )
+		
+		j=New JsonObject
+		json["completion"]=j
+		j["enabled"]=New JsonBool( AcEnabled )
+		j["keywordsOnly"]=New JsonBool( AcKeywordsOnly )
+		j["showAfter"]=New JsonNumber( AcShowAfter )
+		j["useTab"]=New JsonBool( AcUseTab )
+		j["useEnter"]=New JsonBool( AcUseEnter )
+		j["useSpace"]=New JsonBool( AcUseSpace )
+		j["useDot"]=New JsonBool( AcUseDot )
+		j["newLineByEnter"]=New JsonBool( AcNewLineByEnter )
+		j["useLiveTemplates"]=New JsonBool( AcUseLiveTemplates )
+		
+		j=New JsonObject
+		json["editor"]=j
+		j["toolBarVisible"]=New JsonBool( EditorToolBarVisible )
+		j["gutterVisible"]=New JsonBool( EditorGutterVisible )
+		j["showWhiteSpaces"]=New JsonBool( EditorShowWhiteSpaces )
+		j["fontPath"]=New JsonString( EditorFontPath )
+		j["fontSize"]=New JsonNumber( EditorFontSize )
+		j["showEvery10"]=New JsonBool( EditorShowEvery10LineNumber )
+		j["codeMapVisible"]=New JsonBool( EditorCodeMapVisible )
+		j["autoIndent"]=New JsonBool( EditorAutoIndent )
+		j["autoPairs"]=New JsonBool( EditorAutoPairs )
+		j["surroundSelection"]=New JsonBool( EditorSurroundSelection )
+		
+		j=New JsonObject
+		json["source"]=j
+		j["sortByType"]=New JsonBool( SourceSortByType )
+		j["showInherited"]=New JsonBool( SourceShowInherited )
+		
+		If "SiblyMode" json["siblyMode"]=JsonBool.TrueValue
+		
+	End
+	
+	Method LoadLocalState()
+		
+		IdeHomeDir=HomeDir()+"Ted2Go/"
+		CreateDir( IdeHomeDir )
+		
+		Local json:=JsonObject.Load( AppDir()+"state.json" )
+		If Not json Return
+		
+		MonkeyRootPath=Json_GetString( json.Data,"rootPath","" )
+		If Not MonkeyRootPath.EndsWith( "/" ) Then MonkeyRootPath+="/"
+		
+		FindFilesFilter=Json_GetString( json.Data,"findFilesFilter","monkey2,txt" )
+	End
+	
+	Method SaveLocalState()
+		
+		If Not MonkeyRootPath.EndsWith( "/" ) Then MonkeyRootPath+="/"
+		
+		Local json:=New JsonObject
+		json["rootPath"]=New JsonString( MonkeyRootPath )
+		json["findFilesFilter"]=New JsonString( FindFilesFilter )
+		json.Save( AppDir()+"state.json" )
+		
+	End
+	
+	Method GetCustomFontPath:String()
+		
+		If Not EditorFontPath Return ""
+		If Not EditorFontPath.Contains( ".ttf" ) Return ""
+		
+		Local path:=EditorFontPath
+		If Not path.Contains( ":" ) 'relative asset path
+			path=AssetsDir()+path
+		Endif
+		
+		Return path
+	End
+	
+	Method GetCustomFontSize:Int()
+	
+		Return Max( EditorFontSize,6 ) '6 is a minimum
+	End
+	
+	Private 
+	
+	Field _findFilter:String
+	
+End

+ 211 - 0
ProcessReader.monkey2

@@ -0,0 +1,211 @@
+
+Namespace ted2go
+
+
+#rem monkeydoc The ProcessReader class.
+
+Allow us to read output from process.
+We can reuse this class with any commands.
+Each command starts new process.
+You should to wait until work is finished - if you run while process already running then nothing happen.
+
+There are 2 usage scenarios: RunAsync and Run.
+
+With RunAsync we get output by PortionRead and Finished events.
+This is not blocked method.
+
+With Run we get output as result of this call.
+This is blocked method.
+
+Both methods are using Fiber to waiting process finished.
+#end
+Class ProcessReader
+	
+	#rem monkeydoc Tag to identify reader.
+	#end
+	Field Tag:=""
+	
+	#rem monkeydoc Invoked when a process finishes execution.
+	#end
+	Field Finished:Void( output:String,exitCode:Int )
+	
+	#rem monkeydoc Invoked when read portion of output from process.
+	#end
+	Field PortionRead:Void( output:String )
+	
+	#rem monkeydoc Invoked when a process finishes execution AND exitCode <> 0.
+	#end
+	Field Error:Void( exitCode:Int )
+	
+	#rem monkeydoc Obtain a reader instance.
+	#end
+	Method New( tag:String="" )
+	
+		Tag=tag
+		_items.Add( Self )
+	End
+	
+	Function StopAll()
+	
+		For Local r:=Eachin _items
+			r.Stop()
+		Next
+	End
+	
+	#rem monkeydoc
+	#end
+	Function WaitingForStopAll( wait:Future<Bool> )
+		
+		_stopSize=0
+		_stopCounter=0
+		
+		For Local r:=Eachin _items
+			If r.IsRunning
+				_stopSize+=1
+				r.Finished+=Lambda( s:String,c:Int )
+					_stopCounter+=1
+					If _stopCounter=_stopSize Then wait.Set( True )
+				End
+			Endif
+		Next
+		If _stopSize=0
+			wait.Set( True )
+			Return
+		Endif
+	End
+	
+	#rem monkeydoc Async reading of process. You should to subscribe on (at least) Finished event to get result.
+	This method can be used without creation of new Fiber.
+	If started while process already running - nothing happen.
+	#end
+	Method RunAsync( command:String )
+		
+		If _running Return
+		
+		New Fiber( Lambda()
+		
+			RunInternal( command )
+		End )
+	End
+	
+	#rem monkeydoc Sync reading of process.
+	This method must be used with creation of new Fiber, because it uses Future to waiting for process finished.
+	Return full output of a process.
+	If started while process already running - immediately return an empty string.
+	#end
+	Method Run:String( command:String )
+	
+		If _running Return ""
+	
+		Return RunInternal( command )
+	End
+	
+	#rem monkeydoc Terminate process execution.
+	#end
+	Method Stop()
+		
+		If Not _procOpen
+'			If _stdoutWaiting
+'				_stdoutWaiting.Set( False )
+'			Endif
+			Return
+		Endif
+		
+		_process.Terminate()
+		
+		OnStop()
+	End
+	
+	#rem monkeydoc Is reading currently in progress.
+	#end
+	Property IsRunning:Bool()
+	
+		Return _running
+	End
+	
+	
+	Private
+	
+	Field _process:Process
+	Field _output:String
+	Field _running:Bool
+	Field _stdoutWaiting:Future<Bool>
+	Field _stdoutOpen:Bool,_procOpen:Bool
+	Global _items:=New Stack<ProcessReader>
+	Global _stopSize:Int,_stopCounter:Int
+	
+	Method RunInternal:String( cmd:String )
+	
+		If Not Start( cmd )
+			Print "Failed to start process '"+cmd+"'"
+			Return ""
+		Endif
+		
+		' waiting for the end
+		_stdoutWaiting=New Future<Bool>
+		_stdoutWaiting.Get()
+		_stdoutWaiting=Null
+		
+		Return _output
+	End
+	
+	Method Start:Bool( cmd:String )
+		
+		If _running Return False
+		
+		Local process:=New Process
+	
+		process.Finished=Lambda()
+			'Print "proc.finished: "+Tag
+			_procOpen=False
+			UpdateRunning()
+		End
+		
+		process.StdoutReady=Lambda()
+			'Print "proc.stdoutReady: "+Tag
+			Local stdout:=process.ReadStdout()
+			
+			If stdout
+				stdout=stdout.Replace( "~r~n","~n" ).Replace( "~r","~n" )
+				_output+=stdout
+				PortionRead( stdout )
+			Else
+				_stdoutOpen=False
+				UpdateRunning()
+			Endif
+		End
+		
+		If Not process.Start( cmd ) Return False
+		
+		_process=process
+		_running=True
+		_procOpen=True
+		_stdoutOpen=True
+		_output=""
+		
+		Return True
+	End
+	
+	Method UpdateRunning()
+	
+		If Not _running Or _procOpen Or _stdoutOpen Return
+	
+		OnStop()
+		
+		Local code:=_process.ExitCode
+		
+		Finished( _output,code )
+		If code<>0 Then Error( code )
+		
+		If _stdoutWaiting
+			_stdoutWaiting.Set( True )
+		Endif
+	End
+	
+	Method OnStop()
+		
+		_running=False
+		_items.Remove( Self )
+	End
+	
+End

+ 38 - 0
README.md

@@ -0,0 +1,38 @@
+# Ted2Go
+An IDE for Monkey2 programming language.
+
+Binaries for MacOS and Windows are available at [itch.io](https://nerobot.itch.io/ted2go).
+
+## Benefits & Goals
+* Autocompletion for keywords, modules and user's code (WIP).
+* On-the-fly parser - see errors w/o build (not all errors).
+* "Find in project" dialog.
+* CodeTree and NavigationList for comfortable code jumping (todo).
+* Code folding and bookmarks (todo).
+* Doc's hints directly inside of code area (todo).
+
+## More info
+Discuss on [forum page](http://monkeycoder.co.nz/forums/topic/ted2go-fork/).
+
+## Monkey <-> money :)
+Support me if you like this project:
+* [PayPal](https://paypal.me/engor)
+* Payed downloading [from itch.io](https://nerobot.itch.io/ted2go)
+
+## Notes for contributors
+Please, take a look at code style. It based on original Ted2.
+
+Will be super-cool if you can write the same style to make this project consistent.
+
+`Local abc:="ABC"` ' there is no spaces in assignment
+
+`digit=8`
+
+`callSomeMethod( param1,param2 )` 'there are spaces in bracket bounds
+
+```
+Method check:Bool( value:Double ) 'spaces in declaration
+                          ' empty line after method name (can ignore if there is one-line body)
+   Return value > 1.75
+End
+```

+ 292 - 0
Ted2.monkey2

@@ -0,0 +1,292 @@
+
+#If __TARGET__="windows"
+
+#Import "bin/wget.exe"
+
+'to build resource.o when icon changes...
+'
+'windres resource.rc resource.o
+
+#Import "logo/resource.o"
+
+#Endif
+
+'----------------------------
+
+'#Import "<reflection>"
+
+#Import "<std>"
+#Import "<mojo>"
+#Import "<mojox>"
+#Import "<tinyxml2>"
+
+#Import "action/FileActions"
+#Import "action/EditActions"
+#Import "action/BuildActions"
+#Import "action/HelpActions"
+#Import "action/FindActions"
+#Import "action/ViewActions"
+
+#Import "dialog/FindDialog"
+#Import "dialog/PrefsDialog"
+#Import "dialog/EditProductDialog"
+#Import "dialog/DialogExt"
+#Import "dialog/NoTitleDialog"
+#Import "dialog/FindInFilesDialog"
+#Import "dialog/UpdateModulesDialog"
+#Import "dialog/GenerateClassDialog"
+#Import "dialog/LiveTemplateDialog"
+
+#Import "document/DocumentManager"
+#Import "document/Ted2Document"
+#Import "document/CodeDocument"
+#Import "document/PlainTextDocument"
+#Import "document/ImageDocument"
+#Import "document/AudioDocument"
+#Import "document/JsonDocument"
+#Import "document/XmlDocument"
+#Import "document/BananasDocument"
+#Import "document/SceneDocument"
+
+#Import "eventfilter/TextViewKeyEventFilter"
+#Import "eventfilter/Monkey2KeyEventFilter"
+
+#Import "parser/CodeItem"
+#Import "parser/Parser"
+#Import "parser/Monkey2Parser"
+#Import "parser/ParserPlugin"
+
+#Import "product/BuildProduct"
+#Import "product/Mx2ccEnv"
+#Import "product/ModuleManager"
+
+#Import "syntax/Keywords"
+#Import "syntax/Monkey2Keywords"
+#Import "syntax/Highlighter"
+#Import "syntax/Monkey2Highlighter"
+#Import "syntax/CppHighlighter"
+#Import "syntax/CppKeywords"
+#Import "syntax/GlslHighlighter"
+#Import "syntax/GlslKeywords"
+#Import "syntax/CodeFormatter"
+#Import "syntax/Monkey2Formatter"
+
+#Import "testing/ParserTests"
+
+#Import "utils/JsonUtils"
+#Import "utils/Utils"
+
+#Import "view/IRCView"
+#Import "view/CodeMapView"
+#Import "view/CodeTextView"
+#Import "view/ConsoleViewExt"
+#Import "view/ListViewExt"
+#Import "view/AutocompleteView"
+#Import "view/CodeTreeView"
+#Import "view/TreeViewExt"
+#Import "view/FileBrowserExt"
+#Import "view/CodeGutterView"
+#Import "view/ToolBarViewExt"
+#Import "view/HintView"
+#Import "view/HtmlViewExt"
+#Import "view/ProjectBrowserView"
+#Import "view/TabViewExt"
+#Import "view/StatusBarView"
+#Import "view/DebugView"
+#Import "view/ProjectView"
+#Import "view/HelpTreeView"
+#Import "view/Ted2TextView"
+#Import "view/Ted2CodeTextView"
+#Import "view/JsonTreeView"
+#Import "view/XmlTreeView"
+#Import "view/Monkey2TreeView"
+#Import "view/GutterView"
+#Import "view/MenuExt"
+#Import "view/ScrollableViewExt"
+#Import "view/BuildErrorListViewItem"
+#Import "view/TextFieldExt"
+#Import "view/SpacerView"
+#Import "view/FindReplaceView"
+#Import "view/ViewExtensions"
+#Import "view/DockingViewExt"
+
+#Import "Tuple"
+#Import "Plugin"
+#Import "ThemeImages"
+#Import "Prefs"
+#Import "ProcessReader"
+#Import "LiveTemplates"
+#Import "DraggableTabs"
+#Import "MainWindow"
+
+
+Namespace ted2go
+
+Using std..
+Using mojo..
+Using mojox..
+Using tinyxml2..
+
+
+Const MONKEY2_DOMAIN:="http://monkeycoder.co.nz"
+
+Global AppTitle:="Ted2Go v2.7"
+
+
+Function Main()
+
+	Prefs.LoadLocalState()
+	
+	Local root:=Prefs.MonkeyRootPath
+	If Not root Then root=AppDir()
+	
+	root=SetupMonkeyRootPath( root,True )
+	If Not root libc.exit_( 1 )
+	
+	If root<>Prefs.MonkeyRootPath
+		Prefs.MonkeyRootPath=root
+		Prefs.SaveLocalState()
+	Endif
+	
+	ChangeDir( root )
+	
+	'load ted2 state
+	'
+	Local jobj:=JsonObject.Load( "bin/ted2.state.json" )
+	If Not jobj jobj=New JsonObject
+
+	Prefs.LoadState( jobj )
+	
+	'initial theme
+	'
+	If Not jobj.Contains( "theme" ) jobj["theme"]=New JsonString( "theme-prime-blue" )
+
+	If Not jobj.Contains( "themeScale" ) jobj["themeScale"]=New JsonNumber( 1 )
+	
+	Local config:=New StringMap<String>
+	
+	config["initialTheme"]=jobj.GetString( "theme" )
+	config["initialThemeScale"]=jobj.GetNumber( "themeScale" )
+	
+	'start the app!
+	'
+	New AppInstance( config )
+	
+	'initial window state
+	'
+	Local flags:=WindowFlags.Resizable|WindowFlags.HighDPI
+
+	Local rect:Recti
+	
+	If jobj.Contains( "windowRect" ) 
+		rect=ToRecti( jobj["windowRect"] )
+	Else
+		Local w:=Min( 1380,App.DesktopSize.x-40 )
+		Local h:=Min( 970,App.DesktopSize.y-64 )
+		rect=New Recti( 0,0,w,h )
+		flags|=WindowFlags.Center
+	Endif
+
+	New MainWindowInstance( AppTitle,rect,flags,jobj )
+	
+	' open docs from args
+	Local args:=AppArgs()
+	For Local i:=1 Until args.Length
+		Local arg:=args[i]
+		arg=arg.Replace( "\","/" )
+		If GetFileType( arg ) = FileType.File
+			MainWindow.OpenDocument( arg )
+		Endif
+	Next
+	
+	App.Run()
+	
+End
+
+Function SetupMonkeyRootPath:String( rootPath:String,searchMode:Bool )
+	
+#If __DESKTOP_TARGET__
+
+	If searchMode
+		' search for desired folder
+		Local found:=FindBinFolder( rootPath )
+		' search for AddDir() folder
+		If Not found And rootPath<>AppDir() Then found=FindBinFolder( AppDir() )
+		' search for choosen-by-requester folder
+		While Not found
+	
+			Local ok:=Confirm( "Initializing","Monkey2 root directory isn't set.~nTo continue, you should to specify it." )
+			If Not ok
+				Return ""
+			End
+			Local s:=requesters.RequestDir( "Choose Monkey2 folder",AppDir() )
+			found=FindBinFolder( s )
+		Wend
+		
+		rootPath=found
+	Else
+		
+		Local ok:= (GetFileType( "bin" )=FileType.Directory And GetFileType( "modules" )=FileType.Directory)
+		If Not ok
+			Notify( "Monkey2 root folder","Incorrect folder!" )
+			Return ""
+		Endif
+		
+	Endif
+	
+#Endif
+	
+	Return rootPath
+End
+
+Function GetActionTextWithShortcut:String( action:Action )
+
+	Return action.Text+" ("+action.HotKeyText+")"
+End
+
+Function Exec( exePath:String,args:String="" )
+
+#If __HOSTOS__="windows"
+
+	libc.system( exePath+" "+args )
+	
+#Else If __HOSTOS__="macos"
+
+	libc.system( "open ~q"+exePath+"~q --args "+args )
+
+#Else If __HOSTOS__="linux"
+
+	libc.system( exePath+" "+args+" >/dev/null 2>/dev/null &" )
+
+#Else If __HOSTOS__="raspbian"
+
+	libc.system( exePath+" "+args+" >/dev/null 2>/dev/null &" )
+
+#Endif
+
+End
+
+
+Private
+
+Function FindBinFolder:String( startingFolder:String )
+	
+	Local cur:=CurrentDir()
+	Local ok:=True
+	ChangeDir( startingFolder )
+	
+	While GetFileType( "bin" )<>FileType.Directory Or GetFileType( "modules" )<>FileType.Directory
+	
+		If IsRootDir( CurrentDir() )
+			
+			ok=False
+			Exit
+		Endif
+	
+		ChangeDir( ExtractDir( CurrentDir() ) )
+	Wend
+	Local result:=ok ? CurrentDir() Else ""
+	ChangeDir( cur )
+	
+	Return result
+End

+ 50 - 0
ThemeImages.monkey2

@@ -0,0 +1,50 @@
+
+Namespace ted2go
+
+
+Class ThemeImages Extends Plugin
+
+	Property Name:String() Override
+		Return "ThemeImages Plugin"
+	End
+	
+	Function Get:Image( key:String )
+		
+		If Not _images.Contains(key)
+			Local img:=Image.Load( "theme::"+key )
+			If img Then img.Scale=App.Theme.Scale
+			_images[key]=img
+			Return img
+		Endif
+		Return _images[key]
+	End
+	
+	
+	Private
+	
+	Global _images:=New StringMap<Image>
+	Global _inst:=New ThemeImages
+	
+	Method New()
+	End
+	
+	Method OnCreate() Override
+		
+		App.ThemeChanged+=Lambda()
+			AdjustImagesScale()
+		End
+	End
+	
+	Function AdjustImagesScale()
+	
+		For Local key:=Eachin _images.Keys
+			Local img:=_images[key]
+			If img<>Null
+				img.Scale=App.Theme.Scale
+			Else
+				Print "ThemeImages.AdjustImagesScale: image is null: "+key
+			Endif
+		Next
+	End
+	
+End

+ 99 - 0
Tuple.monkey2

@@ -0,0 +1,99 @@
+
+Namespace ted2go
+
+
+Class Tuple Abstract
+
+End
+
+'---------------------------
+' Tuple 2
+'---------------------------
+
+Class Tuple2<T1,T2> Extends Tuple Final
+	
+	Method New( item1:T1,item2:T2 )
+		
+		_i1=item1
+		_i2=item2
+	End
+	
+	Property Item1:T1()
+		Return _i1
+	End
+	
+	Property Item2:T2()
+		Return _i2
+	End
+	
+	Private
+	
+	Field _i1:T1,_i2:T2
+End
+
+
+'---------------------------
+' Tuple 3
+'---------------------------
+
+Class Tuple3<T1,T2,T3> Extends Tuple Final
+	
+	Method New( item1:T1,item2:T2,item3:T3 )
+		
+		_i1=item1
+		_i2=item2
+		_i3=item3
+	End
+	
+	Property Item1:T1()
+		Return _i1
+	End
+	
+	Property Item2:T2()
+		Return _i2
+	End
+	
+	Property Item3:T3()
+		Return _i3
+	End
+	
+	Private
+	
+	Field _i1:T1,_i2:T2,_i3:T3
+End
+
+
+'---------------------------
+' Tuple 4
+'---------------------------
+
+Class Tuple4<T1,T2,T3,T4> Extends Tuple Final
+	
+	Method New( item1:T1,item2:T2,item3:T3,item4:T4 )
+		
+		_i1=item1
+		_i2=item2
+		_i3=item3
+		_i4=item4
+	End
+	
+	Property Item1:T1()
+		Return _i1
+	End
+	
+	Property Item2:T2()
+		Return _i2
+	End
+	
+	Property Item3:T3()
+		Return _i3
+	End
+	
+	Property Item4:T4()
+		Return _i4
+	End
+	
+	Private
+	
+	Field _i1:T1,_i2:T2,_i3:T3,_i4:T4
+End

+ 668 - 0
action/BuildActions.monkey2

@@ -0,0 +1,668 @@
+
+Namespace ted2go
+
+
+Class BuildError
+
+	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:BuildError )
+		If line<err.line Return -1
+		If line>err.line Return 1
+		Return 0
+	End
+	
+End
+
+
+Interface IModuleBuilder
+	
+	Method BuildModules:Bool( clean:Bool,modules:String="",configs:String="debug release" )
+	
+End
+
+
+Class BuildActions Implements IModuleBuilder
+
+	Field buildAndRun:Action
+	Field debugApp:Action
+	Field build:Action
+	Field semant:Action
+	Field buildSettings:Action
+	Field nextError:Action
+	Field lockBuildFile:Action
+	Field updateModules:Action
+	Field moduleManager:Action
+	Field rebuildHelp:Action
+	
+	Field targetMenu:MenuExt
+	
+	
+	Field PreBuild:Void()
+	Field PreSemant:Void()
+	Field PreBuildModules:Void()
+	Field ErrorsOccured:Void(errors:BuildError[])
+	
+	Method New( docs:DocumentManager,console:ConsoleExt,debugView:DebugView )
+	
+		_docs=docs
+		_console=console
+		_debugView=debugView
+		
+		_docs.DocumentRemoved+=Lambda( doc:Ted2Document )
+
+			If doc=_locked _locked=Null
+		End
+		
+		buildAndRun=New Action( "Run" )
+#If __TARGET__="macos"
+		buildAndRun.HotKey=Key.R
+		buildAndRun.HotKeyModifiers=Modifier.Menu
+#Else
+		buildAndRun.HotKey=Key.F5
+#Endif
+		buildAndRun.Triggered=OnBuildAndRun
+		
+		debugApp=New Action( "Debug" )
+#If __TARGET__="macos"
+		debugApp.HotKey=Key.D
+		debugApp.HotKeyModifiers=Modifier.Menu
+#Else
+		debugApp.HotKey=Key.F8
+#Endif
+		debugApp.Triggered=OnDebugApp
+
+		build=New Action( "Build" )
+#If __TARGET__="macos"
+		build.HotKey=Key.B
+		build.HotKeyModifiers=Modifier.Menu
+#Else
+		build.HotKey=Key.F6
+#Endif
+		build.Triggered=OnBuild
+		
+		semant=New Action( "Check" )
+#If __TARGET__="macos"
+		semant.HotKey=Key.R
+		semant.HotKeyModifiers=Modifier.Menu|Modifier.Shift
+#Else
+		semant.HotKey=Key.F7
+#Endif
+		semant.Triggered=OnSemant
+		
+		buildSettings=New Action( "Product settings..." )
+		buildSettings.Triggered=OnBuildFileSettings
+		
+		nextError=New Action( "Next build error" )
+		nextError.Triggered=OnNextError
+		nextError.HotKey=Key.F4
+		
+		lockBuildFile=New Action( "Lock build file" )
+		lockBuildFile.Triggered=LockBuildFile
+		lockBuildFile.HotKey=Key.L
+		lockBuildFile.HotKeyModifiers=Modifier.Menu
+		
+		updateModules=New Action( "Update / Rebuild modules..." )
+		updateModules.Triggered=OnUpdateModules
+		updateModules.HotKey=Key.U
+		updateModules.HotKeyModifiers=Modifier.Menu
+		
+		moduleManager=New Action( "Module manager..." )
+		moduleManager.Triggered=OnModuleManager
+		
+		rebuildHelp=New Action( "Rebuild documentation" )
+		rebuildHelp.Triggered=OnRebuildHelp
+		
+		local group:=New CheckGroup
+		_debugConfig=New CheckButton( "Debug",,group )
+		_debugConfig.Layout="fill-x"
+		_releaseConfig=New CheckButton( "Release",,group )
+		_releaseConfig.Layout="fill-x"
+		_debugConfig.Clicked+=Lambda()
+			_buildConfig="debug"
+		End
+		_releaseConfig.Clicked+=Lambda()
+			_buildConfig="release"
+		End
+		_buildConfig="debug"
+
+		group=New CheckGroup
+
+		_desktopTarget=New CheckButton( "Desktop",,group )
+		_desktopTarget.Layout="fill-x"
+		
+		_emscriptenTarget=New CheckButton( "Emscripten",,group )
+		_emscriptenTarget.Layout="fill-x"
+		
+		_androidTarget=New CheckButton( "Android",,group )
+		_androidTarget.Layout="fill-x"
+		
+		_iosTarget=New CheckButton( "iOS",,group )
+		_iosTarget.Layout="fill-x"
+		
+		targetMenu=New MenuExt( "Build target" )
+		targetMenu.AddView( _debugConfig )
+		targetMenu.AddView( _releaseConfig )
+		targetMenu.AddSeparator()
+		targetMenu.AddView( _desktopTarget )
+		targetMenu.AddView( _emscriptenTarget )
+		targetMenu.AddView( _androidTarget )
+		targetMenu.AddView( _iosTarget )
+		targetMenu.AddSeparator()
+		targetMenu.AddAction( buildSettings )
+		
+		'check valid targets...WIP...
+		
+		_validTargets=EnumValidTargets( _console )
+		
+		If _validTargets _buildTarget=_validTargets[0].ToLower()
+		
+		If _validTargets.Contains( "desktop" )
+			_desktopTarget.Clicked+=Lambda()
+				_buildTarget="desktop"
+			End
+		Else
+			_desktopTarget.Enabled=False
+		Endif
+		
+		If _validTargets.Contains( "emscripten" )
+			_emscriptenTarget.Clicked+=Lambda()
+				_buildTarget="emscripten"
+			End
+		Else
+			_emscriptenTarget.Enabled=False
+		Endif
+
+		If _validTargets.Contains( "android" )
+			_androidTarget.Clicked+=Lambda()
+				_buildTarget="android"
+			End
+		Else
+			_androidTarget.Enabled=False
+		Endif
+
+		If _validTargets.Contains( "ios" )
+			_iosTarget.Clicked+=Lambda()
+				_buildTarget="ios"
+			End
+		Else
+			_iosTarget.Enabled=False
+		Endif
+	End
+	
+	Property LockedDocument:CodeDocument()
+	
+		Return _locked
+	End
+	
+	Method LockBuildFile()
+		
+		Local doc:=Cast<CodeDocument>( _docs.CurrentDocument )
+		OnLockBuildFile( doc )
+	End
+	
+	Method SaveState( jobj:JsonObject )
+		
+		If _locked jobj["lockedDocument"]=New JsonString( _locked.Path )
+		
+		jobj["buildConfig"]=New JsonString( _buildConfig )
+		
+		jobj["buildTarget"]=New JsonString( _buildTarget )
+	End
+		
+	Method LoadState( jobj:JsonObject )
+	
+		If jobj.Contains( "lockedDocument" )
+			Local path:=jobj["lockedDocument"].ToString()
+			_locked=Cast<CodeDocument>( _docs.FindDocument( path ) )
+			If _locked Then SetLockedState( _locked,True )
+		Endif
+		
+		If jobj.Contains( "buildConfig" )
+			_buildConfig=jobj["buildConfig"].ToString()
+			Select _buildConfig
+			Case "release"
+				_releaseConfig.Checked=True
+			Default
+				_debugConfig.Checked=True
+				_buildConfig="debug"
+			End
+		Endif
+		
+		If jobj.Contains( "buildTarget" )
+					
+			local target:=jobj["buildTarget"].ToString()
+
+			If _validTargets.Contains( target )
+			
+				 _buildTarget=target
+				
+				Select _buildTarget
+				Case "desktop"
+					_desktopTarget.Checked=True
+				Case "emscripten"
+					_emscriptenTarget.Checked=True
+				Case "android"
+					_androidTarget.Checked=True
+				Case "ios"
+					_iosTarget.Checked=True
+				End
+			
+			Endif
+			
+		Endif
+		
+	End
+	
+	Method Update()
+	
+		While Not _errors.Empty And _errors.First.removed
+			_errors.RemoveFirst()
+		Wend
+	
+		Local idle:=Not _console.Running
+		Local canbuild:=idle And BuildDoc()<>Null And _buildTarget
+		
+		build.Enabled=canbuild
+		buildAndRun.Enabled=canbuild
+		nextError.Enabled=Not _errors.Empty
+		updateModules.Enabled=idle
+		rebuildHelp.Enabled=idle
+		moduleManager.Enabled=idle
+	End
+
+	Method BuildModules:Bool( clean:Bool,modules:String="",configs:String="debug release" )
+	
+		Local dialog:=New UpdateModulesDialog( _validTargets,modules,configs,clean )
+		dialog.Title="Update / Rebuild modules"
+		
+		Local ok:=dialog.ShowModal()
+		If Not ok Return False
+		
+		Local result:=True
+		
+		Local targets:=dialog.SelectedTargets
+		modules=dialog.SelectedModules
+		
+		clean=dialog.NeedClean
+		configs=dialog.SelectedConfigs
+		
+		Local time:=Millisecs()
+		
+		For Local target:=Eachin targets
+			result=BuildModules( clean,target,modules,configs )
+			If result=False Exit
+		Next
+		
+		time=Millisecs()-time
+		Local prefix:=clean ? "Rebuild" Else "Update"
+		
+		If result
+			_console.Write( "~n"+prefix+" modules completed successfully!~n" )
+		Else
+			_console.Write( "~n"+prefix+" modules failed.~n" )
+		Endif
+		_console.Write( "Total time elapsed: "+FormatTime( time )+".~n" )
+		
+		Return result
+	End
+	
+	Method GotoError( err:BuildError )
+	
+		Local doc:=Cast<CodeDocument>( _docs.OpenDocument( err.path,True ) )
+		If Not doc Return
+	
+		Local tv := doc.CodeView
+		If Not tv Return
+	
+		MainWindow.UpdateWindow( False )
+	
+		tv.GotoPosition( New Vec2i( err.line,0 ) )
+	End
+	
+	
+	Private
+	
+	Field _docs:DocumentManager
+	Field _console:ConsoleExt
+	Field _debugView:DebugView
+	
+	Field _locked:CodeDocument
+	
+	Field _errors:=New List<BuildError>
+	
+	Field _buildConfig:String
+	Field _buildTarget:String
+	
+	Field _debugConfig:CheckButton
+	Field _releaseConfig:CheckButton
+	Field _desktopTarget:CheckButton
+	Field _emscriptenTarget:CheckButton
+	Field _androidTarget:CheckButton
+	Field _iosTarget:CheckButton
+	
+	Field _validTargets:StringStack
+	Field _timing:Long
+	
+	
+	Method BuildDoc:CodeDocument()
+		
+		If Not _locked Return Cast<CodeDocument>( _docs.CurrentDocument )
+		
+		Return _locked
+	End
+	
+	Method SaveAll:Bool( buildFile:String )
+		
+		Local proj:=ProjectView.FindProjectByFile( buildFile )
+		
+		For Local doc:=Eachin _docs.OpenDocuments
+			' save docs only for built project
+			If proj And Not doc.Path.StartsWith( proj ) Continue
+			If Not doc.Save() Return False
+		Next
+		
+		Return True
+	End
+	
+	Method ClearErrors()
+	
+		_errors.Clear()
+	
+		For Local doc:=Eachin _docs.OpenDocuments
+			Local mx2Doc:=Cast<CodeDocument>( doc )
+			If mx2Doc mx2Doc.Errors.Clear()
+		Next
+
+	End
+
+	Method BuildMx2:Bool( cmd:String,progressText:String,action:String="build",buildFile:String="",showElapsedTime:Bool=False )
+	
+		ClearErrors()
+		
+		_console.Clear()
+		
+		MainWindow.StoreConsoleVisibility()
+		
+		MainWindow.ShowBuildConsole()
+		
+		If Not SaveAll( buildFile ) Return False
+		
+		_timing=Millisecs()
+		
+		If Not _console.Start( cmd )
+			Alert( "Failed to start process: '"+cmd+"'" )
+			Return False
+		Endif
+		
+		Local title := (action="semant") ? "Checking" Else "Building"
+		
+		Local s:=progressText
+		If Not s.EndsWith( "..." ) Then s+="..."
+		
+		MainWindow.ShowStatusBarText( s )
+		MainWindow.ShowStatusBarProgress( _console.Terminate )
+		
+		Local hasErrors:=False
+		
+		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
+					hasErrors=True
+					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 BuildError( path,line,msg )
+						Local doc:=Cast<CodeDocument>( _docs.OpenDocument( path,False ) )
+						
+						If doc
+							doc.AddError( err )
+							'If _errors.Empty
+							'	MainWindow.ShowBuildConsole( True )
+							'	GotoError( err )
+							'Endif
+							_errors.Add( err )
+						Endif
+						
+					Endif
+				Endif
+				If Not hasErrors
+					i=stdout.Find( "Build error: " )
+					hasErrors=(i<>-1)
+				Endif
+				
+			Endif
+			
+			_console.Write( stdout )
+		
+		Forever
+		
+		If Not _errors.Empty
+			ErrorsOccured( _errors.ToArray() )
+		Endif
+		
+		MainWindow.HideStatusBarProgress()
+		
+		Local status:=hasErrors ? "{0} failed. See the build console for details." Else (_console.ExitCode=0 ? "{0} finished." Else "{0} cancelled.")
+		status=status.Replace( "{0}",title )
+		
+		If showElapsedTime
+			Local elapsed:=(Millisecs()-_timing)
+			status+="   Time elapsed: "+FormatTime( elapsed )+"."
+		Endif
+		
+		MainWindow.ShowStatusBarText( status )
+		
+		Return _console.ExitCode=0
+	End
+
+	Method BuildModules:Bool( clean:Bool,target:String,modules:String,configs:String="debug release" )
+		
+		PreBuildModules()
+		
+		Local msg:=(clean ? "Rebuilding ~ " Else "Updating ~ ")+target
+		
+		Local arr:=configs.Split( " " )
+		For Local cfg:=Eachin arr
+		
+			'Local cfg:=(config ? "debug" Else "release")
+			
+			Local cmd:=MainWindow.Mx2ccPath+" makemods -target="+target
+			If clean cmd+=" -clean"
+			cmd+=" -config="+cfg
+			If modules Then cmd+=" "+modules
+			
+			Local s:=msg+" ~ "+cfg+" ~ ["
+			s+=modules ? modules Else "all modules"
+			s+="]..."
+			If Not BuildMx2( cmd,s ) Return False
+		Next
+		
+		Return True
+	End
+	
+	Method MakeDocs:Bool()
+	
+		Return BuildMx2( MainWindow.Mx2ccPath+" makedocs","Rebuilding documentation...","build","",True )
+	End
+	
+	Method BuildApp:Bool( config:String,target:String,sourceAction:String )
+	
+		Local buildDoc:=BuildDoc()
+		If Not buildDoc Return False
+		
+		Local product:=BuildProduct.GetBuildProduct( buildDoc.Path,target,False )
+		If Not product Return False
+		
+		Local opts:=product.GetMx2ccOpts()
+		
+		Local run:=(sourceAction="run")
+		
+		Local action:=sourceAction
+		If run Then action="build"
+
+		Local cmd:=MainWindow.Mx2ccPath+" makeapp -"+action+" "+opts
+		cmd+=" -config="+config
+		cmd+=" -target="+target
+		cmd+=" ~q"+buildDoc.Path+"~q"
+		
+		Local title := sourceAction="build" ? "Building" Else (sourceAction="run" ? "Running" Else "Checking")
+		Local msg:=title+" ~ "+target+" ~ "+config+" ~ "+StripDir( buildDoc.Path )
+		
+		If Not BuildMx2( cmd,msg,sourceAction,buildDoc.Path,True ) Return False
+		
+		_console.Write("~nDone.")
+		
+		If Not run
+			MainWindow.RestoreConsoleVisibility()
+			Return True
+		Endif
+		
+		Local exeFile:=product.GetExecutable()
+		If Not exeFile Return True
+		
+		Select target
+		Case "desktop"
+			
+			MainWindow.ShowStatusBarText( "   App is running now...",True )
+			MainWindow.SetStatusBarActive( True )
+			MainWindow.ShowStatusBarProgress( MainWindow.OnForceStop,True )
+			
+			_debugView.DebugApp( exeFile,config )
+
+		Case "emscripten"
+		
+			Local mserver:=GetEnv( "MX2_MSERVER" )
+			If mserver _console.Run( mserver+" ~q"+exeFile+"~q" )
+		
+		End
+		
+		Return True
+	End
+	
+	Method OnBuildAndRun()
+		
+		PreBuild()
+		
+		If _console.Running Return
+		
+		BuildApp( _buildConfig,_buildTarget,"run" )
+	End
+	
+	Method OnDebugApp()
+	
+		PreBuild()
+	
+		If _console.Running Return
+	
+		BuildApp( "debug",_buildTarget,"run" )
+	End
+	
+	Method OnBuild()
+		
+		PreBuild()
+		
+		If _console.Running Return
+	
+		BuildApp( _buildConfig,_buildTarget,"build" )
+	End
+	
+	Method OnSemant()
+	
+		PreSemant()
+		
+		If _console.Running Return
+	
+		BuildApp( _buildConfig,_buildTarget,"semant" )
+	End
+	
+	Method OnNextError()
+	
+		While Not _errors.Empty And _errors.First.removed
+			_errors.RemoveFirst()
+		Wend
+		
+		If _errors.Empty Return
+		
+		_errors.AddLast( _errors.RemoveFirst() )
+			
+		GotoError( _errors.First )
+	End
+	
+	Method OnLockBuildFile( doc:CodeDocument )
+	
+		If Not doc Return
+		
+		If _locked Then SetLockedState( _locked,False )
+		
+		If doc=_locked
+			_locked=Null
+			Return
+		Endif
+		
+		_locked=doc
+		SetLockedState( _locked,True )
+	End
+	
+	Method SetLockedState( doc:CodeDocument,locked:Bool )
+		
+		doc.State=locked ? "+" Else ""
+		Local tab:=_docs.FindTab( doc.View )
+		If tab Then tab.SetLockedState( locked )
+	End
+	
+	Method OnBuildFileSettings()
+
+		Local buildDoc:=BuildDoc()
+		If Not buildDoc Return
+		
+		local product:=BuildProduct.GetBuildProduct( buildDoc.Path,_buildTarget,True )
+	End
+	
+	Method OnUpdateModules()
+		
+		If _console.Running Return
+	
+		BuildModules( False )
+	End
+	
+	Method OnModuleManager()
+	
+		If _console.Running Return
+	
+		Local modman:=New ModuleManager( _console )
+		
+		modman.Open()
+	End
+	
+	Method OnRebuildHelp()
+	
+		If _console.Running Return
+	
+		MakeDocs()
+		
+		MainWindow.UpdateHelpTree()
+	End
+	
+End

+ 138 - 0
action/EditActions.monkey2

@@ -0,0 +1,138 @@
+
+Namespace ted2go
+
+
+Class EditActions
+
+	Field undo:Action
+	Field redo:Action
+	Field cut:Action
+	Field copy:Action
+	Field paste:Action
+	Field selectAll:Action
+	Field wordWrap:Action
+	
+	
+	Method New( docs:DocumentManager )
+	
+		_docs=docs
+		
+		undo=New Action( "Undo" )
+		undo.Triggered=OnUndo
+		undo.HotKey=Key.Z
+		undo.HotKeyModifiers=Modifier.Menu|Modifier.Ignore
+
+		redo=New Action( "Redo" )
+		redo.Triggered=OnRedo
+#If __TARGET__="macos"
+		redo.HotKey=Key.Z
+		redo.HotKeyModifiers=Modifier.Menu|Modifier.Ignore|Modifier.Shift
+#Else
+		redo.HotKey=Key.Y
+		redo.HotKeyModifiers=Modifier.Menu|Modifier.Ignore
+#Endif
+		
+		cut=New Action( "Cut" )
+		cut.Triggered=OnCut
+		cut.HotKey=Key.X
+		cut.HotKeyModifiers=Modifier.Menu|Modifier.Ignore
+
+		copy=New Action( "Copy" )
+		copy.Triggered=OnCopy
+		copy.HotKey=Key.C
+		copy.HotKeyModifiers=Modifier.Menu|Modifier.Ignore
+
+		paste=New Action( "Paste" )
+		paste.Triggered=OnPaste
+		paste.HotKey=Key.V
+		paste.HotKeyModifiers=Modifier.Menu|Modifier.Ignore
+
+		selectAll=New Action( "Select all" )
+		selectAll.Triggered=OnSelectAll
+		selectAll.HotKey=Key.A
+		selectAll.HotKeyModifiers=Modifier.Menu|Modifier.Ignore
+		
+		wordWrap=New Action( "Toggle word wrap" )
+		wordWrap.Triggered=OnWordWrap
+		wordWrap.HotKey=Key.Z
+		wordWrap.HotKeyModifiers=Modifier.Alt
+		
+	End
+	
+	Method Update()
+	
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		undo.Enabled=tv And tv.CanUndo
+		redo.Enabled=tv And tv.CanRedo
+		cut.Enabled=tv And tv.CanCut
+		copy.Enabled=tv And tv.CanCopy
+		paste.Enabled=tv And tv.CanPaste
+		selectAll.Enabled=tv
+	End
+	
+	Private
+	
+	Field _docs:DocumentManager
+	
+	Method OnUndo()
+
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		If tv tv.Undo()
+		
+		'TODO
+		' testing stuff here
+		
+	End
+	
+	Method OnRedo()
+	
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		If tv tv.Redo()
+	End
+	
+	Method OnCut()
+	
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		If tv tv.Cut()
+	End
+
+	Method OnCopy()
+
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		If tv tv.Copy()
+	End
+
+	Method OnPaste()
+		
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		If tv tv.Paste()
+	End
+	
+	Method OnSelectAll()
+		
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		If tv tv.SelectAll()
+	End
+	
+	Method OnWordWrap()
+	
+		Local tv:=Cast<TextView>( App.KeyView )
+		
+		If tv
+			Local cur:=tv.Cursor
+			Local anc:=tv.Anchor
+			Local sc:=tv.Scroll
+			tv.WordWrap=Not tv.WordWrap
+			tv.SelectText( cur,anc )
+			tv.Scroll=sc
+		Endif
+	End
+	
+End

+ 357 - 0
action/FileActions.monkey2

@@ -0,0 +1,357 @@
+
+Namespace ted2go
+
+
+Class FileActions
+
+	Field new_:Action
+	Field open:Action
+	Field close:Action
+	Field closeOthers:Action
+	Field closeToRight:Action
+	Field closeAll:Action
+	Field save:Action
+	Field saveAs:Action
+	Field saveAll:Action
+	Field quit:Action
+	Field prefs:Action
+	
+	Method New( docs:DocumentManager )
+	
+		_docs=docs
+		
+		new_=New Action( "New file" )
+#if __TARGET__="macos"
+		new_.HotKey=Key.T
+		new_.HotKeyModifiers=Modifier.Menu
+#else
+		new_.HotKey=Key.N
+		new_.HotKeyModifiers=Modifier.Menu
+#endif
+		new_.Triggered=OnNew
+		
+		open=New Action( "Open file" )
+		open.HotKey=Key.O
+		open.HotKeyModifiers=Modifier.Menu
+		open.Triggered=OnOpen
+		
+		close=New Action( "Close tab" )
+		close.HotKey=Key.W
+		close.HotKeyModifiers=Modifier.Menu
+		close.Triggered=OnClose
+		
+		closeOthers=New Action( "Close other tabs" )
+		closeOthers.Triggered=OnCloseOthers
+		
+		closeToRight=New Action( "Close tabs to the right" )
+		closeToRight.Triggered=OnCloseToRight
+		
+		closeAll=New Action( "Close all tabs" )
+		closeAll.Triggered=Lambda()
+			CloseFiles( _docs.OpenDocuments )
+		End
+		
+		save=New Action( "Save" )
+		save.HotKey=Key.S
+		save.HotKeyModifiers=Modifier.Menu
+		save.Triggered=OnSave
+
+		saveAs=New Action( "Save as..." )
+		saveAs.Triggered=OnSaveAs
+
+		saveAll=New Action( "Save all" )
+		saveAll.HotKey=Key.S
+		saveAll.HotKeyModifiers=Modifier.Menu|Modifier.Shift
+		saveAll.Triggered=OnSaveAll
+		
+		quit=New Action( "Quit" )
+		quit.Triggered=OnQuit
+		
+#If __TARGET__="windows"
+		quit.HotKey=Key.F4
+		quit.HotKeyModifiers=Modifier.Alt|Modifier.Ignore
+#Elseif __TARGET__="macos"
+		quit.HotKey=Key.Q
+		quit.HotKeyModifiers=Modifier.Menu|Modifier.Ignore
+#Elseif __TARGET__="linux"
+		quit.HotKey=Key.F4
+		quit.HotKeyModifiers=Modifier.Alt|Modifier.Ignore
+#endif		
+
+		prefs=New Action( "Preferences..." )
+		prefs.Triggered=OnPrefs
+#if __TARGET__="macos"
+		prefs.HotKey=Key.Comma
+#Else
+		prefs.HotKey=Key.P
+#Endif
+		prefs.HotKeyModifiers=Modifier.Menu
+		
+	End
+	
+	Method Update()
+	
+		Local docs:=_docs.OpenDocuments
+
+		Local n:=0
+		Local anyDirty:Bool
+		For Local doc:=Eachin docs
+			If doc.Dirty anyDirty=True
+			n+=1
+		Next
+	
+		Local doc:=_docs.CurrentDocument
+
+		close.Enabled=doc
+		closeOthers.Enabled=n>1
+		closeToRight.Enabled=doc And doc<>docs[docs.Length-1]
+		closeAll.Enabled=n>0
+		save.Enabled=doc And (doc.Dirty Or MainWindow.IsTmpPath( doc.Path ))
+		saveAs.Enabled=doc
+		saveAll.Enabled=anyDirty
+	End
+	
+	Method CloseFiles( docs:Ted2Document[] )
+		
+		If Not docs.Length Return
+		
+		_saveAllFlag=False
+		_discardAllFlag=False
+	
+		For Local doc:=Eachin docs
+			If Not CanClose( doc,True ) Return
+		Next
+	
+		For Local doc:=Eachin docs
+			doc.Close()
+		Next
+	
+	End
+	
+	
+	Private
+	
+	Field _docs:DocumentManager
+	Field _saveAllFlag:Bool,_discardAllFlag:Bool
+	Field _quit:Bool
+	
+	
+	Method SaveAs:Ted2Document()
+	
+		Local doc:=_docs.CurrentDocument
+		If Not doc Return Null
+		
+		Local name:=StripDir( doc.Path )
+		Local path:=MainWindow.RequestFile( "Save As",name,True )
+		If Not path Return Null
+				
+		If Not ExtractExt( path ) path+=ExtractExt( doc.Path )
+		
+		Return _docs.RenameDocument( doc,path )
+	End
+
+	Method CanClose:Ted2Document( doc:Ted2Document,manyFiles:Bool=False )
+	
+		If Not doc.Dirty Return doc
+		
+		'_docs.CurrentDocument=doc
+				
+		Local buttons:String[]
+		If manyFiles
+			buttons=New String[]( "Save","Save All","Discard","Discard All","Cancel" )
+		Else
+			buttons=New String[]( "Save","Discard","Cancel" )
+		Endif
+			
+		Local result:=-1
+		If manyFiles
+			If _saveAllFlag
+				result=1
+			Elseif _discardAllFlag
+				result=3
+			Endif
+		Endif
+		If result = -1 Then result=TextDialog.Run( "Close File","File '"+doc.Path+"' has been modified.",buttons )
+		
+		Select result
+		Case 0 'save
+			If MainWindow.IsTmpPath( doc.Path )
+				Return SaveAs()
+			Else
+				If Not doc.Save() Return Null
+			Endif
+		Case 1 'saveAll or discard
+			If manyFiles
+				If MainWindow.IsTmpPath( doc.Path )
+					Return SaveAs()
+				Else
+					If Not doc.Save() Return Null
+				Endif
+				_saveAllFlag=True
+			Endif
+		Case 2 'discard or cancel
+			Return manyFiles ? doc Else Null
+		Case 3 'discardAll
+			_discardAllFlag=True
+		Case 4 'cancel
+			Return Null
+		End
+		
+		Return doc
+	End
+	
+	Method OnNew()
+	
+		Local path:=MainWindow.AllocTmpPath( "untitled",".monkey2" )
+		If Not path
+			Alert( "Can't allocate temporary file" )
+			Return
+		Endif
+
+		SaveString( "",path )
+		
+		_docs.OpenDocument( path,True )
+	End
+		
+	Method OnOpen()
+	
+		Local path:=MainWindow.RequestFile( "Open File","",False )
+		If Not path Return
+		
+		path=RealPath( path )
+		
+		_docs.OpenDocument( path,True )
+	End
+	
+	Method OnClose()
+	
+		Local doc:=_docs.CurrentDocument
+		If Not doc Return
+		
+		doc=CanClose( doc )
+		If Not doc Return
+		
+		doc.Close()
+	End
+	
+	Method OnCloseOthers()
+	
+		Local current:=_docs.CurrentDocument
+		If Not current Return
+	
+		_saveAllFlag=False
+		_discardAllFlag=False
+		
+		Local docs:=_docs.OpenDocuments
+		
+		For Local doc:=Eachin docs
+			If doc<>current And Not CanClose( doc,True ) Return
+		Next
+		
+		For Local doc:=Eachin docs
+			If doc<>current doc.Close()
+		Next
+	End
+	
+	Method OnCloseToRight()
+	
+		Local current:=_docs.CurrentDocument
+		If Not current Return
+	
+		_saveAllFlag=False
+		_discardAllFlag=False
+		
+		Local docs:=_docs.OpenDocuments
+		
+		Local close:=False
+		For Local doc:=Eachin docs
+			If close
+				If Not CanClose( doc,True ) Return
+			Else
+				If doc=current close=True
+			Endif
+		Next
+		
+		close=False
+		For Local doc:=Eachin docs
+			If close
+				doc.Close()
+			Else
+				If doc=current close=True
+			Endif
+		Next
+		
+	End
+	
+	Method OnSave()
+	
+		Local doc:=_docs.CurrentDocument
+		If Not doc Return
+		
+		If MainWindow.IsTmpPath( doc.Path )
+			SaveAs()
+		Else
+			doc.Save()
+		Endif
+	End
+	
+	Method OnSaveAs()
+	
+		SaveAs()
+	End
+	
+	Method OnSaveAll()
+	
+		For Local doc:=Eachin _docs.OpenDocuments
+
+			If MainWindow.IsTmpPath( doc.Path )
+				_docs.CurrentDocument=doc
+				If Not SaveAs() Return
+			Else
+				doc.Save()
+			Endif
+		Next
+	End
+	
+	Method OnQuit()
+		
+		If _quit Return
+		_quit=True
+		
+		_saveAllFlag=False
+		_discardAllFlag=False
+		
+		For Local doc:=Eachin _docs.OpenDocuments
+		
+			If MainWindow.IsTmpPath( doc.Path )
+				If Not doc.Save() Then _quit=False ; Return
+			Else
+				If Not CanClose( doc,True ) Then _quit=False ; Return
+			Endif
+		Next
+		
+		MainWindow.Terminate()
+	End
+	
+	Field _prefsDialog:PrefsDialog
+	
+	Method OnPrefs()
+	
+		If Not _prefsDialog
+			_prefsDialog=New PrefsDialog
+			
+			_prefsDialog.Apply+=Lambda()
+			
+				For Local d:=Eachin _docs.OpenDocuments
+					Local tv:=Cast<CodeDocumentView>( d.TextView )
+					If tv Then tv.UpdatePrefs()
+				Next
+				
+				MainWindow.OnPrefsChanged()
+			End
+			
+		Endif
+		_prefsDialog.Show()
+	End
+	
+End

+ 479 - 0
action/FindActions.monkey2

@@ -0,0 +1,479 @@
+
+Namespace ted2go
+
+
+Class FindActions
+
+	Field find:Action
+	Field findNext:Action
+	field findPrevious:Action
+	Field replace:Action
+	Field replaceNext:Action
+	Field replaceAll:Action
+	Field findInFiles:Action
+	Field findAllInFiles:Action
+	
+	Field options:FindOptions
+	
+	Method New( docs:DocumentManager,projView:ProjectView,findConsole:TreeViewExt )
+		
+		_docs=docs
+		_findConsole=findConsole
+		
+		find=New Action( "Find..." )
+		find.Triggered=OnFind
+		find.HotKey=Key.F
+		find.HotKeyModifiers=Modifier.Menu
+		
+		findNext=New Action( "Find next" )
+		findNext.Triggered=OnFindNext
+		findNext.HotKey=Key.F3
+		
+		findPrevious=New Action( "Find previous" )
+		findPrevious.Triggered=OnFindPrevious
+		findPrevious.HotKey=Key.F3
+		findPrevious.HotKeyModifiers=Modifier.Shift
+		
+		replace=New Action( "Replace..." )
+		replace.Triggered=OnReplace
+		#If __TARGET__="macos"
+		replace.HotKey=Key.F
+		replace.HotKeyModifiers=Modifier.Alt|Modifier.Menu
+		#Else
+		replace.HotKey=Key.H
+		replace.HotKeyModifiers=Modifier.Menu
+		#Endif
+		replaceNext=New Action( "Replace next" )
+		replaceNext.Triggered=OnReplaceNext
+		
+		replaceAll=New Action( "Replace all" )
+		replaceAll.Triggered=OnReplaceAll
+		
+		findInFiles=New Action( "Find in files..." )
+		findInFiles.Triggered=Lambda()
+			Local proj:=projView.FindProjectByFile( docs.CurrentDocument.Path )
+			OnFindInFiles( "",proj )
+		End
+		findInFiles.HotKey=Key.F
+		findInFiles.HotKeyModifiers=Modifier.Menu|Modifier.Shift
+		
+		findAllInFiles=New Action( "Find all" )
+		findAllInFiles.Triggered=OnFindAllInFiles
+		
+		_findDialog=New FindDialog( Self )
+		_findInFilesDialog=New FindInFilesDialog( Self,projView )
+	End
+	
+	Method Update()
+	
+		Local tv:=_docs.CurrentTextView
+		findNext.Enabled=tv
+		findPrevious.Enabled=tv
+		replace.Enabled=tv
+		replaceAll.Enabled=tv
+	End
+	#Rem
+	Method FindByTextChanged( entireProject:Bool )
+		
+		If Not entireProject Then OnFindNext( False )
+	End
+	#End
+	
+	Method FindInFiles( folder:String )
+	
+		OnFindInFiles( folder )
+	End
+	
+	
+	Private
+	
+	Const NXT:=1
+	Const PREV:=-1
+	
+	Field _docs:DocumentManager
+	
+	Field _findDialog:FindDialog
+	Field _findInFilesDialog:FindInFilesDialog
+	Field _findConsole:TreeViewExt
+	Field _cursorPos:=0
+	
+	Method OnFind()
+		
+		Local s:=GetInitialText()
+		MainWindow.ShowFind( s )
+	End
+	
+	Method GetInitialText:String()
+		
+		Local tv:=_docs.CurrentTextView
+		If Not tv Return ""
+		
+		_cursorPos=Min( tv.Cursor,tv.Anchor )
+		
+		If tv.CanCopy And Not Prefs.SiblyMode
+			Local min:=Min( tv.Cursor,tv.Anchor )
+			Local max:=Max( tv.Cursor,tv.Anchor )
+			Return tv.Text.Slice( min,max )
+		Endif
+		Return ""
+	End
+	
+	Method GetRange:Vec2i( tv:TextView )
+		
+		If options.selectionOnly
+			Local code:=Cast<CodeTextView>( tv )
+			If code And code.HasExtraSelection
+				Return New Vec2i( code.ExtraSelectionStart,code.ExtraSelectionEnd )
+			Endif
+		Endif
+		
+		Return New Vec2i( 0,tv.Text.Length )
+	End
+	
+	Method OnFindInFiles( folder:String=Null,selProj:String=Null )
+	
+		Local s:=GetInitialText()
+		If s Then _findInFilesDialog.SetInitialText( s )
+		_findInFilesDialog.SetSelectedProject( selProj )
+		_findInFilesDialog.CustomFolder=folder
+		_findInFilesDialog.Show()
+	End
+	
+	Method OnFindNext()
+		
+		Local tv:=_docs.CurrentTextView
+		If Not tv Return
+		
+		If Not options Return
+		
+		Local doc:=_docs.CurrentDocument
+		
+		Local what:=options.findText
+		If Not what Return
+		
+		Local text:=tv.Text
+		Local sens:=options.caseSensitive
+		
+		If Not sens
+			what=what.ToLower()
+			text=text.ToLower()
+		Endif
+		
+		Local range:=GetRange( tv )
+		
+		Local cursor:=Max( tv.Anchor,tv.Cursor )
+		
+		If cursor<range.x Or cursor>range.y Then cursor=range.x
+		
+		Local i:=text.Find( what,cursor )
+		
+		If i=-1 Or i+what.Length>range.y
+			If Not options.wrapAround Return
+			
+			i=text.Find( what,range.x )
+			If i=-1 Or i+what.Length>range.y Return
+		Endif
+		
+		tv.SelectText( i,i+what.Length )
+		
+	End
+	
+	Method OnFindPrevious()
+		
+		Local tv:=_docs.CurrentTextView
+		If Not tv Return
+		
+		If Not options Return
+		
+		Local doc:=_docs.CurrentDocument
+		
+		Local what:=options.findText
+		If Not what Return
+		
+		Local text:=tv.Text
+		Local sens:=options.caseSensitive
+		
+		If Not sens
+			what=what.ToLower()
+			text=text.ToLower()
+		Endif
+		
+		Local range:=GetRange( tv )
+		
+		Local i:=text.Find( what,range.x )
+		If i=-1 Or i+what.Length>range.y Return
+		
+		Local cursor:=Min( tv.Anchor,tv.Cursor )
+		
+		If cursor<range.x Or cursor>range.y Then cursor=range.y
+		
+		If i>=cursor
+			If Not options.wrapAround Return
+			Repeat
+				Local n:=text.Find( what,i+what.Length )
+				If n=-1 Or n>=range.y Exit
+				i=n
+			Forever
+		Else
+			Repeat
+				Local n:=text.Find( what,i+what.Length )
+				If n=-1 Or n>=cursor Exit
+				i=n
+			Forever
+		End
+		
+		tv.SelectText( i,i+what.Length )
+	End
+	
+	Method OnFindAllInFiles()
+	
+		If Not _findInFilesDialog.FindText
+			ShowMessage( "","Please, enter text to find what." )
+			Return
+		Endif
+		
+		If Not _findInFilesDialog.SelectedProject
+			ShowMessage( "","Please, select project in the list." )
+			Return
+		Endif
+		
+		'_findInFilesDialog.Hide()
+		MainWindow.ShowFindResults()
+		
+		New Fiber( Lambda()
+		
+			Local what:=_findInFilesDialog.FindText
+			Local proj:=_findInFilesDialog.SelectedProject
+			Local sens:=_findInFilesDialog.CaseSensitive
+			Local filter:=_findInFilesDialog.FilterText
+			
+			Local result:=FindInProject( what,proj,sens,filter )
+			
+			If result Then CreateResultTree( _findConsole.RootNode,result,what,proj )
+		End)
+		
+	End
+	
+	Const DEFAULT_FILES_FILTER:="monkey2" ',txt,htm,html,h,cpp,json,xml,ini"
+	
+	Method FindInProject:StringMap<Stack<FileJumpData>>( what:String,projectPath:String,caseSensitive:Bool,filesFilter:String=DEFAULT_FILES_FILTER )
+		
+		If Not filesFilter Then filesFilter=DEFAULT_FILES_FILTER
+		
+		Local exts:=filesFilter.Split( "," )
+		
+		projectPath+="/"
+		
+		If Not caseSensitive Then what=what.ToLower()
+		
+		Local files:=New Stack<String>
+		Utils.GetAllFiles( projectPath,exts,files )
+		Local len:=what.Length
+		
+		Local result:=New StringMap<Stack<FileJumpData>>
+		
+		'Local counter:=1
+		Local doc:=New TextDocument 'use it to get line number
+		For Local f:=Eachin files
+		
+			Local text:=LoadString( f )
+		
+			If Not caseSensitive Then text=text.ToLower()
+		
+			doc.Text=text 'any needed replacing is here (\r\n -> \n)
+			text=doc.Text
+		
+			Local i:=0
+			Local items:=New Stack<FileJumpData>
+			
+			Repeat
+				i=text.Find( what,i )
+				If i=-1 Exit
+				
+				Local data:=New FileJumpData
+				data.path=f
+				data.pos=i
+				data.len=len
+				data.line=doc.FindLine( i )+1
+				
+				items.Add( data )
+				
+				i+=len
+			Forever
+			
+			If Not items.Empty Then result[f]=items
+			
+			'If counter Mod 10 = 0
+			'	' process 10 files per frame to save app responsibility
+			'	App.WaitIdle()
+			'Endif
+			
+		Next
+		
+		Return result
+	End
+	
+	#Rem
+	Method FindInFile:Stack<FileJumpData>( filePath:String,what:String,caseSensitive:Bool,doc:TextDocument=Null )
+	
+		Local len:=what.Length
+		Local text:String
+		
+		If Not doc
+			doc=New TextDocument
+			text=LoadString( filePath )
+			doc.Text=text 'any needed replacing is here (\r\n -> \n)
+		Endif
+		text=doc.Text
+		If Not caseSensitive Then text=text.ToLower()
+		
+		Local i:=0
+		Local result:=New Stack<FileJumpData>
+		
+		Repeat
+			i=text.Find( what,i )
+			If i=-1 Exit
+
+			Local data:=New FileJumpData
+			data.path=filePath
+			data.pos=i
+			data.len=len
+			data.line=doc.FindLine( i )+1
+
+			result.Add( data )
+
+			i+=len
+		Forever
+
+		Return result
+	End
+	#End
+	
+	Method CreateResultTree( root:TreeView.Node,map:StringMap<Stack<FileJumpData>>,what:String,projectPath:String )
+		
+		root.RemoveAllChildren()
+		
+		root.Text="Results for '"+what+"'"
+		
+		Local subRoot:TreeView.Node
+		
+		For Local file:=Eachin map.Keys
+			
+			Local items:=map[file]
+			
+			subRoot=New TreeView.Node( file.Replace( projectPath+"/","" )+" ("+items.Length+")",root )
+	
+			For Local d:=Eachin items
+				Local node:=New NodeWithData<FileJumpData>( " at line "+d.line,subRoot )
+				node.data=d
+			Next
+		
+		Next
+		
+		If root.NumChildren=0 Then New TreeView.Node( "not found :(",root )
+		
+		root.Expanded=True
+		
+	End
+	
+	Method OnReplace()
+		
+		Local s:=GetInitialText()
+		MainWindow.ShowReplace( s )
+	End
+	
+	Method OnReplaceNext()
+	
+		Local tv:=_docs.CurrentTextView
+		If Not tv Return
+		
+		Local min:=Min( tv.Anchor,tv.Cursor )
+		Local max:=Max( tv.Anchor,tv.Cursor )
+		
+		Local text:=tv.Text.Slice( min,max )
+		Local what:=options.findText
+		
+		If Not text Return
+
+		If Not options.caseSensitive
+			text=text.ToLower()
+			what=what.ToLower()
+		Endif
+		
+		If text<>what Return
+		
+		Local with:=options.replaceText
+		
+		tv.ReplaceText( with )
+		
+		' temp solution
+		If options.selectionOnly
+			Local code:=Cast<CodeTextView>( tv )
+			If code Then code.ExtraSelectionEnd+=(with.Length-what.Length)
+		Endif
+		
+		OnFindNext()
+
+	End
+	
+	Method OnReplaceAll()
+	
+		Local tv:=_docs.CurrentTextView
+		If Not tv Return
+		
+		Local what:=options.findText
+		If Not what Return
+		
+		Local with:=options.replaceText
+		
+		Local text:=tv.Text
+
+		If Not options.caseSensitive
+			text=text.ToLower()
+			what=what.ToLower()
+		Endif
+		
+		Local anchor:=tv.Anchor
+		Local cursor:=tv.Cursor
+		
+		Local range:=GetRange( tv )
+		
+		Local lenWhat:=what.Length
+		Local lenWith:=with.Length
+		
+		Local i:=range.x,t:=0
+		Repeat
+		
+			i=text.Find( what,i )
+			If i=-1 Or i+lenWhat>range.y Exit
+			
+			tv.SelectText( i+t,i+lenWhat+t )
+			tv.ReplaceText( with )
+			
+			' select last replacement
+			cursor=tv.Cursor
+			anchor=tv.Cursor-lenWith
+			
+			Local dlen:=lenWith-lenWhat
+			
+			' temp solution
+			If options.selectionOnly
+				Local code:=Cast<CodeTextView>( tv )
+				If code Then code.ExtraSelectionEnd+=dlen
+			Endif
+			
+			t+=dlen
+			i+=lenWhat
+			
+		Forever
+		
+'		If options.selectionOnly
+'			anchor=range.x
+'			cursor=range.x
+'		Endif
+		
+		tv.SelectText( anchor,cursor )
+		
+	End
+	
+End

+ 112 - 0
action/HelpActions.monkey2

@@ -0,0 +1,112 @@
+
+Namespace ted2go
+
+
+Class HelpActions
+
+	Field quickHelp:Action
+	Field onlineHelp:Action
+	Field viewManuals:Action
+	Field uploadModules:Action
+	Field about:Action
+	Field aboutTed2go:Action
+	Field makeBetter:Action
+	Field mx2homepage:Action
+	Field bananas:Action
+	
+
+	Method New()
+	
+		quickHelp=New Action( "Quick help" )
+		quickHelp.Triggered=OnQuickHelp
+		quickHelp.HotKey=Key.F1
+		
+		onlineHelp=New Action( "Online help" )
+		onlineHelp.Triggered=lambda()
+		
+			OpenUrl( MONKEY2_DOMAIN+"/monkey2-docs/" )
+		End
+		
+		viewManuals=New Action( "Browse manuals" )
+		viewManuals.Triggered=Lambda()
+		
+			OpenUrl( RealPath( "docs/index.html" ) )
+		End
+		
+		uploadModules=New Action( "Upload module" )
+		uploadModules.Triggered=Lambda()
+		
+			GotoUploadModulesPage()
+		End
+
+		about=New Action( "About monkey2" )
+		about.Triggered=Lambda()
+		
+			Local htmlView:=New HtmlView
+			htmlView.Go( MainWindow.AboutPagePath )
+	
+			Local dialog:=New Dialog( "About monkey2" )
+			dialog.ContentView=htmlView
+
+			dialog.MinSize=New Vec2i( 640,600 )
+
+			dialog.AddAction( "Okay!" ).Triggered=dialog.Close
+			
+			dialog.Open()
+		End
+
+		aboutTed2go=New Action( "About ted2go" )
+		aboutTed2go.Triggered=Lambda()
+		
+			Local htmlView:=New HtmlView
+			htmlView.Go( "asset::ted2/aboutTed2Go.html" )
+	
+			Local dialog:=New Dialog( "About ted2go" )
+			dialog.ContentView=htmlView
+
+			dialog.MinSize=New Vec2i( 640,600 )
+
+			dialog.AddAction( "Okay!" ).Triggered=dialog.Close
+			
+			dialog.Open()
+		End
+		
+		makeBetter=New Action( "Make this app better! (paypal)" )
+		makeBetter.Triggered=Lambda()
+		
+			OpenUrl( "https://paypal.me/engor/10" )
+		End
+		
+		mx2homepage=New Action( "Monkey2 homepage" )
+		mx2homepage.Triggered=lambda()
+		
+			OpenUrl( MONKEY2_DOMAIN )
+		End
+		
+		bananas=New Action( "Bananas showcase" )
+		bananas.Triggered=lambda()
+		
+			MainWindow.ShowBananasShowcase()
+		End
+	End
+
+	
+	Private
+	
+	Field _docs:DocumentManager
+	
+	Method OnQuickHelp()
+	
+		MainWindow.ShowQuickHelp()
+	End
+	
+End
+
+
+Function GotoUploadModulesPage()
+	
+	Alert( "Now taking you to the module manager page at "+MONKEY2_DOMAIN+".~n~nNote: You must have an account at "+MONKEY2_DOMAIN+" and be logged in to upload modules." )
+	
+	OpenUrl( RealPath( MONKEY2_DOMAIN+"/module-manager/" ) )
+	
+End

+ 103 - 0
action/ViewActions.monkey2

@@ -0,0 +1,103 @@
+
+Namespace ted2go
+
+
+Class ViewActions
+	
+	Field goBack:Action
+	Field goForward:Action
+	Field comment:Action
+	Field uncomment:Action
+	Field gotoLine:Action
+	Field gotoDeclaration:Action
+	
+	Method New( docs:DocumentManager )
+		
+		_docs=docs
+		
+		goBack=New Action( "Go back" )
+		goBack.Triggered=OnGoBack
+		goBack.HotKey=Key.Left
+		goBack.HotKeyModifiers=Modifier.Alt|Modifier.Menu
+		
+		goForward=New Action( "Go forward" )
+		goForward.Triggered=OnGoForward
+		goForward.HotKey=Key.Right
+		goForward.HotKeyModifiers=Modifier.Alt|Modifier.Menu
+		
+		comment=New Action( "Comment block" )
+		comment.Triggered=OnComment
+#If __TARGET__="macos"
+		comment.HotKey=Key.Backslash
+#Else
+		comment.HotKey=Key.Apostrophe
+#Endif
+		comment.HotKeyModifiers=Modifier.Menu
+		
+		uncomment=New Action( "Uncomment block" )
+		uncomment.Triggered=OnUncomment
+#If __TARGET__="macos"
+		uncomment.HotKey=Key.Backslash
+#Else
+		uncomment.HotKey=Key.Apostrophe
+#Endif
+		uncomment.HotKeyModifiers=Modifier.Menu|Modifier.Shift
+		
+		gotoLine=New Action( "Goto line" )
+		gotoLine.Triggered=OnGotoLine
+		gotoLine.HotKey=Key.G
+		gotoLine.HotKeyModifiers=Modifier.Menu
+		
+		gotoDeclaration=New Action( "Goto declaration" )
+		gotoDeclaration.Triggered=OnGotoDeclaration
+		gotoDeclaration.HotKey=Key.F12
+	End
+	
+	
+	Private
+	
+	Field _docs:DocumentManager
+	
+	Method OnGoBack()
+		
+		Local doc:=Cast<CodeDocument>( _docs.CurrentDocument )
+		If Not doc Return
+		
+		doc.GoBack()
+	End
+	
+	Method OnGoForward()
+	
+		Local doc:=Cast<CodeDocument>( _docs.CurrentDocument )
+		If Not doc Return
+	
+		doc.GoForward()
+	End
+	
+	Method OnComment()
+	
+		Local doc:=Cast<CodeDocument>( _docs.CurrentDocument )
+		If Not doc Return
+	
+		doc.Comment()
+	End
+	
+	Method OnUncomment()
+	
+		Local doc:=Cast<CodeDocument>( _docs.CurrentDocument )
+		If Not doc Return
+	
+		doc.Uncomment()
+	End
+	
+	Method OnGotoLine()
+	
+		MainWindow.GotoLine()
+	End
+	
+	Method OnGotoDeclaration()
+	
+		MainWindow.GotoDeclaration()
+	End
+	
+End

+ 312 - 0
assets/about.html

@@ -0,0 +1,312 @@
+<!doctype html>
+<html>
+<head>
+<style>
+
+body{
+	background: transparent;
+	color: #eee;
+	font-size: 18px;
+	margin: 8px;
+	padding: 0px;
+	line-height:20px;
+}
+
+h1{
+	color: #fc0;
+	font-size: 28px;
+	text-align: center;
+}
+
+h2{
+	color: #fc0;
+	font-size: 24px;
+	text-align: center;
+}
+
+div.awesome{
+	color: #ccc;
+	font-size: 14px;
+}
+
+a{
+	color: #4ef;
+	text-decoration: none;
+	cursor: pointer;
+}
+
+a:hover{
+	color: #0e0;
+}
+
+</style>
+</head>
+
+<body>
+
+<h1>Monkey2 v1.1.04</h1>
+
+<p>Welcome to monkey2, a new, open source, user friendly, multi target programming language by Mark Sibly.
+
+<p>Please post any bug reports or feature requests to the monkey2 github repository: <a href="https://github.com/blitz-research/monkey2">https://github.com/blitz-research/monkey2</a>.
+
+<p>For monkey2 discussion and programming help, feel free to drop by the monkey2 forums: <a href="http://monkeycoder.co.nz/forums">http://monkeycoder.co.nz/forums</a>.
+
+<p>Monkey2 is a crowd funded project. If you like what you see, please consider contributing to development either via paypal donation or by becoming a Patreon supporter.
+
+<h2>Building Desktop apps</h2>
+
+<p>If you are reading this in Ted2 on a Windows machine, you should theoretically be able to build desktop apps with no extra hassle.
+
+<p>On Macos, it's a little bit trickier but not much. First, you will need to install xcode from the App Store. Once that's done, go into a shell and enter 'xcode-select --install' to install the 'xcode command line tools'. Note that if you are already using Blitzmax or Monkey1 on a Mac, you may not have to do anything.
+
+<p>On Linux, you will need the standard set of development tools and libs such as g++, mesa-gl, a ton of X stuff etc. Sorry I can't be more specific here, but past attempts to produce a definitive list of 'what you need to code in linux' have proved fruitless - it changes from distro to distro and version to version.
+
+<p>Once you're ready to go, try clicking on the 'hello-world.monkey2' file in the 'Files' browser to the right, and then selecting 'Build and Run' from the 'Build' menu.
+
+<p>This will bring up a little 'Build Settings' dialog. Just click OK to use the defaults and build and run the app. If everything is working properly, a simple 'Hello World' window should appear.
+
+<p>Note that the build settings dialog will only appear automatically the first time you build an app for each target. After that, you can manually
+activate it by selecting 'Build Settings' from the 'Build' menu - not that it does a lot right now!
+
+<p>There are a few more examples in the 'bananas' directory on the right - more coming!
+
+<h2>Building Emscripten apps</h2>
+
+<p>To build emscripten apps, you will first need to install emscripten: 
+
+<p><a href="http://kripken.github.io/emscripten-site">http://kripken.github.io/emscripten-site</a>.
+
+<p>(On MacOS, you may also need to modify your bin/env_macos.txt file to let monkey2 know where emscripten has been installed).
+
+<p>Once emscripten is installed, you will then need to 'rebuild modules' for the emscripten target. This involves selecting 'Rebuild modules' from the 'Build' menu in Ted2, and then selecting 'Emscripten'. This will take a while, as monkey2 needs to rebuild ALL source code used behind the scenes.
+
+<p>Once done, you should be able to build emscripten apps. However, to also actually run them you will need to install the 'mserver' package:
+
+<p><a href="http://www.monkey-x.com/mak/devtools/mserver-v86c.zip">http://www.monkey-x.com/mak/devtools/mserver-v86c.zip</a>.
+
+<p>(On Macos and Linux, you may also need to change file permissions to 'execute').
+
+<p>This needs to be unzipped into your monkey2 'devtools' directory. MServer is actually a mini 'http' server, and is necessary because emscripten apps can't be run directly from the filesystem - they must always be run from a server.
+
+<p>Now, select the 'Emscripten' target from the 'Build Targets' menu and you should be able to build and run emscripten apps.
+
+
+<h2>Building Android apps</h2>
+
+<p>To build android apps, you will first need to install Android Studio:
+
+<p><a href="https://developer.android.com/studio/index.html">https://developer.android.com/studio/index.html</a>.
+
+<p>Once installed, make sure everything's working properly and that you can build and deploy android apps from inside Android studio. The best way to do this is by building and deploying one of the simple 'template' apps in android studio.
+
+<p>Next, install the Android NDK (native development kit) via the SDK Manager->SDK Tools section.
+
+<p>Once android studio and the NDK are installed, you will then need to rebuild modules for android. Once this is done, you should (finally!) be able to build android apps.
+
+<p>Android apps are produced in the form of android studio projects, and can be found in the '.products' directory next to your monkey2 source file.
+
+<p>Note that monkey2 only currently builds for 'armv7' hardware.
+
+
+<h2>Building iOS apps</h2>
+
+<p>Monkey2 iOS apps cannot currently be run on the simulator, so the first thing you will need is a real iOS device plus the necessary 'code signing skills' to be able to actually deploy to it.
+
+<p>Apart from that, all you need to build for iOS is the latest version of xcode. Once you have xcode installed, you will to 'rebuild modules' for iOS after which you should be able to build iOS apps.
+
+<p>iOS apps are produced in the form of xcode projects, and can be found in the '.products' directory next to your monkey2 source file.
+
+<p>Note that monkey2 only currently builds for 'armv7' hardware.
+
+
+<h2>That's all Folks!</h2>
+
+<p>Monkey2 is a crowd funded project. If you like what you see, please consider contributing to development either via paypal donation or by becoming a Patreon supporter.
+
+<p>Finally, a big shout out to everyone who has contributed to Monkey2 to date, including...
+
+<div class="awesome">
+Shane Raffa,
+Danilo,
+Blaine Hodge,
+Lucien Bulles,
+Daniel,
+Martin,
+Tony Smits,
+Peter Rigby,
+Jake Birkett,
+Pharmhaus,
+James Boyd,
+David Maziarka,
+starfruit,
+Stephen	Greener,
+Jonathan Pittock,
+Aaron Woodard,
+Lee Wade,
+abakobo,
+York Burkhardt,
+Rene Damm,
+Capn Lee,
+Jesse M Perez,
+Matthew,
+neuro,
+Paul Apgar,
+Matthew	Camerer,
+Difference,
+Kirsty,
+kmac,
+Richard	Betson,
+Javier,
+Adam,
+Phil7,	
+Erik Thon,
+Noel Cole,
+Ole Jostein Røtne,
+Patrik Strandell,
+Darryl,
+Lars Kristian Gretnes,
+C.E.,
+Roger Lockerbie,
+Philippe Back,
+Bill Stanbrook,
+Hotcakes,
+Christian Leth Jeppesen,
+Makarienkov Vladimir,
+Alan Broad,
+David,
+Christian,
+Leo Santos,
+Pierrou,
+Arthur,
+Richard McLoughlin,
+zui,
+Dennis Rohn,
+Daniele Prandini,
+Hezkore,
+Bill Murray,
+Felipe Alfonso,
+Annika Terrortante,
+Panayiotis Yianni,
+RenK,
+Zachary Cassity,
+Jules Duquette,
+Ian Martin,
+Richard Keam,
+James Freeman,
+Paul Huckstepp,
+Graham,
+Hubert BAYRE,
+Jochen Heizmann,
+Boz	
+Aroldo Carvalho,
+Mattias Hansson,
+Catalin Lucaciu,
+Jochen Heizmann,
+Boz,
+Zachary Cassity,
+Hubert BAYRE,
+Cory Estes,
+Paul Huckstepp,
+Stephen Maden,
+degac,
+sal gunduz,
+Ole Jostein Røtne,
+Alan Rawkins,
+Dennis Rohn,
+Christian,
+Philipp Moeller,
+Roger Lockerbie,
+Pierrou,
+Philippe Back,
+Patrik Strandell,
+Bill Stanbrook,
+Erik Thon,
+Richard Keam,
+James Freeman,
+Danilo,
+Juan Camilo,
+Lars Kristian Gretnes,
+Noel Cole,
+Michael Hartlef,
+Jules Duquette,
+Ian Martin,
+Leigh Bowers,
+Daniele Prandini,
+Alan Broad,
+Christian Leth Jeppesen!,
+Rene Damm,
+Richard McLoughlin,
+Kennie,
+ ussell King,
+gcmartijn,
+Darryl,
+Michael Hauck,
+Graham,
+sal gunduz,
+Danilo,
+Daniele Prandini,
+York Burkhardt,
+Peter Rigby,
+Michael Hartlef,
+Leonardo Teixeira,
+Daniel Murphy,
+Gloomywood,
+Adam,
+Arthur,
+Richard Betson,
+Jake Birkett,
+Simon Harrison,
+Daniel Born,
+David Maziarka,
+starfruit,
+David,
+Markus L,
+Capn Lee,
+Jesus M Perez,
+Hotcakes,
+Amon,
+Blaine Hodge,
+Jeffrey Nofsinger,
+Felipe Alfonso,
+Matthew,
+Robin Columbus,
+Alan Rawkins,
+TeaBoy,
+Brian Kramer,
+Bill Murray,
+neuro,
+degac,
+Javier San Juan Cervera,
+Sander Voorn,
+Makarienkov Vladimir,
+impixi,
+kmac,
+Paul Apgar,
+Shane Woolcock,
+Stephen Greener,
+Tony Smits,
+Lucien Bulles,
+SecondGear,
+Matthew Camerer,
+Jonathan Pittock,
+Annika Terrortante,
+Josh Klint,
+Aaron woodard,
+Lee Wade,
+taumel,
+Arthur Bikmullin,
+Difference,
+Michael Denathorn,
+Jose Faeti,
+Martin Leidel,
+abakobo,
+Kirsty,
+Benjamin Aregger,
+James Boyd,
+Simon Armstrong.
+</div>
+
+</body>
+
+</html>

+ 131 - 0
assets/aboutTed2Go.html

@@ -0,0 +1,131 @@
+<!doctype html>
+<html>
+<head>
+<style>
+
+body{
+	background: transparent;
+	color: #eee;
+	font-size: 18px;
+	margin: 8px;
+	padding: 0px;
+	line-height:20px;
+}
+
+h1{
+	color: #fc0;
+	font-size: 28px;
+	text-align: center;
+}
+
+h2{
+	color: #fc0;
+	font-size: 24px;
+	text-align: center;
+}
+
+div.awesome{
+	color: #ccc;
+	font-size: 14px;
+}
+
+a{
+	color: #4ef;
+	text-decoration: none;
+	cursor: pointer;
+}
+
+a:hover{
+	color: #0e0;
+}
+
+</style>
+</head>
+
+<body>
+
+<center><a href="https://github.com/engor/Ted2Go">Sources on Github</a> | <a href="https://trello.com/b/6FHUXCBF/ted2go">Todo on Trello</a> | <a href="http://monkeycoder.co.nz/forums/topic/ted2go-fork/">Discuss on Forum</a> | <a href="https://paypal.me/engor/10">Donate</a><br></center>
+
+<h3>Features</h3>
+
+<ul>
+<li><b>Autocompletion List</b><br>
+It is based on real parsing of sources, parse all modules and user's code.<br>
+(WIP, don't parse locals yet.)
+</li>
+<br>
+<li><b>CodeTree View</b><br>
+Shows code structure, gives us comfortable code jumping.
+</li>
+<br>
+<li><b>Code templates</b><br>
+You just type short combination (like 'prop'), press TAB and get whole code constuction (for ex. property with setter and getter).<br>
+You can add your own templates. Speed up your coding!
+</li>
+<br>
+<li><b>Goto definition</b><br>
+Press F12 (or F2) to goto definition of ident under cursor.
+</li>
+<br>
+<li><b>Parsing on-the-fly</b><br>
+You can see parse errors in realtime. Point the mouse to see a hint.
+</li>
+<br>
+<li><b>ToolBars</b><br>
+MainToolBar - to simplify access to actions: open/save/undo/redo/build.<br>
+EditorToolBar: find/comment/shift.
+</li>
+<br>
+<li><b>StatusBar</b><br>
+You can see some useful info here:<br>
+* quick help for any (almost) code member by F1;<br>
+* cursor line number and position in line;<br>
+* building dialog moved here, so you can comfortable write code while compiling.<br>
+</li>
+<br>
+<li><b>Quick help</b><br>
+Press F1 first time and you'll see quick help in status bar.<br>
+Press F1 again and you'll see the full help for module members, or will be jumped to member declaration.<br>
+Help system find idents more accurately (in comparison with original ted2).
+</li>
+<br>
+<li><b>"Find in files" dialog</b> (Ctrl+Shift+F)</li>
+Allow you to find in whole project.
+</ul>
+
+
+<h3>Shortcuts</h3>
+<ul>
+<li>F1 - show help for ident under cursor;</li>
+<li>F2/F12 - goto ident declaration;</li>
+<li>Ctrl+Alt+Left / Ctrl+Alt+Right - go back / go forward through navigation stack;</li>
+<li>Ctrl+' (or just ' for selection) - comment selected lines (macos: Ctrl+\);</li>
+<li>Ctrl+Shift+' (or just ' for selection) - uncomment selected lines (macos: Ctrl+Shift+\);</li>
+<li>Ctrl+E - delete whole line under cursor (macos: Ctrl+Backspace).</li>
+<li>Ctrl+Shift+F - open "Find in files" dialog.</li>
+<li>Shift+F5 - stop current process (cancel building, etc).</li>
+<li>Esc - show/hide bottom tabs.</li>
+<li>Shift+Esc - show/hide left&right tabs.</li>
+</ul>
+
+
+<h3>Authors</h3>
+
+<p>Maintained by Evgeniy Goroshkin (nerobot/engor) and Mark Sibly.<br>
+Welcome to say thanks to Evgeniy with <a href="https://paypal.me/engor/10">PayPal donation</a>.<br>
+Enjoy coding!</p>
+
+
+<h3>Third party</h3>
+
+<p>Almost all icons for CodeTree were taken from <a href="https://netbeans.org">Netbeans IDE</a>.<br>
+ToolBar icons were taken from <a href="https://icons8.com/icon/new-icons/win8">icons8.com</a>.</p>
+
+
+<h3>Special thanks</h3>
+
+<p>Matthew Bowen, Mark Mcvittie, Simon Armstrong, Rudy van Etten, Hezkore, Sal Gunduz, Peter Scheutz, Matthieu Chemin, David Maziarka, Leonardo Teixeira, Jesus Perez, Mark Sibly, Philipp Moeller, Lee Wade.</p>
+
+</body>
+
+</html>

BIN
assets/fonts/MesloLGSDZ-Bold.ttf


BIN
assets/fonts/Roboto-Medium.ttf


BIN
assets/fonts/RobotoMono-Medium.ttf


BIN
assets/fonts/verdana.ttf


BIN
assets/fonts/verdanab.ttf


+ 9 - 0
assets/gen/newClass.txt

@@ -0,0 +1,9 @@
+
+_NAMESPACE_
+
+
+Class _NAME__SUPERCLASS__INTERFACES_
+	
+	
+	
+End

+ 30 - 0
assets/liveTemplates.json

@@ -0,0 +1,30 @@
+{
+	".monkey2":{
+		"do":"Repeat\n\t${Cursor}\nForever",
+		"dou":"Repeat\n\t\nUntil _${Cursor}",
+		"each":"For Local ${Cursor}:=Eachin _\n\t\nNext",
+		"fib":"New Fiber( Lambda()\n\t${Cursor}\nEnd )",
+		"fori":"For Local ${Cursor}:=0 Until _\n\t\nNext",
+		"fu":"Function ${Cursor}()\n\t\n\t\nEnd",
+		"fus":"Function ${Cursor}:String()\n\t\n\tReturn \nEnd",
+		"get":"Property ${Cursor}()\n\tReturn \nEnd",
+		"ifb":"If ${Cursor}\n\t\nEndif",
+		"ife":"If ${Cursor}\n\t\nElse\n\t\nEndif",
+		"ifn":"If ${Cursor} = Null\n\t\nEndif",
+		"inn":"If ${Cursor} <> Null\n\t\nEndif",
+		"last":"[_${Cursor}.Length-1]",
+		"lo":"Local ${Cursor}:=",
+		"me":"Method ${Cursor}()\n\t\n\t\nEnd",
+		"meb":"Method ${Cursor}:Bool()\n\t\n\t\nEnd",
+		"mes":"Method ${Cursor}:String()\n\t\n\tReturn \nEnd",
+		"prnt":"Print \"${Cursor}\"",
+		"prop":"Property ${Cursor}()\n\tReturn \nSetter( value: )\n\t\n\t=value\nEnd",
+		"sel":"Select ${Cursor}\n\tCase \n\t\t\nEnd",
+		"seld":"Select ${Cursor}\n\tCase \n\t\t\n\tDefault \n\t\t\nEnd",
+		"st":"String",
+		"try":"Try\n\t${Cursor}\nCatch _\n\t\nEnd",
+		"whe":"While ${Cursor} = _\n\t\nWend",
+		"whi":"While ${Cursor}\n\t\nWend",
+		"whn":"While ${Cursor} <> _\n\t\nWend"
+	}
+}

+ 54 - 0
assets/newfiles/Letterboxed_Mojo_App.monkey2

@@ -0,0 +1,54 @@
+
+Namespace myapp
+
+#Import "<std>"
+#Import "<mojo>"
+
+Using std..
+Using mojo..
+
+Const Size:=New Vec2i( 640,360 )
+
+Class MyWindow Extends Window
+
+	Method New()
+		Super.New( "My Window",640,480,WindowFlags.Resizable )
+	
+		Layout="letterbox"
+	
+	End
+
+	Method OnRender( canvas:Canvas ) Override
+	
+		App.RequestRender()
+	
+		canvas.DrawText( "Hello World",Width/2,Height/2,.5,.5 )
+	
+	End
+	
+	Method OnKeyEvent( event:KeyEvent ) Override
+	
+		If event.Type=EventType.KeyDown And event.Key=Key.Enter And event.Modifiers & Modifier.Alt
+		
+			Fullscreen=Not Fullscreen
+			
+		Endif
+	
+	End
+	
+	Method OnMeasure:Vec2i() Override
+	
+		Return Size
+		
+	End
+	
+End
+
+Function Main()
+
+	New AppInstance
+	
+	New MyWindow
+	
+	App.Run()
+End

+ 12 - 0
assets/newfiles/Simple_Console_App.monkey2

@@ -0,0 +1,12 @@
+
+Namespace myapp
+
+#Import "<std>"
+
+Using std..
+
+Function Main()
+
+	Print "Hello World"
+	
+End

+ 33 - 0
assets/newfiles/Simple_Mojo_App.monkey2

@@ -0,0 +1,33 @@
+
+Namespace myapp
+
+#Import "<std>"
+#Import "<mojo>"
+
+Using std..
+Using mojo..
+
+Class MyWindow Extends Window
+
+	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )
+
+		Super.New( title,width,height,flags )
+	End
+
+	Method OnRender( canvas:Canvas ) Override
+	
+		App.RequestRender()
+	
+		canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 )
+	End
+	
+End
+
+Function Main()
+
+	New AppInstance
+	
+	New MyWindow
+	
+	App.Run()
+End

+ 26 - 0
assets/newfiles/Simple_Mojox_Gui_App.monkey2

@@ -0,0 +1,26 @@
+
+#Import "<std>"
+#Import "<mojo>"
+#Import "<mojox>"
+
+Using std..
+Using mojo..
+Using mojox..
+
+Class MyWindow Extends Window
+
+	Method New()
+		Super.New( "Simple Mojo Gui App",640,480,WindowFlags.Resizable )
+	End
+
+End
+
+Function Main()
+
+	New AppInstance
+	
+	New MyWindow
+	
+	App.Run()
+End
+

BIN
assets/themes/cancel.png


BIN
assets/themes/codeicons/alias.png


BIN
assets/themes/codeicons/annotation.png


BIN
assets/themes/codeicons/class.png


BIN
assets/themes/codeicons/class_private.png


BIN
assets/themes/codeicons/class_protected.png


BIN
assets/themes/codeicons/code_template.png


BIN
assets/themes/codeicons/const.png


BIN
assets/themes/codeicons/constructor.png


BIN
assets/themes/codeicons/constructor_private.png


BIN
assets/themes/codeicons/constructor_protected.png


BIN
assets/themes/codeicons/enum.png


BIN
assets/themes/codeicons/enum_private.png


BIN
assets/themes/codeicons/enum_protected.png


BIN
assets/themes/codeicons/error.png


BIN
assets/themes/codeicons/field.png


BIN
assets/themes/codeicons/field_func.png


BIN
assets/themes/codeicons/field_private.png


BIN
assets/themes/codeicons/field_protected.png


BIN
assets/themes/codeicons/field_static.png


BIN
assets/themes/codeicons/field_static_private.png


BIN
assets/themes/codeicons/field_static_protected.png


BIN
assets/themes/codeicons/folder.png


BIN
assets/themes/codeicons/interface.png


BIN
assets/themes/codeicons/keyword.png


BIN
assets/themes/codeicons/local.png


BIN
assets/themes/codeicons/method.png


BIN
assets/themes/codeicons/method_private.png


BIN
assets/themes/codeicons/method_protected.png


BIN
assets/themes/codeicons/method_static.png


BIN
assets/themes/codeicons/method_static_private.png


BIN
assets/themes/codeicons/method_static_protected.png


BIN
assets/themes/codeicons/operator.png


BIN
assets/themes/codeicons/other.png


BIN
assets/themes/codeicons/package.png


BIN
assets/themes/codeicons/property.png


BIN
assets/themes/codeicons/property_private.png


BIN
assets/themes/codeicons/property_protected.png


BIN
assets/themes/codeicons/struct.png


BIN
assets/themes/codeicons/struct_private.png


BIN
assets/themes/codeicons/struct_protected.png


BIN
assets/themes/codeicons/warning.png


BIN
assets/themes/debug_icons.png


+ 341 - 0
assets/themes/default-tmp.json

@@ -0,0 +1,341 @@
+{
+	"colors":{
+
+		"transparent": "#0000",
+		"clear": "#181818",
+		"gutter": "#262626",
+		"content": "#323232",
+		"panel": "#4c4c4c",
+		"knob": "#666666",
+		"hover": "#888888",
+		"active" : "#989898",
+		
+		"text-default": "#fff",
+		"text-highlight": "#ff0",
+		"text-disabled": "#888",
+		"text-background": "#888",
+		
+		"textview-cursor":"#fff",
+		"textview-selection":"#88f",
+		"textview-cursor-line":"#2000",
+		"textview-whitespaces":"#2aaa",
+
+		"textview-color0":"#0000",
+		"textview-color1":"#fff",
+		"textview-color2":"#ff0",
+		"textview-color3":"#0f8",
+		"textview-color4":"#0f8",
+		"textview-color5":"#0ff",
+		"textview-color6":"#fc0",
+		"textview-color7":"#fff",
+		
+		"windowClearColor":"clear",
+		"menu-shortcut":"text-background"
+	},
+	
+	"fonts":{
+	
+		"normal":"DejaVuSans.ttf,14",
+		"fixedWidth":"DejaVuSansMono.ttf,14",
+		"small":"DejaVuSans.ttf,13",
+		"editor":"DejaVuSansMono.ttf,16"
+	},
+	
+	"styles":{
+
+		"default":{
+			"font":"normal",
+			"textColor":"text-default",
+			"iconColor":"#ffff",
+			"states":{
+				"disabled":{
+					"textColor":"text-disabled",
+					"iconColor":"#8fff"
+				}
+			}
+		},
+		
+		"Label":{
+			"padding":[8,4]
+		},
+		
+		"Button":{
+			"extends":"Label",
+			"padding":[4,2],
+			"skin":"button_skin.png",
+			"skinColor":"content",
+			
+			"states":{
+				"hover":{
+					"skinColor":"hover"
+				},
+				"active":{
+					"skinColor":"active"
+				},
+				"selected":{
+					"skinColor":"active"
+				}
+			}
+		},
+		
+		"PushButton":{
+			"extends":"Button",
+			"margin":[4,4]
+		},
+		
+		"CheckButton":{
+			"extends":"Label"
+		},
+		
+		"CheckBox":{
+			"icons":"checkbox_icons.png",
+			"margin":[8,0,0,0]
+		},
+		
+		"ProgressBar":{
+			"icons":"progressbar_icons.png"
+		},
+		
+		"ScrollView":{
+		},
+		
+		"ScrollBar":{
+			"backgroundColor":"gutter"
+		},
+		
+		"ScrollKnob":{
+			"padding":[ 4 ],
+			"border":[ 1 ],
+			"borderColor":"#0000",
+			"skin":"button_skin.png",
+			"skinColor":"knob",
+			"states":{
+				"hover":{
+					"skinColor":"hover"
+				},
+				"active":{
+					"skinColor":"active"
+				}
+			}
+		},
+		
+		"TextView":{
+			"font":"editor",
+			"backgroundColor":"content"
+		},
+		
+		"TextViewContent":{
+			"padding":[4]
+		},
+		
+		"TextField":{
+			"font":"normal",
+			"padding":[ 2 ],
+			"margin":[ 2 ],
+			"skin":"button_skin.png",
+			"skinColor":"content"
+		},
+		
+		"DockingView":{
+		},
+		
+		"DockedView":{
+		},
+		
+		"DockKnob":{
+			"padding":[ 3 ],
+			"backgroundColor":"knob",
+			"states":{
+				"hover":{
+					"backgroundColor":"hover"
+				},
+				"active":{
+					"backgroundColor":"active"
+				}
+			}
+		},
+		
+		"ToolBar":{
+			"padding":[ 2 ],
+			"backgroundColor":"panel"
+		},
+		
+		"ToolButton":{
+			"extends":"Button",
+			"padding":[2,0],
+			"margin":[6,0]
+		},
+		
+		"Menu":{
+			"extends":"DockingView",
+			"padding":[ 0 ],
+			"skin":"dialog_skin.png",
+			"skinColor":"panel"
+		},
+		
+		"MenuButton":{
+			"extends":"Label",
+			"padding":[8,3],
+			"states":{
+				"hover":{
+					"backgroundColor":"hover"
+				},
+				"active":{
+					"backgroundColor":"active"
+				},
+				"selected":{
+					"backgroundColor":"active"
+				}
+			}
+		},
+		
+		"MenuBar":{
+			"extends":"ToolBar",
+			"backgroundColor":"content",
+			"margin":[ 0 ]
+		},
+		
+		"MenuSeparator":{
+			"padding":[ 0,0,0,1 ],
+			"backgroundColor":"content",
+			"border":[ 8,8,7,7 ]
+		},
+
+		"TabView":{
+		},
+		
+		"TabBar":{
+			"extends":"ToolBar",
+			"padding":[ 0,2,4,0 ],
+			"backgroundColor":"clear"
+		},
+		
+		"TabButton":{
+			"extends":"Button",
+//			"font":"small",
+			"padding":[1],
+			"margin":[2,0],
+			"backgroundColor":"#0000",
+			"skin":"tabbutton_skin.png",
+			"skinColor":"gutter",
+			"textColor":"text-background",
+			
+			"states":{
+				"hover":{
+					"skinColor":"gutter"
+				},
+				"active":{
+					"skinColor":"content"
+				},
+				"selected":{
+					"skinColor":"content",
+					"textColor":"text-default"
+				}
+			}
+		},
+		
+		"TabClose":{
+			"margin":[ 4,0,0,0 ],
+			"icons":"tabclose_icons.png",
+			"iconColor":"#cfff",
+			"states":{
+				"hover":{
+					"iconColor":"#ffff"
+				},
+				"active":{
+					"iconColor":"#ffff"
+				}
+			}
+		},
+		
+		"TableView":{
+			"extends":"DockingView"
+		},
+		
+		"TableHeader":{
+			"extends":"Label",
+			"textColor":"text-highlight",
+			"border":[0,0,0,1],
+			"borderColor":"panel"
+		},
+		
+		"TableColumn":{
+		},
+		
+		"TreeView":{
+			"backgroundColor":"content",
+			"icons":"treeview_icons.png",
+			"iconColor":"#8fff"
+		},
+		
+		"TreeViewContent":{
+			"padding":[2]
+		},
+
+		"TreeViewNode":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
+		"ListView":{
+			"backgroundColor":"content"
+		},
+		
+		"ListViewContent":{
+			"padding":[2]
+		},
+		
+		"ListViewItem":{
+			"padding":[1],
+			"states":{
+				"hover":{
+					"backgroundColor":"panel"
+				},
+				"selected":{
+					"backgroundColor":"panel",
+					"textColor":"text-highlight"
+				}
+			}
+		},
+		
+		"FileBrowser":{
+			"extends":"TreeView"
+		},
+		
+		"HtmlView":{
+		},
+		
+		"Console":{
+			"backgroundColor":"content"
+		},
+		
+		"Dialog":{
+			"skin":"dialog_skin.png",
+			"skinColor":"panel"
+		},
+		
+		"DialogTitle":{
+			"extends":"Label",
+			"backgroundColor":"knob"
+		
+		},
+		
+		"DialogContent":{
+			"padding":[ 8,8,8,4 ]
+		},
+		
+		"DialogActions":{
+			"padding":[ 8,4,8,4 ]
+		},
+
+		"GridView":{}
+	}
+}

BIN
assets/themes/docbar/back.png


BIN
assets/themes/docbar/forward.png


BIN
assets/themes/docbar/home.png


BIN
assets/themes/editorbar/back.png


BIN
assets/themes/editorbar/comment.png


BIN
assets/themes/editorbar/find_next.png


BIN
assets/themes/editorbar/find_previous.png


BIN
assets/themes/editorbar/find_selection.png


BIN
assets/themes/editorbar/forward.png


BIN
assets/themes/editorbar/last_edit.png


BIN
assets/themes/editorbar/next_bookmark.png


BIN
assets/themes/editorbar/previous_bookmark.png


BIN
assets/themes/editorbar/shift_left.png


BIN
assets/themes/editorbar/shift_right.png


BIN
assets/themes/editorbar/toggle_bookmark.png


BIN
assets/themes/editorbar/uncomment.png


BIN
assets/themes/hollow_assets/checkbox_icons.png


BIN
assets/themes/hollow_assets/dialog_skin.png


BIN
assets/themes/hollow_assets/progressbar_icons.png


BIN
assets/themes/hollow_assets/tabclose_icons.png


BIN
assets/themes/hollow_assets/treeview_icons.png


BIN
assets/themes/irc/blink.png


BIN
assets/themes/irc/important.png


BIN
assets/themes/irc/notice.png


BIN
assets/themes/outputbar/clean.png


BIN
assets/themes/outputbar/wrap.png


BIN
assets/themes/prime_assets/checkbox_icons.png


Some files were not shown because too many files changed in this diff