瀏覽代碼

Squashed 'src/ted2go/' changes from 0f6470b6..188a508b

188a508b Merge branch 'dev'
84f73667 Fixed bug with Project -- New file.
15f0adfb Merge branch 'dev'
5b976819 Updated about.html.
51645b91 Code map - now drawing by one pass.
54840df5 Improve - completion list now resized accordingly to theme scale. Updated themes images.
610fd362 Added 'Save' icon into main toolbar.
67bb690e Fix in themes.
da3daaf9 Show 'dirty' state on SaveAll toolbar icon.
4999c545 Fixed - click outside console errors list items crash.
1da79f43 Updated themes.
6a036aeb Replace icons with white-color ones. Compress all themes' icons by pngoptimizer.
cff1bac0 Macos - added shortcut Cmd+Backspace - delete line at caret.
de89a83a Done with live templates. Added option to on/off showing templates in completion list.
53dcc5d5 Added Templates into Preferences dialog.
74ba7c08 (wip) Live templates feature.
5dd9bfc0 Cleanup.
49185096 Added "Generate class" dialog.
375bf8ca Fixed project tree expanding state (when create or delete files).
7c495c5f (wip) Show clickable errors list in build console.
98c775f4 Fixed "Find text" bug (have no results for non case sensitive mode).
b795b45c Now closing related docs when close project.
9a6c71d1 Added word-wrap mode for output console.
4b3daa82 Added right-click menu for code editor.
4bafc33f Changed toolbar icons. Added cut/copy/paste button into main toolbar.
0c8eeb9c Merge branch 'dev'
1d181eac Added link to "upload module" to module manager.
52650e42 Merge branch 'redesign_find_dialog' into dev
847ef534 Done with Find entire project logic.
1ec8ca62 Merge pull request #43 from Hezkore/dev
ec96c368 IRC char limit increased to 512 (was 60)
e387e303 Merge pull request #42 from Hezkore/dev
8316318b Merge branch 'dev'
5935adcc Better chat nick notifications
da1cc5de wip Find dialog - added 'entire solution' checkbox

git-subtree-dir: src/ted2go
git-subtree-split: 188a508bd710a7a631524fc624d9ca91784846c4
Mark Sibly 8 年之前
父節點
當前提交
25374fc18b
共有 100 個文件被更改,包括 1613 次插入323 次删除
  1. 158 0
      LiveTemplates.monkey2
  2. 147 35
      MainWindow.monkey2
  3. 7 0
      Prefs.monkey2
  4. 8 7
      Ted2.monkey2
  5. 25 17
      action/BuildActions.monkey2
  6. 23 21
      action/FileActions.monkey2
  7. 226 86
      action/FindActions.monkey2
  8. 10 3
      action/HelpActions.monkey2
  9. 9 3
      assets/aboutTed2Go.html
  10. 9 0
      assets/gen/newClass.txt
  11. 30 0
      assets/liveTemplates.json
  12. 二進制
      assets/themes/cancel.png
  13. 二進制
      assets/themes/codeicons/alias.png
  14. 二進制
      assets/themes/codeicons/annotation.png
  15. 二進制
      assets/themes/codeicons/code_template.png
  16. 二進制
      assets/themes/codeicons/const.png
  17. 二進制
      assets/themes/codeicons/keyword.png
  18. 二進制
      assets/themes/codeicons/operator.png
  19. 二進制
      assets/themes/codeicons/other.png
  20. 二進制
      assets/themes/codeicons/property.png
  21. 二進制
      assets/themes/codeicons/property_private.png
  22. 二進制
      assets/themes/codeicons/property_protected.png
  23. 二進制
      assets/themes/debug_icons.png
  24. 二進制
      assets/themes/docbar/back.png
  25. 二進制
      assets/themes/docbar/forward.png
  26. 二進制
      assets/themes/docbar/home.png
  27. 二進制
      assets/themes/hollow_assets/checkbox_icons.png
  28. 二進制
      assets/themes/hollow_assets/dialog_skin.png
  29. 二進制
      assets/themes/hollow_assets/progressbar_icons.png
  30. 二進制
      assets/themes/hollow_assets/tabclose_icons.png
  31. 二進制
      assets/themes/hollow_assets/treeview_icons.png
  32. 二進制
      assets/themes/irc/blink.png
  33. 二進制
      assets/themes/irc/important.png
  34. 二進制
      assets/themes/irc/notice.png
  35. 二進制
      assets/themes/outputbar/clean.png
  36. 二進制
      assets/themes/outputbar/wrap.png
  37. 二進制
      assets/themes/prime_assets/checkbox_icons.png
  38. 二進制
      assets/themes/prime_assets/dialog_skin.png
  39. 二進制
      assets/themes/prime_assets/progressbar_icons.png
  40. 二進制
      assets/themes/prime_assets/tabclose_icons.png
  41. 二進制
      assets/themes/prime_assets/treeview_icons.png
  42. 二進制
      assets/themes/progressbar_icons.png
  43. 二進制
      assets/themes/project/package.png
  44. 二進制
      assets/themes/smooth_assets/button_skin.png
  45. 二進制
      assets/themes/smooth_assets/checkbox_icons.png
  46. 二進制
      assets/themes/smooth_assets/dialog_skin.png
  47. 二進制
      assets/themes/smooth_assets/progressbar_icons.png
  48. 二進制
      assets/themes/smooth_assets/tabbutton_selected_skin.png
  49. 二進制
      assets/themes/smooth_assets/tabbutton_skin.png
  50. 二進制
      assets/themes/smooth_assets/tabclose_icons.png
  51. 二進制
      assets/themes/smooth_assets/treeview_icons.png
  52. 二進制
      assets/themes/sourcebar/filter_inherited.png
  53. 二進制
      assets/themes/sourcebar/sort_alpha.png
  54. 25 3
      assets/themes/ted2-default.json
  55. 7 1
      assets/themes/theme-hollow.json
  56. 7 1
      assets/themes/theme-prime-base.json
  57. 二進制
      assets/themes/toolbar/back.png
  58. 二進制
      assets/themes/toolbar/build.png
  59. 二進制
      assets/themes/toolbar/check.png
  60. 二進制
      assets/themes/toolbar/copy.png
  61. 二進制
      assets/themes/toolbar/cut.png
  62. 二進制
      assets/themes/toolbar/debug.png
  63. 二進制
      assets/themes/toolbar/find.png
  64. 二進制
      assets/themes/toolbar/forward.png
  65. 二進制
      assets/themes/toolbar/navigate_back.png
  66. 二進制
      assets/themes/toolbar/navigate_forward.png
  67. 二進制
      assets/themes/toolbar/new_file.png
  68. 二進制
      assets/themes/toolbar/open_file.png
  69. 二進制
      assets/themes/toolbar/open_project.png
  70. 二進制
      assets/themes/toolbar/options.png
  71. 二進制
      assets/themes/toolbar/paste.png
  72. 二進制
      assets/themes/toolbar/paypal.png
  73. 二進制
      assets/themes/toolbar/redo.png
  74. 二進制
      assets/themes/toolbar/run.png
  75. 二進制
      assets/themes/toolbar/save.png
  76. 二進制
      assets/themes/toolbar/save_all.png
  77. 二進制
      assets/themes/toolbar/save_all_dirty.png
  78. 二進制
      assets/themes/toolbar/save_dirty.png
  79. 二進制
      assets/themes/toolbar/undo.png
  80. 二進制
      assets/themes/toolbar/zoom_in.png
  81. 二進制
      assets/themes/toolbar/zoom_out.png
  82. 19 6
      dialog/FindDialog.monkey2
  83. 186 0
      dialog/GenerateClassDialog.monkey2
  84. 66 0
      dialog/LiveTemplatesDialog.monkey2
  85. 186 1
      dialog/PrefsDialog.monkey2
  86. 0 4
      dialog/UpdateModulesDialog.monkey2
  87. 54 10
      document/CodeDocument.monkey2
  88. 5 1
      product/ModuleManager.monkey2
  89. 10 0
      utils/JsonUtils.monkey2
  90. 18 0
      utils/Utils.monkey2
  91. 99 21
      view/AutocompleteView.monkey2
  92. 21 0
      view/BuildErrorListViewItem.monkey2
  93. 24 37
      view/CodeMapView.monkey2
  94. 24 4
      view/CodeTextView.monkey2
  95. 77 45
      view/CodeTreeView.monkey2
  96. 9 0
      view/FileBrowserExt.monkey2
  97. 1 0
      view/IRCView.monkey2
  98. 36 6
      view/ListViewExt.monkey2
  99. 38 11
      view/ProjectView.monkey2
  100. 49 0
      view/Ted2CodeTextView.monkey2

+ 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

+ 147 - 35
MainWindow.monkey2

@@ -13,6 +13,7 @@ Namespace ted2go
 
 
 #Import "assets/themes/irc/@/themes/irc"
 #Import "assets/themes/irc/@/themes/irc"
 
 
+
 Global MainWindow:MainWindowInstance
 Global MainWindow:MainWindowInstance
 
 
 Class MainWindowInstance Extends Window
 Class MainWindowInstance Extends Window
@@ -27,6 +28,8 @@ Class MainWindowInstance Extends Window
 		
 		
 		UpdateToolsPaths()
 		UpdateToolsPaths()
 		
 		
+		LiveTemplates.Load()
+		
 		_docsTabView=New TabViewExt( TabViewFlags.DraggableTabs|TabViewFlags.ClosableTabs )
 		_docsTabView=New TabViewExt( TabViewFlags.DraggableTabs|TabViewFlags.ClosableTabs )
 		
 		
 		_browsersTabView=New TabView( TabViewFlags.DraggableTabs )
 		_browsersTabView=New TabView( TabViewFlags.DraggableTabs )
@@ -41,7 +44,11 @@ Class MainWindowInstance Extends Window
 		
 		
 		_docsManager=New DocumentManager( _docsTabView,_docBrowser )
 		_docsManager=New DocumentManager( _docsTabView,_docBrowser )
 
 
-		_docsManager.CurrentDocumentChanged+=UpdateKeyView
+		_docsManager.CurrentDocumentChanged+=Lambda()
+			
+			UpdateKeyView()
+			CodeDocument.HideAutocomplete()
+		End
 		
 		
 		App.FileDropped+=Lambda( path:String )
 		App.FileDropped+=Lambda( path:String )
 			_docsManager.OpenDocument( path,True )
 			_docsManager.OpenDocument( path,True )
@@ -79,16 +86,6 @@ Class MainWindowInstance Extends Window
 		Local bar:=New ToolBarExt
 		Local bar:=New ToolBarExt
 		bar.MaxSize=New Vec2i( 300,30 )
 		bar.MaxSize=New Vec2i( 300,30 )
 		
 		
-		bar.AddIconicButton(
-			ThemeImages.Get( "outputbar/clean.png" ),
-			Lambda()
-				_outputConsole.ClearAll()
-			End,
-			"Clear all" )
-		
-		'bar.AddSeparator()
-		'bar.AddSeparator()
-			
 		Local label:=New Label( "Filter:" )
 		Local label:=New Label( "Filter:" )
 		bar.AddView( label,"left" )
 		bar.AddView( label,"left" )
 		Local editFilter:=New TextField()
 		Local editFilter:=New TextField()
@@ -102,6 +99,23 @@ Class MainWindowInstance Extends Window
 			_outputConsole.SetFilter( t )
 			_outputConsole.SetFilter( t )
 		End
 		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=New DockingView
 		_outputConsoleView.AddView( bar,"top" )
 		_outputConsoleView.AddView( bar,"top" )
 		_outputConsoleView.ContentView=_outputConsole
 		_outputConsoleView.ContentView=_outputConsole
@@ -174,16 +188,23 @@ Class MainWindowInstance Extends Window
 		
 		
 		
 		
 		_buildActions=New BuildActions( _docsManager,_buildConsole,_debugView )
 		_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=New ProjectView( _docsManager,_buildActions )
 		_projectView=New ProjectView( _docsManager,_buildActions )
 		_projectView.ProjectOpened+=Lambda( dir:String )
 		_projectView.ProjectOpened+=Lambda( dir:String )
 			AddRecentProject( dir )
 			AddRecentProject( dir )
 			SaveState()
 			SaveState()
 		End
 		End
-		_projectView.ProjectClosed+=Lambda( dir:String )
-			UpdateCloseProjectMenu( dir )
-			SaveState()
-		End
+		_projectView.ProjectClosed+=OnProjectClosed
 		
 		
 		_fileActions=New FileActions( _docsManager )
 		_fileActions=New FileActions( _docsManager )
 		_editActions=New EditActions( _docsManager )
 		_editActions=New EditActions( _docsManager )
@@ -299,7 +320,8 @@ Class MainWindowInstance Extends Window
 		_forceStop.HotKeyModifiers=Modifier.Shift
 		_forceStop.HotKeyModifiers=Modifier.Shift
 		
 		
 		'
 		'
-		_buildActions.PreBuild+=OnForceStop
+		_buildActions.PreBuild+=OnPreBuild
+		_buildActions.PreSemant+=OnPreSemant
 		
 		
 		_buildMenu=New MenuExt( "Build" )
 		_buildMenu=New MenuExt( "Build" )
 		_buildMenu.AddAction( _buildActions.buildAndRun )
 		_buildMenu.AddAction( _buildActions.buildAndRun )
@@ -366,7 +388,18 @@ Class MainWindowInstance Extends Window
 		_browsersTabView.AddTab( "Debug",_debugView,False )
 		_browsersTabView.AddTab( "Debug",_debugView,False )
 		_browsersTabView.AddTab( "Help",_helpTree,False )
 		_browsersTabView.AddTab( "Help",_helpTree,False )
 		
 		
-		_consolesTabView.AddTab( "Build",_buildConsole,True )
+		_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
+		
+		_consolesTabView.AddTab( "Build",_buildConsoleView,True )
 		_consolesTabView.AddTab( "Output",_outputConsoleView,False )
 		_consolesTabView.AddTab( "Output",_outputConsoleView,False )
 		_consolesTabView.AddTab( "Docs",_helpConsole,False )
 		_consolesTabView.AddTab( "Docs",_helpConsole,False )
 		_consolesTabView.AddTab( "Find",_findConsole,False )
 		_consolesTabView.AddTab( "Find",_findConsole,False )
@@ -645,6 +678,7 @@ Class MainWindowInstance Extends Window
 		'
 		'
 		Local newTitle:=GetActionTextWithShortcut( _fileActions.new_ )
 		Local newTitle:=GetActionTextWithShortcut( _fileActions.new_ )
 		Local openTitle:=GetActionTextWithShortcut( _fileActions.open )
 		Local openTitle:=GetActionTextWithShortcut( _fileActions.open )
+		Local saveTitle:=GetActionTextWithShortcut( _fileActions.save )
 		Local saveAllTitle:=GetActionTextWithShortcut( _fileActions.saveAll )
 		Local saveAllTitle:=GetActionTextWithShortcut( _fileActions.saveAll )
 		Local undoTitle:=GetActionTextWithShortcut( _editActions.undo )
 		Local undoTitle:=GetActionTextWithShortcut( _editActions.undo )
 		Local redoTitle:=GetActionTextWithShortcut( _editActions.redo )
 		Local redoTitle:=GetActionTextWithShortcut( _editActions.redo )
@@ -653,15 +687,36 @@ Class MainWindowInstance Extends Window
 		Local checkTitle:=GetActionTextWithShortcut( _buildActions.semant )
 		Local checkTitle:=GetActionTextWithShortcut( _buildActions.semant )
 		Local findTitle:=GetActionTextWithShortcut( _findActions.find )
 		Local findTitle:=GetActionTextWithShortcut( _findActions.find )
 		Local debugTitle:=GetActionTextWithShortcut( _buildActions.debugApp )
 		Local debugTitle:=GetActionTextWithShortcut( _buildActions.debugApp )
+		Local cutTitle:=GetActionTextWithShortcut( _editActions.cut )
+		Local copyTitle:=GetActionTextWithShortcut( _editActions.copy )
+		Local pasteTitle:=GetActionTextWithShortcut( _editActions.paste )
 		
 		
 		_toolBar=New ToolBarExt
 		_toolBar=New ToolBarExt
 		_toolBar.Style=GetStyle( "MainToolBar" )
 		_toolBar.Style=GetStyle( "MainToolBar" )
 		_toolBar.MaxSize=New Vec2i( 10000,40 )
 		_toolBar.MaxSize=New Vec2i( 10000,40 )
 		
 		
+		Local goBack:=Lambda()
+			Navigator.TryBack()
+		End
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/back.png" ),goBack,"Go back (Alt+Left)" )
+		
+		Local goForw:=Lambda()
+			Navigator.TryForward()
+		End
+		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/forward.png" ),goForw,"Go forward (Alt+Right)" )
+		_toolBar.AddSeparator()
+		
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/new_file.png" ),_fileActions.new_.Triggered,newTitle )
 		_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_file.png" ),_fileActions.open.Triggered,openTitle )
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/open_project.png" ),_projectView.openProject.Triggered,"Open project..." )
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/open_project.png" ),_projectView.openProject.Triggered,"Open project..." )
-		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/save_all.png" ),_fileActions.saveAll.Triggered,saveAllTitle )
+		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.AddSeparator()
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/undo.png" ),_editActions.undo.Triggered,undoTitle )
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/undo.png" ),_editActions.undo.Triggered,undoTitle )
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/redo.png" ),_editActions.redo.Triggered,redoTitle )
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/redo.png" ),_editActions.redo.Triggered,redoTitle )
@@ -678,17 +733,6 @@ Class MainWindowInstance Extends Window
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/options.png" ),act,"Target settings" )
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/options.png" ),act,"Target settings" )
 		_toolBar.AddSeparator()
 		_toolBar.AddSeparator()
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/find.png" ),_findActions.find.Triggered,findTitle )
 		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/find.png" ),_findActions.find.Triggered,findTitle )
-		_toolBar.AddSeparator()
-		
-		Local goBack:=Lambda()
-			Navigator.TryBack()
-		End
-		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/back.png" ),goBack,"Go back (Alt+Left)" )
-		
-		Local goForw:=Lambda()
-			Navigator.TryForward()
-		End
-		_toolBar.AddIconicButton( ThemeImages.Get( "toolbar/forward.png" ),goForw,"Go forward (Alt+Right)" )
 		
 		
 		Return _toolBar
 		Return _toolBar
 	End
 	End
@@ -728,7 +772,7 @@ Class MainWindowInstance Extends Window
 	Method ShowBuildConsole( vis:Bool=True )
 	Method ShowBuildConsole( vis:Bool=True )
 		
 		
 		If vis _consolesTabView.Visible=True
 		If vis _consolesTabView.Visible=True
-		_consolesTabView.CurrentView=_buildConsole
+		_consolesTabView.CurrentView=_buildConsoleView
 	End
 	End
 	
 	
 	Method ShowOutputConsole( vis:Bool=True )
 	Method ShowOutputConsole( vis:Bool=True )
@@ -820,6 +864,21 @@ Class MainWindowInstance Extends Window
 		_helpView.Scroll=New Vec2i( 0,0 )
 		_helpView.Scroll=New Vec2i( 0,0 )
 	End
 	End
 	
 	
+	Method ShowEditorMenu( tv:TextView )
+		
+		If Not tv Then tv=_docsManager.CurrentTextView
+		If Not tv Return
+		
+		If Not _editorMenu
+			_editorMenu=New MenuExt
+			_editorMenu.AddAction( _editActions.cut )
+			_editorMenu.AddAction( _editActions.copy )
+			_editorMenu.AddAction( _editActions.paste )
+		Endif
+		
+		_editorMenu.Open()
+	End
+	
 	Method UpdateHelpTree()
 	Method UpdateHelpTree()
 		_helpTree.Update()
 		_helpTree.Update()
 	End
 	End
@@ -994,6 +1053,32 @@ Class MainWindowInstance Extends Window
 		_fileActions.quit.Trigger()
 		_fileActions.quit.Trigger()
 	End
 	End
 	
 	
+	Method OnPreBuild()
+		
+		OnForceStop()
+		_buildErrorsList.Visible=False
+	End
+	
+	Method OnPreSemant()
+	
+		_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()
 	Method OnResized()
 		
 		
 		' just set a flag here.
 		' just set a flag here.
@@ -1020,21 +1105,41 @@ Class MainWindowInstance Extends Window
 	End
 	End
 	
 	
 	Method OnChatClicked()
 	Method OnChatClicked()
+		
 		If _consolesTabView.CurrentView<>_ircView Then Return
 		If _consolesTabView.CurrentView<>_ircView Then Return
 		
 		
 		_consolesTabView.SetTabIcon( _ircView, Null )
 		_consolesTabView.SetTabIcon( _ircView, Null )
+		
 		_ircNotifyIcon=0
 		_ircNotifyIcon=0
+		
+		HideHint()
+		
 	End
 	End
 	
 	
 	Method OnChatMessage( message:IRCMessage, container:IRCMessageContainer, server:IRCServer )
 	Method OnChatMessage( message:IRCMessage, container:IRCMessageContainer, server:IRCServer )
+		
 		If message.type<>"PRIVMSG" Or _consolesTabView.CurrentView=_ircView Then Return
 		If message.type<>"PRIVMSG" Or _consolesTabView.CurrentView=_ircView Then Return
 		
 		
 		'Show notice icon
 		'Show notice icon
 		If message.text.Contains(server.nickname) Then
 		If message.text.Contains(server.nickname) Then
-			If _ircNotifyIcon<=1 Then _ircNotifyIcon=2
-	
+			
+			If _ircNotifyIcon<=1 Then
+				
+				_ircNotifyIcon=2
+				
+				Local mentionStr:String
+				mentionStr=server.nickname+" was mentioned by "
+				mentionStr+=message.fromUser+" in "
+				mentionStr+=container.name
+				
+				ShowHint( mentionStr, New Vec2i( 0, -GetStyle( "Hint" ).Font.Height*4 ), _consolesTabView, 20000 )
+				
+			Endif
+			
 		Else
 		Else
+			
 			If _ircNotifyIcon<=0 Then _ircNotifyIcon=1
 			If _ircNotifyIcon<=0 Then _ircNotifyIcon=1
+			
 		Endif
 		Endif
 		
 		
 	End
 	End
@@ -1166,6 +1271,8 @@ Class MainWindowInstance Extends Window
 	Field _modsDir:String
 	Field _modsDir:String
 	
 	
 	Field _toolBar:ToolBarExt
 	Field _toolBar:ToolBarExt
+	Field _saveItem:MultiIconToolButton
+	Field _saveAllItem:MultiIconToolButton
 	Field _docsManager:DocumentManager
 	Field _docsManager:DocumentManager
 	Field _fileActions:FileActions
 	Field _fileActions:FileActions
 	Field _editActions:EditActions
 	Field _editActions:EditActions
@@ -1176,6 +1283,8 @@ Class MainWindowInstance Extends Window
 	
 	
 	Field _ircView:IRCView
 	Field _ircView:IRCView
 	Field _buildConsole:ConsoleExt
 	Field _buildConsole:ConsoleExt
+	Field _buildErrorsList:ListViewExt
+	Field _buildConsoleView:DockingView
 	Field _outputConsole:ConsoleExt
 	Field _outputConsole:ConsoleExt
 	Field _outputConsoleView:DockingView
 	Field _outputConsoleView:DockingView
 	Field _helpView:HtmlViewExt
 	Field _helpView:HtmlViewExt
@@ -1207,7 +1316,7 @@ Class MainWindowInstance Extends Window
 	Field _windowMenu:MenuExt
 	Field _windowMenu:MenuExt
 	Field _helpMenu:MenuExt
 	Field _helpMenu:MenuExt
 	Field _menuBar:MenuBarExt
 	Field _menuBar:MenuBarExt
-	
+	Field _editorMenu:MenuExt
 	Field _themesMenu:MenuExt
 	Field _themesMenu:MenuExt
 	
 	
 	Field _theme:="default"
 	Field _theme:="default"
@@ -1404,6 +1513,9 @@ Class MainWindowInstance Extends Window
 		
 		
 		_forceStop.Enabled=_buildConsole.Running Or _outputConsole.Running
 		_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
 		App.Idle+=OnAppIdle
 		
 		
 		GCCollect()	'thrash that GC!
 		GCCollect()	'thrash that GC!
@@ -1414,7 +1526,7 @@ Class MainWindowInstance Extends Window
 		Select _consolesTabView.CurrentView
 		Select _consolesTabView.CurrentView
 			Case _outputConsoleView
 			Case _outputConsoleView
 				Return "output"
 				Return "output"
-			Case _buildConsole
+			Case _buildConsoleView
 				Return "build"
 				Return "build"
 			Case _helpConsole
 			Case _helpConsole
 				Return "docs"
 				Return "docs"
@@ -1431,7 +1543,7 @@ Class MainWindowInstance Extends Window
 			Case "output"
 			Case "output"
 				view=_outputConsoleView
 				view=_outputConsoleView
 			Case "build"
 			Case "build"
-				view=_buildConsole
+				view=_buildConsoleView
 			Case "docs"
 			Case "docs"
 				view=_helpConsole
 				view=_helpConsole
 			Case "find"
 			Case "find"

+ 7 - 0
Prefs.monkey2

@@ -13,6 +13,7 @@ Class Prefs
 	Global AcUseDot:=False
 	Global AcUseDot:=False
 	Global AcNewLineByEnter:=True
 	Global AcNewLineByEnter:=True
 	Global AcStrongFirstChar:=True
 	Global AcStrongFirstChar:=True
+	Global AcUseLiveTemplates:=True
 	'
 	'
 	Global MainToolBarVisible:=True
 	Global MainToolBarVisible:=True
 	Global MainProjectTabsRight:=True
 	Global MainProjectTabsRight:=True
@@ -37,6 +38,7 @@ Class Prefs
 	Global SourceShowInherited:=False
 	Global SourceShowInherited:=False
 	'
 	'
 	Global MonkeyRootPath:String
 	Global MonkeyRootPath:String
+	Global IdeHomeDir:String
 	
 	
 	Function LoadState( json:JsonObject )
 	Function LoadState( json:JsonObject )
 		
 		
@@ -71,6 +73,7 @@ Class Prefs
 			AcUseSpace=Json_GetBool( j2,"useSpace",AcUseSpace )
 			AcUseSpace=Json_GetBool( j2,"useSpace",AcUseSpace )
 			AcUseDot=Json_GetBool( j2,"useDot",AcUseDot )
 			AcUseDot=Json_GetBool( j2,"useDot",AcUseDot )
 			AcNewLineByEnter=Json_GetBool( j2,"newLineByEnter",AcNewLineByEnter )
 			AcNewLineByEnter=Json_GetBool( j2,"newLineByEnter",AcNewLineByEnter )
+			AcUseLiveTemplates=Json_GetBool( j2,"useLiveTemplates",AcUseLiveTemplates )
 			
 			
 		Endif
 		Endif
 		
 		
@@ -123,6 +126,7 @@ Class Prefs
 		j["useSpace"]=New JsonBool( AcUseSpace )
 		j["useSpace"]=New JsonBool( AcUseSpace )
 		j["useDot"]=New JsonBool( AcUseDot )
 		j["useDot"]=New JsonBool( AcUseDot )
 		j["newLineByEnter"]=New JsonBool( AcNewLineByEnter )
 		j["newLineByEnter"]=New JsonBool( AcNewLineByEnter )
+		j["useLiveTemplates"]=New JsonBool( AcUseLiveTemplates )
 		
 		
 		j=New JsonObject
 		j=New JsonObject
 		json["editor"]=j
 		json["editor"]=j
@@ -144,6 +148,9 @@ Class Prefs
 	
 	
 	Function LoadLocalState()
 	Function LoadLocalState()
 		
 		
+		IdeHomeDir=HomeDir()+"Ted2Go/"
+		CreateDir( IdeHomeDir )
+		
 		Local json:=JsonObject.Load( AppDir()+"state.json" )
 		Local json:=JsonObject.Load( AppDir()+"state.json" )
 		If Not json Return
 		If Not json Return
 		
 		

+ 8 - 7
Ted2.monkey2

@@ -34,6 +34,8 @@
 #Import "dialog/NoTitleDialog"
 #Import "dialog/NoTitleDialog"
 #Import "dialog/FindInFilesDialog"
 #Import "dialog/FindInFilesDialog"
 #Import "dialog/UpdateModulesDialog"
 #Import "dialog/UpdateModulesDialog"
+#Import "dialog/GenerateClassDialog"
+#Import "dialog/LiveTemplateDialog"
 
 
 #Import "document/DocumentManager"
 #Import "document/DocumentManager"
 #Import "document/Ted2Document"
 #Import "document/Ted2Document"
@@ -93,18 +95,22 @@
 #Import "view/ProjectView"
 #Import "view/ProjectView"
 #Import "view/HelpTreeView"
 #Import "view/HelpTreeView"
 #Import "view/Ted2TextView"
 #Import "view/Ted2TextView"
+#Import "view/Ted2CodeTextView"
 #Import "view/JsonTreeView"
 #Import "view/JsonTreeView"
 #Import "view/XmlTreeView"
 #Import "view/XmlTreeView"
 #Import "view/Monkey2TreeView"
 #Import "view/Monkey2TreeView"
 #Import "view/GutterView"
 #Import "view/GutterView"
 #Import "view/MenuExt"
 #Import "view/MenuExt"
 #Import "view/ScrollableViewExt"
 #Import "view/ScrollableViewExt"
+#Import "view/BuildErrorListViewItem"
+#Import "view/TextFieldExt"
 
 
-#Import "MainWindow"
 #Import "Plugin"
 #Import "Plugin"
 #Import "ThemeImages"
 #Import "ThemeImages"
 #Import "Prefs"
 #Import "Prefs"
 #Import "ProcessReader"
 #Import "ProcessReader"
+#Import "LiveTemplates"
+#Import "MainWindow"
 
 
 
 
 Namespace ted2go
 Namespace ted2go
@@ -117,7 +123,7 @@ Using tinyxml2..
 
 
 Const MONKEY2_DOMAIN:="http://monkeycoder.co.nz"
 Const MONKEY2_DOMAIN:="http://monkeycoder.co.nz"
 
 
-Global AppTitle:="Ted2Go v2.4"
+Global AppTitle:="Ted2Go v2.5"
 
 
 
 
 Function Main()
 Function Main()
@@ -231,11 +237,6 @@ Function GetActionTextWithShortcut:String( action:Action )
 	Return action.Text+" ("+action.HotKeyText+")"
 	Return action.Text+" ("+action.HotKeyText+")"
 End
 End
 
 
-Function IsFileExists:Bool( path:String )
-	
-	Return GetFileType( path ) = FileType.File
-End
-
 Function Exec( exePath:String,args:String="" )
 Function Exec( exePath:String,args:String="" )
 
 
 #If __HOSTOS__="windows"
 #If __HOSTOS__="windows"

+ 25 - 17
action/BuildActions.monkey2

@@ -48,6 +48,8 @@ Class BuildActions Implements IModuleBuilder
 	
 	
 	
 	
 	Field PreBuild:Void()
 	Field PreBuild:Void()
+	Field PreSemant:Void()
+	Field ErrorsOccured:Void(errors:BuildError[])
 	
 	
 	Method New( docs:DocumentManager,console:ConsoleExt,debugView:DebugView )
 	Method New( docs:DocumentManager,console:ConsoleExt,debugView:DebugView )
 	
 	
@@ -326,6 +328,19 @@ Class BuildActions Implements IModuleBuilder
 		Return result
 		Return result
 	End
 	End
 	
 	
+	Method GotoError( err:BuildError )
+	
+		Local doc:=Cast<CodeDocument>( _docs.OpenDocument( err.path,True ) )
+		If Not doc Return
+	
+		Local tv := doc.TextView
+		If Not tv Return
+	
+		MainWindow.UpdateWindow( False )
+	
+		tv.GotoLine( err.line )
+	End
+	
 	
 	
 	Private
 	Private
 	
 	
@@ -379,19 +394,6 @@ Class BuildActions Implements IModuleBuilder
 
 
 	End
 	End
 
 
-	Method GotoError( err:BuildError )
-	
-		Local doc:=Cast<CodeDocument>( _docs.OpenDocument( err.path,True ) )
-		If Not doc Return
-		
-		Local tv := doc.TextView
-		If Not tv Return
-		
-		MainWindow.UpdateWindow( False )
-		
-		tv.GotoLine( err.line )
-	End
-	
 	Method BuildMx2:Bool( cmd:String,progressText:String,action:String="build",showElapsedTime:Bool=False )
 	Method BuildMx2:Bool( cmd:String,progressText:String,action:String="build",showElapsedTime:Bool=False )
 	
 	
 		ClearErrors()
 		ClearErrors()
@@ -445,10 +447,10 @@ Class BuildActions Implements IModuleBuilder
 						
 						
 						If doc
 						If doc
 							doc.AddError( err )
 							doc.AddError( err )
-							If _errors.Empty 
-								MainWindow.ShowBuildConsole( True )
-								GotoError( err )
-							Endif
+							'If _errors.Empty
+							'	MainWindow.ShowBuildConsole( True )
+							'	GotoError( err )
+							'Endif
 							_errors.Add( err )
 							_errors.Add( err )
 						Endif
 						Endif
 						
 						
@@ -465,6 +467,10 @@ Class BuildActions Implements IModuleBuilder
 		
 		
 		Forever
 		Forever
 		
 		
+		If Not _errors.Empty
+			ErrorsOccured( _errors.ToArray() )
+		Endif
+		
 		MainWindow.HideStatusBarProgress()
 		MainWindow.HideStatusBarProgress()
 		
 		
 		Local status:=hasErrors ? "{0} failed. See the build console for details." Else (_console.ExitCode=0 ? "{0} finished." Else "{0} cancelled.")
 		Local status:=hasErrors ? "{0} failed. See the build console for details." Else (_console.ExitCode=0 ? "{0} finished." Else "{0} cancelled.")
@@ -591,6 +597,8 @@ Class BuildActions Implements IModuleBuilder
 	
 	
 	Method OnSemant()
 	Method OnSemant()
 	
 	
+		PreSemant()
+		
 		If _console.Running Return
 		If _console.Running Return
 	
 	
 		BuildApp( _buildConfig,_buildTarget,"semant" )
 		BuildApp( _buildConfig,_buildTarget,"semant" )

+ 23 - 21
action/FileActions.monkey2

@@ -20,7 +20,7 @@ Class FileActions
 	
 	
 		_docs=docs
 		_docs=docs
 		
 		
-		new_=New Action( "New" )
+		new_=New Action( "New file" )
 #if __TARGET__="macos"
 #if __TARGET__="macos"
 		new_.HotKey=Key.T
 		new_.HotKey=Key.T
 		new_.HotKeyModifiers=Modifier.Menu
 		new_.HotKeyModifiers=Modifier.Menu
@@ -30,7 +30,7 @@ Class FileActions
 #endif
 #endif
 		new_.Triggered=OnNew
 		new_.Triggered=OnNew
 		
 		
-		open=New Action( "Open" )
+		open=New Action( "Open file" )
 		open.HotKey=Key.O
 		open.HotKey=Key.O
 		open.HotKeyModifiers=Modifier.Menu
 		open.HotKeyModifiers=Modifier.Menu
 		open.Triggered=OnOpen
 		open.Triggered=OnOpen
@@ -47,7 +47,9 @@ Class FileActions
 		closeToRight.Triggered=OnCloseToRight
 		closeToRight.Triggered=OnCloseToRight
 		
 		
 		closeAll=New Action( "Close all tabs" )
 		closeAll=New Action( "Close all tabs" )
-		closeAll.Triggered=OnCloseAll
+		closeAll.Triggered=Lambda()
+			CloseFiles( _docs.OpenDocuments )
+		End
 		
 		
 		save=New Action( "Save" )
 		save=New Action( "Save" )
 		save.HotKey=Key.S
 		save.HotKey=Key.S
@@ -109,6 +111,23 @@ Class FileActions
 		saveAll.Enabled=anyDirty
 		saveAll.Enabled=anyDirty
 	End
 	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
 	Private
 	
 	
@@ -210,7 +229,7 @@ Class FileActions
 		If Not doc Return
 		If Not doc Return
 		
 		
 		doc=CanClose( doc )
 		doc=CanClose( doc )
-		If Not doc return
+		If Not doc Return
 		
 		
 		doc.Close()
 		doc.Close()
 	End
 	End
@@ -264,23 +283,6 @@ Class FileActions
 		
 		
 	End
 	End
 	
 	
-	Method OnCloseAll()
-
-		_saveAllFlag=False
-		_discardAllFlag=False
-		
-		Local docs:=_docs.OpenDocuments
-		
-		For Local doc:=Eachin docs
-			If Not CanClose( doc,True ) Return
-		Next
-		
-		For Local doc:=Eachin docs
-			doc.Close()
-		Next
-		
-	End
-	
 	Method OnSave()
 	Method OnSave()
 	
 	
 		Local doc:=_docs.CurrentDocument
 		Local doc:=_docs.CurrentDocument

+ 226 - 86
action/FindActions.monkey2

@@ -16,8 +16,9 @@ Class FindActions
 		
 		
 		_docs=docs
 		_docs=docs
 		_findConsole=findConsole
 		_findConsole=findConsole
+		_projView=projView
 		
 		
-		find=New Action( "Find / Replace" )
+		find=New Action( "Find / Replace..." )
 		find.Triggered=OnFind
 		find.Triggered=OnFind
 		find.HotKey=Key.F
 		find.HotKey=Key.F
 		find.HotKeyModifiers=Modifier.Menu
 		find.HotKeyModifiers=Modifier.Menu
@@ -60,9 +61,9 @@ Class FindActions
 		replaceAll.Enabled=tv
 		replaceAll.Enabled=tv
 	End
 	End
 	
 	
-	Method FindByTextChanged()
+	Method FindByTextChanged( entireProject:Bool )
 		
 		
-		OnFindNext( False )
+		If Not entireProject Then OnFindNext( False )
 	End
 	End
 	
 	
 	
 	
@@ -74,6 +75,7 @@ Class FindActions
 	Field _findInFilesDialog:FindInFilesDialog
 	Field _findInFilesDialog:FindInFilesDialog
 	Field _findConsole:TreeViewExt
 	Field _findConsole:TreeViewExt
 	Field _cursorPos:=0
 	Field _cursorPos:=0
+	Field _projView:ProjectView
 	
 	
 	Method OnFind()
 	Method OnFind()
 		
 		
@@ -106,40 +108,165 @@ Class FindActions
 		Endif
 		Endif
 	End
 	End
 	
 	
+	Field _storedTextView:TextView
+	Field _storedWhat:String
+	Field _storedCaseSens:Bool
+	Field _storedEntireProject:Bool
+	Field _results:Stack<FileJumpData>
+	Field _resultIndex:Int=-1
+	
 	Method OnFindNext( changeCursorPos:Bool=True )
 	Method OnFindNext( changeCursorPos:Bool=True )
 	
 	
-		Local tv:=_docs.CurrentTextView
+		Local doc:=_docs.CurrentDocument
+		If Not doc Return
+		
+		Local tv:=doc.TextView
 		If Not tv Return
 		If Not tv Return
 		
 		
-		Local text:=_findDialog.FindText
-		If Not text Return
+		Local what:=_findDialog.FindText
+		If Not what Return
 		
 		
-		Local tvtext:=tv.Text
+		Local sens:=_findDialog.CaseSensitive
+		
+		If Not sens
+			what=what.ToLower()
+		Endif
+		
+		Local entire:=_findDialog.EntireProject
+		
+		' when typing request word we should everytime find from current cursor
 		Local cursor:=_cursorPos
 		Local cursor:=_cursorPos
 		If changeCursorPos
 		If changeCursorPos
 			cursor=Max( tv.Anchor,tv.Cursor )
 			cursor=Max( tv.Anchor,tv.Cursor )
 			_cursorPos=cursor
 			_cursorPos=cursor
 		Endif
 		Endif
 		
 		
-		If Not _findDialog.CaseSensitive
-			tvtext=tvtext.ToLower()
-			text=text.ToLower()
+		Local theSame:=(what=_storedWhat And sens=_storedCaseSens And entire=_storedEntireProject)
+		
+		If Not entire Then theSame=theSame And tv=_storedTextView
+		
+		_storedWhat=what
+		_storedTextView=tv
+		_storedCaseSens=sens
+		_storedEntireProject=entire
+		
+		If Not theSame Then _results=Null
+		
+		If _results
+			' use current search results
+			If Not _results.Empty
+				_resultIndex=(_resultIndex+1) Mod _results.Length
+			Endif
+			
+		Else
+			
+			_resultIndex=-1
+			
+			' start new search
+			If entire
+				
+				Local proj:=""
+				For Local p:=Eachin _projView.OpenProjects
+					If doc.Path.Contains( p )
+						proj=p
+						Exit
+					Endif
+				End
+				Local map:=FindInProject( what,proj,sens )
+				If map
+					CreateResultTree( _findConsole.RootNode,map,what,proj )
+					MainWindow.ShowFindResults()
+				Endif
+				
+				If Not map.Empty
+					
+					_results=New Stack<FileJumpData>
+					
+					' make current opened document as a first results
+					Local curPath:=_docs.CurrentDocument ? _docs.CurrentDocument.Path Else ""
+					If curPath
+						Local vals:=map[curPath]
+						If vals
+							_results.AddAll( vals )
+							map.Remove( curPath )
+						Endif
+					Endif
+					
+					For Local items:=Eachin map.Values
+						_results.AddAll( items )
+					End
+					_resultIndex=0
+				Endif
+				
+			Else
+				
+				_results=FindInFile( "",what,sens,tv.Document )
+				
+				If Not _results.Empty
+					' take the first result accordingly to cursor
+					For Local i:=0 Until _results.Length
+						Local jump:=_results[i]
+						If jump.pos>=cursor
+							_resultIndex=i
+							Exit
+						Endif
+					Next
+					If _resultIndex=-1 Then _resultIndex=0 ' take from top of doc
+				Endif
+				
+			Endif
+			
 		Endif
 		Endif
 		
 		
-		Local i:=tvtext.Find( text,cursor )
-		If i=-1
-			i=tvtext.Find( text )
-			If i=-1 Return
+		If _resultIndex>=0
+			
+			Local jump:=_results[_resultIndex]
+			
+			If _storedEntireProject
+				MainWindow.OpenDocument( jump.path )
+				tv=_docs.CurrentTextView
+			Endif
+			
+			If tv Then tv.SelectText( jump.pos,jump.pos+jump.len )
+			
 		Endif
 		Endif
 		
 		
-		tv.SelectText( i,i+text.Length )
+	End
+	
+	Method OnFindPrevious()
+		
+		If _resultIndex>=0
+			
+			Local tv:=_docs.CurrentTextView
+			If Not tv Return
+			
+			_resultIndex-=1
+			If _resultIndex<0 Then _resultIndex=_results.Length-1
+			
+			Local jump:=_results[_resultIndex]
+			
+			If _storedEntireProject
+				MainWindow.OpenDocument( jump.path )
+				tv=_docs.CurrentTextView
+			Endif
+			
+			If tv Then tv.SelectText( jump.pos,jump.pos+jump.len )
+			
+		Endif
+	
 	End
 	End
 	
 	
 	Method OnFindAllInFiles()
 	Method OnFindAllInFiles()
 	
 	
-		If Not _findInFilesDialog.FindText Return
+		If Not _findInFilesDialog.FindText
+			ShowMessage( "","Please, enter text to find what." )
+			Return
+		Endif
 		
 		
-		If Not _findInFilesDialog.SelectedProject Return
+		If Not _findInFilesDialog.SelectedProject
+			ShowMessage( "","Please, select project in the list." )
+			Return
+		Endif
 		
 		
 		_findInFilesDialog.Hide()
 		_findInFilesDialog.Hide()
 		MainWindow.ShowFindResults()
 		MainWindow.ShowFindResults()
@@ -148,119 +275,132 @@ Class FindActions
 			
 			
 			New Fiber( Lambda()
 			New Fiber( Lambda()
 			
 			
-				FindInFilesInternal()
+				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)
 		End
 		End
 		
 		
 	End
 	End
 	
 	
-	Method FindInFilesInternal()
-		
-		Local what:=_findInFilesDialog.FindText
-		If Not what Return
-		
-		Local proj:=_findInFilesDialog.SelectedProject
-		If Not proj Return
-		
-		Local filter:=_findInFilesDialog.FilterText
-		If Not filter Then filter="monkey2"
+	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 )
 		
 		
-		Local exts:=filter.Split( "," )
+		If Not filesFilter Then filesFilter=DEFAULT_FILES_FILTER
 		
 		
-		proj+="/"
+		Local exts:=filesFilter.Split( "," )
 		
 		
-		Local sens:=_findInFilesDialog.CaseSensitive
+		projectPath+="/"
 		
 		
-		If Not sens Then what=what.ToLower()
+		If Not caseSensitive Then what=what.ToLower()
 		
 		
 		Local files:=New Stack<String>
 		Local files:=New Stack<String>
-		Utils.GetAllFiles( proj,exts,files )
-		
-		Local root:=_findConsole.RootNode
-		root.RemoveAllChildren()
+		Utils.GetAllFiles( projectPath,exts,files )
 		
 		
-		root.Text="Results for '"+what+"'"
-		
-		Local subRoot:TreeView.Node
-		Local items:=New Stack<FileJumpData>
 		Local len:=what.Length
 		Local len:=what.Length
 		
 		
+		Local result:=New StringMap<Stack<FileJumpData>>
+		
 		Local doc:=New TextDocument 'use it to get line number
 		Local doc:=New TextDocument 'use it to get line number
 		For Local f:=Eachin files
 		For Local f:=Eachin files
 		
 		
 			Local text:=LoadString( f )
 			Local text:=LoadString( f )
 		
 		
-			If Not sens Then text=text.ToLower()
-			text=text.Replace( "~r~n","~n" )
-			text=text.Replace( "~r","~n" )
+			If Not caseSensitive Then text=text.ToLower()
 		
 		
-			doc.Text=text
+			doc.Text=text 'any needed replacing is here (\r\n -> \n)
+			text=doc.Text
 		
 		
 			Local i:=0
 			Local i:=0
-			items.Clear()
-		
+			Local items:=New Stack<FileJumpData>
+			
 			Repeat
 			Repeat
 				i=text.Find( what,i )
 				i=text.Find( what,i )
 				If i=-1 Exit
 				If i=-1 Exit
-		
+				
 				Local data:=New FileJumpData
 				Local data:=New FileJumpData
 				data.path=f
 				data.path=f
 				data.pos=i
 				data.pos=i
 				data.len=len
 				data.len=len
 				data.line=doc.FindLine( i )+1
 				data.line=doc.FindLine( i )+1
-		
+				
 				items.Add( data )
 				items.Add( data )
-		
+				
 				i+=len
 				i+=len
 			Forever
 			Forever
-		
-			If Not items.Empty
-		
-				subRoot=New TreeView.Node( f.Replace( proj,"" )+" ("+items.Length+")",root )
-		
-				For Local d:=Eachin items
-					Local node:=New NodeWithData<FileJumpData>( " at line "+d.line,subRoot )
-					node.data=d
-				Next
-		
-			Endif
+			
+			If Not items.Empty Then result[f]=items
+			
 		Next
 		Next
 		
 		
-		If root.NumChildren=0 Then New TreeView.Node( "not found :(",root )
-		
-		root.Expanded=True
+		Return result
 	End
 	End
 	
 	
-	Method OnFindPrevious()
+	Method FindInFile:Stack<FileJumpData>( filePath:String,what:String,caseSensitive:Bool,doc:TextDocument=Null )
 	
 	
-		Local tv:=_docs.CurrentTextView
-		If Not tv Return
+		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 text:=_findDialog.FindText
-		If Not text Return
+			Local data:=New FileJumpData
+			data.path=filePath
+			data.pos=i
+			data.len=len
+			data.line=doc.FindLine( i )+1
 
 
-		Local tvtext:=tv.Text
-		Local cursor:=Min( tv.Anchor,tv.Cursor )
+			result.Add( data )
+
+			i+=len
+		Forever
+
+		Return result
+	End
+	
+	Method CreateResultTree( root:TreeView.Node,map:StringMap<Stack<FileJumpData>>,what:String,projectPath:String )
 		
 		
-		If Not _findDialog.CaseSensitive
-			tvtext=tvtext.ToLower()
-			text=text.ToLower()
-		Endif
+		root.RemoveAllChildren()
 		
 		
-		Local i:=tvtext.Find( text )
-		If i=-1 Return
+		root.Text="Results for '"+what+"'"
 		
 		
-		If i>=cursor
-			i=tvtext.FindLast( text )
-		Else
-			Repeat
-				Local n:=tvtext.Find( text,i+text.Length )
-				If n>=cursor Exit
-				i=n
-			Forever
-		End
+		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
 		
 		
-		tv.SelectText( i,i+text.Length )
 	End
 	End
 	
 	
 	Method OnReplace()
 	Method OnReplace()

+ 10 - 3
action/HelpActions.monkey2

@@ -36,9 +36,7 @@ Class HelpActions
 		uploadModules=New Action( "Upload module" )
 		uploadModules=New Action( "Upload module" )
 		uploadModules.Triggered=Lambda()
 		uploadModules.Triggered=Lambda()
 		
 		
-			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/" ) )
+			GotoUploadModulesPage()
 		End
 		End
 
 
 		about=New Action( "About monkey2" )
 		about=New Action( "About monkey2" )
@@ -103,3 +101,12 @@ Class HelpActions
 	End
 	End
 	
 	
 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

+ 9 - 3
assets/aboutTed2Go.html

@@ -60,8 +60,13 @@ It is based on real parsing of sources, parse all modules and user's code.<br>
 Shows code structure, gives us comfortable code jumping.
 Shows code structure, gives us comfortable code jumping.
 </li>
 </li>
 <br>
 <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>
 <li><b>Goto definition</b><br>
-Press F12 to goto definition of ident under cursor.
+Press F12 (or F2) to goto definition of ident under cursor.
 </li>
 </li>
 <br>
 <br>
 <li><b>Parsing on-the-fly</b><br>
 <li><b>Parsing on-the-fly</b><br>
@@ -115,12 +120,13 @@ Enjoy coding!</p>
 
 
 <h3>Third party</h3>
 <h3>Third party</h3>
 
 
-<p>Almost all icons for CodeTree were taken from Netbeans IDE.</p>
+<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>
 <h3>Special Thanks</h3>
 
 
-<p>Sal Gunduz, Peter Scheutz, Matthieu Chemin, David Maziarka, Leonardo Teixeira, Jesus Perez, Mark Sibly, Philipp Moeller, Lee Wade.</p>
+<p>Hezkore, Sal Gunduz, Peter Scheutz, Matthieu Chemin, David Maziarka, Leonardo Teixeira, Jesus Perez, Mark Sibly, Philipp Moeller, Lee Wade.</p>
 
 
 </body>
 </body>
 
 

+ 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}.Lenght-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"
+	}
+}

二進制
assets/themes/cancel.png


二進制
assets/themes/codeicons/alias.png


二進制
assets/themes/codeicons/annotation.png


二進制
assets/themes/codeicons/code_template.png


二進制
assets/themes/codeicons/const.png


二進制
assets/themes/codeicons/keyword.png


二進制
assets/themes/codeicons/operator.png


二進制
assets/themes/codeicons/other.png


二進制
assets/themes/codeicons/property.png


二進制
assets/themes/codeicons/property_private.png


二進制
assets/themes/codeicons/property_protected.png


二進制
assets/themes/debug_icons.png


二進制
assets/themes/docbar/back.png


二進制
assets/themes/docbar/forward.png


二進制
assets/themes/docbar/home.png


二進制
assets/themes/hollow_assets/checkbox_icons.png


二進制
assets/themes/hollow_assets/dialog_skin.png


二進制
assets/themes/hollow_assets/progressbar_icons.png


二進制
assets/themes/hollow_assets/tabclose_icons.png


二進制
assets/themes/hollow_assets/treeview_icons.png


二進制
assets/themes/irc/blink.png


二進制
assets/themes/irc/important.png


二進制
assets/themes/irc/notice.png


二進制
assets/themes/outputbar/clean.png


二進制
assets/themes/outputbar/wrap.png


二進制
assets/themes/prime_assets/checkbox_icons.png


二進制
assets/themes/prime_assets/dialog_skin.png


二進制
assets/themes/prime_assets/progressbar_icons.png


二進制
assets/themes/prime_assets/tabclose_icons.png


二進制
assets/themes/prime_assets/treeview_icons.png


二進制
assets/themes/progressbar_icons.png


二進制
assets/themes/project/package.png


二進制
assets/themes/smooth_assets/button_skin.png


二進制
assets/themes/smooth_assets/checkbox_icons.png


二進制
assets/themes/smooth_assets/dialog_skin.png


二進制
assets/themes/smooth_assets/progressbar_icons.png


二進制
assets/themes/smooth_assets/tabbutton_selected_skin.png


二進制
assets/themes/smooth_assets/tabbutton_skin.png


二進制
assets/themes/smooth_assets/tabclose_icons.png


二進制
assets/themes/smooth_assets/treeview_icons.png


二進制
assets/themes/sourcebar/filter_inherited.png


二進制
assets/themes/sourcebar/sort_alpha.png


+ 25 - 3
assets/themes/ted2-default.json

@@ -10,7 +10,7 @@
 		"statusbar-active": "#CA5100",
 		"statusbar-active": "#CA5100",
 		"menu-shortcut":"text-background",
 		"menu-shortcut":"text-background",
 		"codemap-background": "transparent",
 		"codemap-background": "transparent",
-		"codemap-selection": "#48000000"
+		"codemap-selection": "#48000000"		
 	},
 	},
 
 
 	"fonts":{
 	"fonts":{
@@ -20,7 +20,8 @@
 	},
 	},
 	
 	
 	"styles":{
 	"styles":{
-	
+				
+
 		"GutterView":{
 		"GutterView":{
 			"extends":"TextView",
 			"extends":"TextView",
 			"textColor":"text-disabled",
 			"textColor":"text-disabled",
@@ -51,7 +52,8 @@
 			"margin":[ 0 ],
 			"margin":[ 0 ],
 			"backgroundColor":"content",
 			"backgroundColor":"content",
 			"border":[ 0,0,0,1 ],
 			"border":[ 0,0,0,1 ],
-			"borderColor":"clear"
+			"borderColor":"clear",
+			"iconColor":"#f00"
 		},
 		},
 
 
 		"MainToolBar":{
 		"MainToolBar":{
@@ -72,6 +74,11 @@
 			"margin":[ 3,0 ]
 			"margin":[ 3,0 ]
 		},
 		},
 
 
+		"ColoredToolButton":{
+			"extends":"ToolButton",
+			"iconColor":"#6A92CF"
+		},
+
 		"TabViewArrowPrev":{
 		"TabViewArrowPrev":{
 			"extends":"Button",
 			"extends":"Button",
 			"padding":[ 4,1 ],
 			"padding":[ 4,1 ],
@@ -162,6 +169,21 @@
 		"BananasDescription":{
 		"BananasDescription":{
 			"extends":"TextView",
 			"extends":"TextView",
 			"font":"normal"
 			"font":"normal"
+		},
+
+		"MenuButton":{
+			"extends":"Label",
+			"states":{
+				"hover":{
+					"backgroundColor":"hover"
+				},
+				"active":{
+					"backgroundColor":"active"
+				},
+				"selected":{
+					"backgroundColor":"active"
+				}
+			}
 		}
 		}
 	}
 	}
 }
 }

+ 7 - 1
assets/themes/theme-hollow.json

@@ -173,7 +173,8 @@
 		"StatusBarButton":{
 		"StatusBarButton":{
 			"extends":"ToolButton",
 			"extends":"ToolButton",
 			"padding":[ 0 ],
 			"padding":[ 0 ],
-			"skinColor":"transparent"
+			"skinColor":"transparent",
+			"backgroundColor":"transparent"
 		},
 		},
 		
 		
 		"Label":{
 		"Label":{
@@ -469,6 +470,11 @@
 		
 		
 		"DialogActions":{
 		"DialogActions":{
 			"padding":[ 8,4,8,4 ]
 			"padding":[ 8,4,8,4 ]
+		},
+		
+		"ColoredToolButton":{
+			"extends":"ToolButton",
+			"iconColor":"text-default"
 		}
 		}
 	}
 	}
 }
 }

+ 7 - 1
assets/themes/theme-prime-base.json

@@ -183,7 +183,8 @@
 		"StatusBarButton":{
 		"StatusBarButton":{
 			"extends":"ToolButton",
 			"extends":"ToolButton",
 			"padding":[ 0 ],
 			"padding":[ 0 ],
-			"skinColor":"transparent"
+			"skinColor":"transparent",
+			"backgroundColor":"transparent"
 		},
 		},
 		
 		
 		"Label":{
 		"Label":{
@@ -459,6 +460,11 @@
 		
 		
 		"DialogActions":{
 		"DialogActions":{
 			"padding":[ 8,4,8,4 ]
 			"padding":[ 8,4,8,4 ]
+		},
+		
+		"ColoredToolButton":{
+			"extends":"ToolButton",
+			"iconColor":"text-default"
 		}
 		}
 	}
 	}
 }
 }

二進制
assets/themes/toolbar/back.png


二進制
assets/themes/toolbar/build.png


二進制
assets/themes/toolbar/check.png


二進制
assets/themes/toolbar/copy.png


二進制
assets/themes/toolbar/cut.png


二進制
assets/themes/toolbar/debug.png


二進制
assets/themes/toolbar/find.png


二進制
assets/themes/toolbar/forward.png


二進制
assets/themes/toolbar/navigate_back.png


二進制
assets/themes/toolbar/navigate_forward.png


二進制
assets/themes/toolbar/new_file.png


二進制
assets/themes/toolbar/open_file.png


二進制
assets/themes/toolbar/open_project.png


二進制
assets/themes/toolbar/options.png


二進制
assets/themes/toolbar/paste.png


二進制
assets/themes/toolbar/paypal.png


二進制
assets/themes/toolbar/redo.png


二進制
assets/themes/toolbar/run.png


二進制
assets/themes/toolbar/save.png


二進制
assets/themes/toolbar/save_all.png


二進制
assets/themes/toolbar/save_all_dirty.png


二進制
assets/themes/toolbar/save_dirty.png


二進制
assets/themes/toolbar/undo.png


二進制
assets/themes/toolbar/zoom_in.png


二進制
assets/themes/toolbar/zoom_out.png


+ 19 - 6
dialog/FindDialog.monkey2

@@ -17,7 +17,7 @@ Class FindDialog Extends DialogExt
 			
 			
 			Local t:=_findField.Text
 			Local t:=_findField.Text
 			If t.Length > 1
 			If t.Length > 1
-				actions.FindByTextChanged()
+				actions.FindByTextChanged( EntireProject )
 			Endif
 			Endif
 		End
 		End
 
 
@@ -28,8 +28,15 @@ Class FindDialog Extends DialogExt
 		_caseSensitive=New CheckButton( "Case sensitive" )
 		_caseSensitive=New CheckButton( "Case sensitive" )
 		_caseSensitive.Layout="float"
 		_caseSensitive.Layout="float"
 		
 		
-'		_escapedText=New CheckButton( "Escaped text" )
-
+		_entireProject=New CheckButton( "Entire project" )
+		_entireProject.Layout="float"
+		
+		Local entireHint:=New Label( "(use 'Find next' button for entire-project-mode)" )
+		entireHint.Visible=False
+		_entireProject.Clicked+=Lambda()
+			entireHint.Visible=_entireProject.Checked
+		End
+		
 		Local table:=New TableView( 2,2 )
 		Local table:=New TableView( 2,2 )
 		table[0,0]=New Label( "Find" )
 		table[0,0]=New Label( "Find" )
 		table[1,0]=_findField
 		table[1,0]=_findField
@@ -39,10 +46,11 @@ Class FindDialog Extends DialogExt
 		_docker=New DockingView
 		_docker=New DockingView
 		_docker.AddView( table,"top" )
 		_docker.AddView( table,"top" )
 		_docker.AddView( _caseSensitive,"top" )
 		_docker.AddView( _caseSensitive,"top" )
-'		_docker.AddView( _escapedText,"top" )
+		_docker.AddView( _entireProject,"top" )
+		_docker.AddView( entireHint,"top" )
 		_docker.AddView( New Label( " " ),"top" )
 		_docker.AddView( New Label( " " ),"top" )
 		
 		
-		Title="Find/Replace"
+		Title="Find / Replace"
 		
 		
 		MaxSize=New Vec2i( 512,0 )
 		MaxSize=New Vec2i( 512,0 )
 		
 		
@@ -77,6 +85,11 @@ Class FindDialog Extends DialogExt
 		Return _caseSensitive.Checked
 		Return _caseSensitive.Checked
 	End
 	End
 	
 	
+	Property EntireProject:Bool()
+	
+		Return _entireProject.Checked
+	End
+	
 	Method SetInitialText( find:String )
 	Method SetInitialText( find:String )
 		
 		
 		_findField.Text=find
 		_findField.Text=find
@@ -89,7 +102,7 @@ Class FindDialog Extends DialogExt
 	Field _findField:TextField
 	Field _findField:TextField
 	Field _replaceField:TextField
 	Field _replaceField:TextField
 	Field _caseSensitive:CheckButton
 	Field _caseSensitive:CheckButton
-	Field _escapedText:CheckButton
+	Field _entireProject:CheckButton
 
 
 	Field _docker:DockingView
 	Field _docker:DockingView
 
 

+ 186 - 0
dialog/GenerateClassDialog.monkey2

@@ -0,0 +1,186 @@
+
+Namespace ted2go
+
+
+#Import "../assets/gen/@/gen"
+
+Class GenerateClassDialog Extends DialogExt
+	
+	Field Generated:Void( filePath:String,fileContent:String )
+	
+	Method New( rootPath:String )
+		
+		_path=rootPath
+		
+		Title="Generate class"
+		
+		Local dock:=New DockingView
+		
+		_codeView=New Ted2CodeTextView
+		_codeView.FileType=".monkey2"
+		_codeView.MinSize=New Vec2i( 200,200 )
+		dock.AddView( _codeView,"bottom" )
+		
+		_codeTemplate=LoadString( "asset::gen/newClass.txt" )
+		
+		Local table:=New TableView( 2,5 )
+		
+		table[0,0]=New Label( "Class name" )
+		_editClassName=CreateTextField()
+		_editClassName.TextChanged+=Lambda()
+			_editFileName.Text=ClassName+".monkey2"
+		End
+		table[1,0]=_editClassName
+		
+		table[0,1]=New Label( "SuperClass name" )
+		_editSuperClassName=CreateTextField()
+		table[1,1]=_editSuperClassName
+		
+		table[0,2]=New Label( "Interface(s) name" )
+		_editInterfacesName=CreateTextField()
+		table[1,2]=_editInterfacesName
+		
+		table[0,3]=New Label( "Namespace" )
+		_editNamespace=CreateTextField()
+		table[1,3]=_editNamespace
+		
+		table[0,4]=New Label( "File name" )
+		_editFileName=New TextFieldExt
+		table[1,4]=_editFileName
+		
+		dock.AddView( table,"bottom" )
+		
+		ContentView=dock
+		
+		Local cancel:=AddAction( "Cancel"  )
+		cancel.Triggered=lambda()
+			HideWithResult( False )
+		End
+		SetKeyAction( Key.Escape,cancel )
+		
+		Local okay:=AddAction( "Generate" )
+		okay.Triggered=Lambda()
+			OnGenerate()
+		End
+		SetKeyAction( Key.Enter,okay )
+		
+		OnShow+=Lambda()
+			_editClassName.MakeKeyView()
+		End
+		
+		AdjustTabOrder()
+		UpdateCodeView()
+		
+	End
+	
+	Property ClassName:String()
+	
+		Return _editClassName.Text.Trim()
+	End
+	
+	Property SuperClassName:String()
+	
+		Return _editSuperClassName.Text.Trim()
+	End
+	
+	Property InterfacesName:String()
+	
+		Return _editInterfacesName.Text.Trim()
+	End
+	
+	Property NamespaceName:String()
+	
+		Return _editNamespace.Text.Trim()
+	End
+	
+	Property FileName:String()
+	
+		Local s:=_editFileName.Text.Trim()
+		If Not ExtractExt( s ) Then s+=".monkey2"
+		Return s
+	End
+	
+	Property GeneratedContent:String()
+	
+		Local s:=_codeTemplate,n:String
+		s=s.Replace( "_NAME_",ClassName )
+		n=NamespaceName
+		s=s.Replace( "_NAMESPACE_",n ? ("Namespace "+n) Else "" )
+		n=SuperClassName
+		s=s.Replace( "_SUPERCLASS_",n ? (" Extends "+n) Else "" )
+		n=InterfacesName
+		s=s.Replace( "_INTERFACES_",n ? (" Implements "+n) Else "" )
+		Return s
+	End
+	
+	Private
+	
+	Field _path:String
+	Field _codeTemplate:String
+	Field _editNamespace:TextFieldExt
+	Field _editClassName:TextFieldExt
+	Field _editSuperClassName:TextFieldExt
+	Field _editInterfacesName:TextFieldExt
+	Field _editFileName:TextFieldExt
+	Field _codeView:Ted2CodeTextView
+	
+	
+	Method OnGenerate()
+		
+		If Not IsIdentStr( ClassName )
+			Alert( "Class name is invalid or empty!",Title )
+			Return
+		Endif
+		If SuperClassName And Not IsIdentStr( SuperClassName )
+			Alert( "SuperClass name is invalid!",Title )
+			Return
+		Endif
+		If NamespaceName And Not IsIdentStr( NamespaceName )
+			Alert( "Namespace is invalid!",Title )
+			Return
+		Endif
+		If InterfacesName
+			Local arr:=InterfacesName.Split( "," )
+			For Local i:=Eachin arr
+				i=i.Trim()
+				If Not IsIdentStr( i )
+					Alert( "Interface name '"+i+"' is invalid!",Title )
+					Return
+				Endif
+			Next
+		Endif
+		
+		Local path:=_path+"/"+FileName
+		If FileExists( path )
+			Alert( "File with such name already exists!",Title )
+			Return
+		Endif
+		
+		HideWithResult( True )
+		
+		Generated( path,GeneratedContent )
+	End
+	
+	Method UpdateCodeView()
+		
+		_codeView.Text=GeneratedContent
+	End
+	
+	Method CreateTextField:TextFieldExt()
+		
+		Local tf:=New TextFieldExt
+		tf.TextChanged+=UpdateCodeView
+		Return tf
+	End
+	
+	Method AdjustTabOrder()
+		
+		_editClassName.NextView=_editSuperClassName
+		_editSuperClassName.NextView=_editInterfacesName
+		_editInterfacesName.NextView=_editNamespace
+		_editNamespace.NextView=_editFileName
+		'_editFileName.NextView=_codeView
+		
+	End
+	
+End

+ 66 - 0
dialog/LiveTemplatesDialog.monkey2

@@ -0,0 +1,66 @@
+
+Namespace ted2go
+
+
+Class LiveTemplateDialog
+	
+	Method New()
+	
+		Title="Live templates"
+	
+		Local dock:=New DockingView
+		_tree=New TreeViewExt
+		_tree.NodeClicked=Lambda( node:Node )
+			
+			If node.Parent=_tree.RootNode Return
+			
+			ShowTemplate( node.Parent.Text,node.Text )
+		End
+		FillTree( _tree )
+	
+		dock.AddView( _tree,"left","150",True)
+		
+		_codeView=New Ted2CodeTextView
+		dock.ContentView=_codeView
+		
+		ContentView=dock
+	
+		Local cancel:=AddAction( "Cancel"  )
+		cancel.Triggered=lambda()
+			_result.Set( False )
+		End
+		SetKeyAction( Key.Escape,cancel )
+	
+		Local okay:=AddAction( "Save" )
+		okay.Triggered=Lambda()
+			_result.Set( True )
+		End
+		SetKeyAction( Key.Enter,okay )
+		
+	End
+	
+	
+	Private
+	
+	Field _tree:TreeViewExt
+	Field _codeView:Ted2CodeTextView
+	
+	Method ShowTemplate( lang:String,name:String )
+		
+		If _codeView.FileType<>lang Then _codeView.FileType=lang
+		_codeView.Text=LiveTemplates[lang,name]
+		_codeView.SelectText( 0,0 )
+	End
+	
+	Method FillTree( tree:TreeView )
+		
+		For Local map:=Eachin LiveTemplates.All()
+			Local node:=New TreeView.Node( map.Key,tree.RootNode )
+			For Local i:=Eachin map.Value.All()
+				New TreeView.Node( i.Key,node )
+			Next
+		Next
+	End
+	
+End
+

+ 186 - 1
dialog/PrefsDialog.monkey2

@@ -1,3 +1,4 @@
+
 Namespace ted2go
 Namespace ted2go
 
 
 
 
@@ -32,6 +33,10 @@ Class PrefsDialog Extends DialogExt
 		docker=GetChatDock()
 		docker=GetChatDock()
 		tabView.AddTab( "IRC chat",docker )
 		tabView.AddTab( "IRC chat",docker )
 		
 		
+		' Live Templates
+		'
+		docker=GetLiveTemplatesDock()
+		tabView.AddTab( "CodeTemplates",docker )
 		
 		
 		ContentView=tabView
 		ContentView=tabView
 		
 		
@@ -41,6 +46,8 @@ Class PrefsDialog Extends DialogExt
 		_acShowAfter.Activated+=_acShowAfter.MakeKeyView
 		_acShowAfter.Activated+=_acShowAfter.MakeKeyView
 		
 		
 		Deactivated+=MainWindow.UpdateKeyView
 		Deactivated+=MainWindow.UpdateKeyView
+		
+		MinSize=New Vec2i( 300,500 )
 	End
 	End
 	
 	
 	
 	
@@ -55,6 +62,7 @@ Class PrefsDialog Extends DialogExt
 	Field _acNewLineByEnter:CheckButton
 	Field _acNewLineByEnter:CheckButton
 	Field _acKeywordsOnly:CheckButton
 	Field _acKeywordsOnly:CheckButton
 	Field _acShowAfter:TextField
 	Field _acShowAfter:TextField
+	Field _acUseLiveTemplates:CheckButton
 	
 	
 	Field _editorToolBarVisible:CheckButton
 	Field _editorToolBarVisible:CheckButton
 	Field _editorGutterVisible:CheckButton
 	Field _editorGutterVisible:CheckButton
@@ -77,6 +85,9 @@ Class PrefsDialog Extends DialogExt
 	Field _chatRooms:TextField
 	Field _chatRooms:TextField
 	Field _chatAutoConnect:CheckButton
 	Field _chatAutoConnect:CheckButton
 	
 	
+	Field _codeView:Ted2CodeTextView
+	Field _treeView:TreeViewExt
+	
 	Method OnApply()
 	Method OnApply()
 	
 	
 		Prefs.AcEnabled=_acEnabled.Checked
 		Prefs.AcEnabled=_acEnabled.Checked
@@ -88,6 +99,7 @@ Class PrefsDialog Extends DialogExt
 		Prefs.AcKeywordsOnly=_acKeywordsOnly.Checked
 		Prefs.AcKeywordsOnly=_acKeywordsOnly.Checked
 		Local count:=Max( 1,Int( _acShowAfter.Text ) )
 		Local count:=Max( 1,Int( _acShowAfter.Text ) )
 		Prefs.AcShowAfter=count
 		Prefs.AcShowAfter=count
+		Prefs.AcUseLiveTemplates=_acUseLiveTemplates.Checked
 		
 		
 		Prefs.EditorToolBarVisible=_editorToolBarVisible.Checked
 		Prefs.EditorToolBarVisible=_editorToolBarVisible.Checked
 		Prefs.EditorGutterVisible=_editorGutterVisible.Checked
 		Prefs.EditorGutterVisible=_editorGutterVisible.Checked
@@ -118,6 +130,8 @@ Class PrefsDialog Extends DialogExt
 		Apply()
 		Apply()
 		
 		
 		Prefs.SaveLocalState()
 		Prefs.SaveLocalState()
+		
+		LiveTemplates.Save()
 	End
 	End
 	
 	
 	Method GetMainDock:DockingView()
 	Method GetMainDock:DockingView()
@@ -278,6 +292,9 @@ Class PrefsDialog Extends DialogExt
 		_acNewLineByEnter=New CheckButton( "Add new line (by Enter)" )
 		_acNewLineByEnter=New CheckButton( "Add new line (by Enter)" )
 		_acNewLineByEnter.Checked=Prefs.AcNewLineByEnter
 		_acNewLineByEnter.Checked=Prefs.AcNewLineByEnter
 		
 		
+		_acUseLiveTemplates=New CheckButton( "Show live templates" )
+		_acUseLiveTemplates.Checked=Prefs.AcUseLiveTemplates
+		
 		Local docker:=New DockingView
 		Local docker:=New DockingView
 		docker.AddView( New Label( " " ),"top" )
 		docker.AddView( New Label( " " ),"top" )
 		docker.AddView( _acEnabled,"top" )
 		docker.AddView( _acEnabled,"top" )
@@ -288,6 +305,7 @@ Class PrefsDialog Extends DialogExt
 		docker.AddView( _acUseSpace,"top" )
 		docker.AddView( _acUseSpace,"top" )
 		docker.AddView( _acUseDot,"top" )
 		docker.AddView( _acUseDot,"top" )
 		docker.AddView( _acKeywordsOnly,"top" )
 		docker.AddView( _acKeywordsOnly,"top" )
+		docker.AddView( _acUseLiveTemplates,"top" )
 		docker.AddView( New Label( " " ),"top" )
 		docker.AddView( New Label( " " ),"top" )
 		
 		
 		Return docker
 		Return docker
@@ -295,7 +313,7 @@ Class PrefsDialog Extends DialogExt
 	
 	
 	Method GetChatDock:DockingView()
 	Method GetChatDock:DockingView()
 		
 		
-		Local chatTable:=New TableView( 2,5 )
+		Local chatTable:=New TableView( 2,6 )
 		_chatNick=New TextField( Prefs.IrcNickname )
 		_chatNick=New TextField( Prefs.IrcNickname )
 		_chatServer=New TextField( Prefs.IrcServer )
 		_chatServer=New TextField( Prefs.IrcServer )
 		_chatPort=New TextField( ""+Prefs.IrcPort )
 		_chatPort=New TextField( ""+Prefs.IrcPort )
@@ -311,6 +329,7 @@ Class PrefsDialog Extends DialogExt
 		chatTable[0,3]=New Label( "Rooms" )
 		chatTable[0,3]=New Label( "Rooms" )
 		chatTable[1,3]=_chatRooms
 		chatTable[1,3]=_chatRooms
 		chatTable[0,4]=_chatAutoConnect
 		chatTable[0,4]=_chatAutoConnect
+		chatTable[0,5]=New Label( "" ) 'bottom padding hack
 		
 		
 		Local docker:=New DockingView
 		Local docker:=New DockingView
 		docker.AddView( New Label( " " ),"top" )
 		docker.AddView( New Label( " " ),"top" )
@@ -319,4 +338,170 @@ Class PrefsDialog Extends DialogExt
 		Return docker
 		Return docker
 	End
 	End
 	
 	
+	Method GetLiveTemplatesDock:DockingView()
+	
+		Local treeDock:=New DockingView
+		Local tree:=New TreeViewExt
+		_treeView=tree
+		
+		Local dockButtons:=New DockingView
+		Local st:=dockButtons.Style.Copy()
+		st.Margin=New Recti( 0,-5,0,0 )
+		dockButtons.Style=st
+		
+		Local btn:=New ToolButtonExt( New Action( "Add" ),"Add new template" )
+		btn.Clicked=Lambda()
+			New Fiber( Lambda()
+				Local name:=RequestString( "New template name:","" )
+				name=name.Trim()
+				If name AddTemplate( name )
+			End )
+		End
+		dockButtons.AddView( btn,"right" )
+		
+		btn=New ToolButtonExt( New Action( "Clone" ),"Clone selected" )
+		btn.Clicked=Lambda()
+			New Fiber( Lambda()
+				If Not TemplateSelName
+					Alert( "Please, select an item to clone from!" )
+					Return
+				Endif
+				Local name:=RequestString( "New template name:","" )
+				name=name.Trim()
+				If name CloneTemplate( name )
+			End )
+		End
+		dockButtons.AddView( btn,"right" )
+		
+		btn=New ToolButtonExt( New Action( "Del" ),"Remove selected" )
+		btn.Clicked=Lambda()
+			RemoveTemplate()
+		End
+		dockButtons.AddView( btn,"right" )
+		
+		btn=New ToolButtonExt( New Action( "..." ),"Open containing folder (customTemplates.json)" )
+		btn.Clicked=Lambda()
+			OpenUrl( Prefs.IdeHomeDir )
+		End
+		dockButtons.AddView( btn,"right" )
+		
+		treeDock.ContentView=tree
+		treeDock.AddView( dockButtons,"bottom" )
+		
+		Local docker1:=New DockingView
+		docker1.AddView( treeDock,"left","170",True)
+		
+		_codeView=New Ted2CodeTextView
+		_codeView.ShowWhiteSpaces=True
+		_codeView.Document.TextChanged+=Lambda()
+			
+			Local name:=TemplateSelName
+			If name Then LiveTemplates[TemplateSelLang,name]=_codeView.Text
+		End
+		docker1.ContentView=_codeView
+		
+		Local docker2:=New DockingView
+		docker2.AddView( New Label( "Press 'Tab' in completion list or editor to insert template." ),"top" )
+		docker2.ContentView=docker1
+		
+		PrepareTree( tree )
+		
+		Return docker2
+	End
+	
+	Method ShowTemplate( lang:String,name:String )
+		
+		If _codeView.FileType<>lang Then _codeView.FileType=lang
+		_codeView.Text=LiveTemplates[lang,name]
+		_codeView.SelectText( 0,0 )
+	End
+	
+	Method PrepareTree( tree:TreeViewExt)
+		
+		tree.RootNodeVisible=False
+		tree.RootNode.Expanded=True
+		tree.SelectedChanged+=Lambda( node:TreeView.Node )
+		
+			If Not node Return
+		
+			If node.Parent=tree.RootNode Return
+		
+			ShowTemplate( node.Parent.Text,node.Text )
+		End
+		
+		For Local map:=Eachin LiveTemplates.All()
+			Local node:=New TreeView.Node( map.Key,tree.RootNode )
+			For Local i:=Eachin map.Value.All()
+				New TreeView.Node( i.Key,node )
+			Next
+		Next
+		
+		Local n:=tree.RootNode
+		If n.NumChildren > 0
+			n=n.Children[0]
+			If n.NumChildren > 0
+				_treeView.Selected=n.Children[0]
+			Endif
+		Endif
+	End
+	
+	Method AddTemplate( name:String )
+		
+		Local lang:=TemplateSelLang
+		If LiveTemplates[lang,name]
+			Alert( "Such name already exists!" )
+			Return
+		Endif
+		AddTemplateInternal( lang,name,"" )
+	End
+	
+	Method CloneTemplate( name:String )
+	
+		Local lang:=TemplateSelLang
+		If LiveTemplates[lang,name]
+			Alert( "Such name already exists!" )
+			Return
+		Endif
+		AddTemplateInternal( lang,name,LiveTemplates[lang,TemplateSelName] )
+	End
+	
+	Method RemoveTemplate()
+		
+		If Not TemplateSelName
+			Alert( "Have no selected item to remove!" )
+			Return
+		Endif
+		
+		DebugStop()
+		LiveTemplates[TemplateSelLang].Remove( TemplateSelName )
+		_treeView.RemoveNode( _treeView.Selected )
+		_codeView.Text=""
+	End
+	
+	Method AddTemplateInternal( lang:String,name:String,value:String )
+		
+		LiveTemplates[lang,name]=value
+		Local n:=_treeView.FindSubNode( lang,_treeView.RootNode )
+		Local n2:=New TreeView.Node( name,n )
+		_treeView.Selected=n2
+		
+		_codeView.MakeKeyView()
+	End
+	
+	Property TemplateSelLang:String()
+		
+		Local sel:=_treeView.Selected
+		If Not sel Return Null
+		
+		Return (sel.Parent=_treeView.RootNode) ? sel.Text Else sel.Parent.Text
+	End
+	
+	Property TemplateSelName:String()
+		
+		Local sel:=_treeView.Selected
+		If Not sel Return Null
+		
+		Return (sel.Parent=_treeView.RootNode) ? Null Else sel.Text
+	End
+	
 End
 End

+ 0 - 4
dialog/UpdateModulesDialog.monkey2

@@ -246,8 +246,4 @@ Class UpdateModulesDialog Extends DialogExt
 	End
 	End
 #end
 #end
 	
 	
-	Function ShowMessage( title:String,msg:String,okButton:String="  OK  " )
-		
-		Dialog.Run( title,New Label( msg ),New String[](okButton),0,0 )
-	End
 End
 End

+ 54 - 10
document/CodeDocument.monkey2

@@ -51,13 +51,20 @@ Class CodeDocumentView Extends Ted2CodeTextView
 				
 				
 				Local ident:=result.ident
 				Local ident:=result.ident
 				Local text:=result.text
 				Local text:=result.text
-				Local item:=result.item
-				Local bySpace:=result.bySpace
 				
 				
-				text=_doc.PrepareForInsert( ident,text,Not bySpace,LineTextAtCursor,PosInLineAtCursor,item )
-				
-				SelectText( Cursor,Cursor-AutoComplete.LastIdentPart.Length )
-				ReplaceText( text )
+				If result.isTemplate
+					
+					InsertLiveTemplate( AutoComplete.LastIdentPart,text )
+					
+				Else
+					
+					Local item:=result.item
+					Local bySpace:=result.bySpace
+					
+					text=_doc.PrepareForInsert( ident,text,Not bySpace,LineTextAtCursor,PosInLineAtCursor,item )
+					SelectText( Cursor,Cursor-AutoComplete.LastIdentPart.Length )
+					ReplaceText( text )
+				Endif
 			Endif
 			Endif
 		End
 		End
 		
 		
@@ -190,6 +197,7 @@ Class CodeDocumentView Extends Ted2CodeTextView
 					Endif
 					Endif
 				
 				
 				Case Key.Backspace
 				Case Key.Backspace
+					
 					If AutoComplete.IsOpened
 					If AutoComplete.IsOpened
 						Local ident:=IdentBeforeCursor()
 						Local ident:=IdentBeforeCursor()
 						ident=ident.Slice( 0,ident.Length-1 )
 						ident=ident.Slice( 0,ident.Length-1 )
@@ -198,6 +206,15 @@ Class CodeDocumentView Extends Ted2CodeTextView
 						Else
 						Else
 							_doc.HideAutocomplete()
 							_doc.HideAutocomplete()
 						Endif
 						Endif
+						
+					Else
+						
+						#If __TARGET__="macos"
+						If ctrl
+							DeleteLineAtCursor()
+						Endif
+						#Endif
+						
 					Endif
 					Endif
 				
 				
 				Case Key.F11
 				Case Key.F11
@@ -208,9 +225,7 @@ Class CodeDocumentView Extends Ted2CodeTextView
 				#If __TARGET__="windows"
 				#If __TARGET__="windows"
 				Case Key.E 'delete whole line
 				Case Key.E 'delete whole line
 					If ctrl
 					If ctrl
-						Local line:=Document.FindLine( Cursor )
-						SelectText( Document.StartOfLine( line ),Document.EndOfLine( line )+1 )
-						ReplaceText( "" )
+						DeleteLineAtCursor()
 						Return
 						Return
 					Endif
 					Endif
 				#Endif
 				#Endif
@@ -370,6 +385,11 @@ Class CodeDocumentView Extends Ted2CodeTextView
 			
 			
 					If Cursor = Anchor 'has no selection
 					If Cursor = Anchor 'has no selection
 			
 			
+						' live templates by tab!
+						Local ident:=IdentBeforeCursor()
+						If InsertLiveTemplate( ident ) Return
+						
+						' usual tab behaviour
 						If Not shift
 						If Not shift
 							ReplaceText( "~t" )
 							ReplaceText( "~t" )
 						Else
 						Else
@@ -663,6 +683,30 @@ Class CodeDocumentView Extends Ted2CodeTextView
 		RenderStyle.Font=newFont
 		RenderStyle.Font=newFont
 	End
 	End
 	
 	
+	Method InsertLiveTemplate:Bool( ident:String,templ:String=Null )
+		
+		If Not templ Then templ=LiveTemplates[FileType,ident]
+		If templ
+			templ=PrepareSmartPaste( templ )
+			Local start:=Cursor-ident.Length
+			Local cursorOffset:=templ.Find( "${Cursor}" )
+			If cursorOffset <> -1 Then templ=templ.Replace( "${Cursor}","" )
+			SelectText( start,Cursor )
+			ReplaceText( templ )
+			If cursorOffset <> -1 Then SelectText( start+cursorOffset,start+cursorOffset )
+			Return True
+		Endif
+		
+		Return False
+	End
+	
+	Method DeleteLineAtCursor()
+		
+		Local line:=Document.FindLine( Cursor )
+		SelectText( Document.StartOfLine( line ),Document.EndOfLine( line )+1 )
+		ReplaceText( "" )
+	End
+	
 End
 End
 
 
 
 
@@ -1044,7 +1088,7 @@ Class CodeDocument Extends Ted2Document
 		
 		
 	End
 	End
 	
 	
-	Method HideAutocomplete()
+	Function HideAutocomplete()
 		AutoComplete.Hide()
 		AutoComplete.Hide()
 	End
 	End
 	
 	

+ 5 - 1
product/ModuleManager.monkey2

@@ -72,7 +72,11 @@ Class ModuleManager Extends Dialog
 			
 			
 			UpdateTable()
 			UpdateTable()
 		End
 		End
-			
+		
+		Local upload:=New Button( "Upload module" )
+		upload.Clicked+=GotoUploadModulesPage
+		buttons.AddView( upload,"right" )
+		
 		_docker.AddView( buttons,"bottom" )
 		_docker.AddView( buttons,"bottom" )
 		
 		
 		ContentView=_docker
 		ContentView=_docker

+ 10 - 0
utils/JsonUtils.monkey2

@@ -2,6 +2,16 @@
 Namespace ted2go
 Namespace ted2go
 
 
 
 
+Function Json_LoadObject:JsonObject( filePath:String )
+	
+	If GetFileType(filePath) <> FileType.File Return Null
+	
+	'Local txt:=LoadString( filePath ).Replace( "\n","~n" ).Replace( "\t","~t" ).Replace( "\r","~r" )
+	
+	'Return JsonObject.Parse( txt )
+	Return JsonObject.Load( filePath )
+End
+
 Function Json_LoadValue:JsonValue( filePath:String,key:String )
 Function Json_LoadValue:JsonValue( filePath:String,key:String )
 	
 	
 	If GetFileType(filePath) <> FileType.File Return Null
 	If GetFileType(filePath) <> FileType.File Return Null

+ 18 - 0
utils/Utils.monkey2

@@ -188,3 +188,21 @@ Function FormatTime:String( millis:Long,format:String="{min} m {sec} s" )
 	
 	
 	Return s
 	Return s
 End
 End
+
+Function ShowMessage( title:String,msg:String,okButton:String="  OK  " )
+
+	Dialog.Run( title,New Label( msg ),New String[](okButton),0,0 )
+End
+
+Function IsIdentStr:Bool( str:String )
+	
+	If Not str Return False
+	
+	If IsDigit( str[0] ) Return False
+	
+	For Local c:=Eachin str
+		If Not IsIdent( c ) Return False
+	Next
+	
+	Return True
+End

+ 99 - 21
view/AutocompleteView.monkey2

@@ -85,6 +85,7 @@ Struct AutocompleteResult
 	Field text:String
 	Field text:String
 	Field item:CodeItem
 	Field item:CodeItem
 	Field bySpace:Bool
 	Field bySpace:Bool
+	Field isTemplate:Bool
 	
 	
 End
 End
 
 
@@ -97,14 +98,17 @@ Class AutocompleteDialog Extends NoTitleDialog
 		
 		
 		Super.New()
 		Super.New()
 		
 		
-		_view=New AutocompleteListView( 20,15 )
+		Local lineHg:=20,linesCount:=15
+		
+		_view=New AutocompleteListView( lineHg,linesCount )
 		_view.MoveCyclic=True
 		_view.MoveCyclic=True
 		
 		
-		_view.MaxSize=New Vec2i( 500,20*15 )
+		_etalonMaxSize=New Vec2i( 500,lineHg*linesCount )
 		
 		
 		ContentView=_view
 		ContentView=_view
 		
 		
 		_keywords=New StringMap<List<ListViewItem>>
 		_keywords=New StringMap<List<ListViewItem>>
+		_templates=New StringMap<List<ListViewItem>>
 		_parsers=New StringMap<ICodeParser>
 		_parsers=New StringMap<ICodeParser>
 		
 		
 		_view.OnItemChoosen+=Lambda()
 		_view.OnItemChoosen+=Lambda()
@@ -119,6 +123,7 @@ Class AutocompleteDialog Extends NoTitleDialog
 			_disableUsingsFilter=False
 			_disableUsingsFilter=False
 		End
 		End
 		
 		
+		OnThemeChanged()
 	End
 	End
 	
 	
 	Property DisableUsingsFilter:Bool()
 	Property DisableUsingsFilter:Bool()
@@ -288,6 +293,17 @@ Class AutocompleteDialog Extends NoTitleDialog
 		
 		
 		If lastIdent Then CodeItemsSorter.SortByIdent( result,lastIdent )
 		If lastIdent Then CodeItemsSorter.SortByIdent( result,lastIdent )
 		
 		
+		'-----------------------------
+		' live templates
+		'-----------------------------
+		If onlyOne And Prefs.AcUseLiveTemplates
+			For Local i:=Eachin GetTemplates( fileType )
+				If i.Text.StartsWith( lastIdent )
+					result.Insert( 0,i )
+				Endif
+			Next
+		Endif
+		
 		_view.Reset()'reset selIndex
 		_view.Reset()'reset selIndex
 		_view.SetItems( result )
 		_view.SetItems( result )
 		
 		
@@ -297,10 +313,19 @@ Class AutocompleteDialog Extends NoTitleDialog
 	End
 	End
 	
 	
 	
 	
+	Protected
+	
+	Method OnThemeChanged() Override
+		
+		_view.MaxSize=_etalonMaxSize*App.Theme.Scale
+	End
+	
 	Private
 	Private
 	
 	
+	Field _etalonMaxSize:Vec2i
 	Field _view:AutocompleteListView
 	Field _view:AutocompleteListView
 	Field _keywords:StringMap<List<ListViewItem>>
 	Field _keywords:StringMap<List<ListViewItem>>
+	Field _templates:StringMap<List<ListViewItem>>
 	Field _lastIdentPart:String,_fullIdent:String
 	Field _lastIdentPart:String,_fullIdent:String
 	Field _parsers:StringMap<ICodeParser>
 	Field _parsers:StringMap<ICodeParser>
 	Field _listForExtract:=New List<CodeItem>
 	Field _listForExtract:=New List<CodeItem>
@@ -317,6 +342,18 @@ Class AutocompleteDialog Extends NoTitleDialog
 		Return _keywords[fileType]
 		Return _keywords[fileType]
 	End
 	End
 	
 	
+	Method GetTemplates:List<ListViewItem>( fileType:String )
+		If _templates[fileType] = Null
+			UpdateTemplates( fileType )
+			LiveTemplates.DataChanged+=Lambda( lang:String )
+				If _templates[lang] 'recreate items only if them were in use
+					UpdateTemplates( lang )
+				Endif
+			End
+		Endif
+		Return _templates[fileType]
+	End
+	
 	Method IsItemInScope:Bool( item:CodeItem,scope:CodeItem )
 	Method IsItemInScope:Bool( item:CodeItem,scope:CodeItem )
 		If scope = Null Return False
 		If scope = Null Return False
 		Return item.ScopeStartPos.x >= scope.ScopeStartPos.x And item.ScopeEndPos.x <= scope.ScopeEndPos.x
 		Return item.ScopeStartPos.x >= scope.ScopeStartPos.x And item.ScopeEndPos.x <= scope.ScopeEndPos.x
@@ -330,44 +367,61 @@ Class AutocompleteDialog Extends NoTitleDialog
 			
 			
 			Case EventType.KeyDown,EventType.KeyRepeat
 			Case EventType.KeyDown,EventType.KeyRepeat
 				
 				
+				Local curItem:=_view.CurrentItem
+				Local templ:=Cast<TemplateListViewItem>( curItem )
+				
 				Select event.Key
 				Select event.Key
 				Case Key.Escape
 				Case Key.Escape
 					Hide()
 					Hide()
 					event.Eat()
 					event.Eat()
+					
 				Case Key.Up
 				Case Key.Up
 					_view.SelectPrev()
 					_view.SelectPrev()
 					event.Eat()
 					event.Eat()
+					
 				Case Key.Down
 				Case Key.Down
 					_view.SelectNext()
 					_view.SelectNext()
 					event.Eat()
 					event.Eat()
+					
 				Case Key.PageUp
 				Case Key.PageUp
 					_view.PageUp()
 					_view.PageUp()
 					event.Eat()
 					event.Eat()
+					
 				Case Key.PageDown
 				Case Key.PageDown
 					_view.PageDown()
 					_view.PageDown()
 					event.Eat()
 					event.Eat()
+					
 				Case Key.Enter,Key.KeypadEnter
 				Case Key.Enter,Key.KeypadEnter
-					If Prefs.AcUseEnter
-						OnItemChoosen( _view.CurrentItem )
-						If Not Prefs.AcNewLineByEnter Then event.Eat()
-					Else
-						Hide() 'hide by enter
+					If Not templ
+						If Prefs.AcUseEnter
+							OnItemChoosen( curItem )
+							If Not Prefs.AcNewLineByEnter Then event.Eat()
+						Else
+							Hide() 'hide by enter
+						Endif
 					Endif
 					Endif
+					
 				Case Key.Tab
 				Case Key.Tab
-					If Prefs.AcUseTab
-						OnItemChoosen( _view.CurrentItem )
+					If Prefs.AcUseTab Or templ
+						OnItemChoosen( curItem )
 						event.Eat()
 						event.Eat()
 					Endif
 					Endif
+					
 				Case Key.Space
 				Case Key.Space
-					Local ctrl:=event.Modifiers & Modifier.Control
-					If Prefs.AcUseSpace And Not ctrl
-						OnItemChoosen( _view.CurrentItem,True )
-						event.Eat()
+					If Not templ
+						Local ctrl:=event.Modifiers & Modifier.Control
+						If Prefs.AcUseSpace And Not ctrl
+							OnItemChoosen( curItem,True )
+							event.Eat()
+						Endif
 					Endif
 					Endif
+					
 				Case Key.Period
 				Case Key.Period
-					If Prefs.AcUseDot
-						OnItemChoosen( _view.CurrentItem )
-						event.Eat()
+					If Not templ
+						If Prefs.AcUseDot
+							OnItemChoosen( curItem )
+							event.Eat()
+						Endif
 					Endif
 					Endif
 				
 				
 				Case Key.Backspace
 				Case Key.Backspace
@@ -390,13 +444,19 @@ Class AutocompleteDialog Extends NoTitleDialog
 	
 	
 	Method OnItemChoosen( item:ListViewItem,bySpace:Bool=False )
 	Method OnItemChoosen( item:ListViewItem,bySpace:Bool=False )
 		
 		
-		Local si:=Cast<CodeListViewItem>( item )
+		Local siCode:=Cast<CodeListViewItem>( item )
+		Local siTempl:=Cast<TemplateListViewItem>( item )
 		Local ident:="",text:=""
 		Local ident:="",text:=""
 		Local code:CodeItem=Null
 		Local code:CodeItem=Null
-		If si <> Null
-			ident=si.CodeItem.Ident
-			text=si.CodeItem.TextForInsert
-			code=si.CodeItem
+		Local templ:=False
+		If siCode
+			ident=siCode.CodeItem.Ident
+			text=siCode.CodeItem.TextForInsert
+			code=siCode.CodeItem
+		Elseif siTempl
+			ident=siTempl.name
+			text=siTempl.value
+			templ=True
 		Else
 		Else
 			ident=item.Text
 			ident=item.Text
 			text=item.Text
 			text=item.Text
@@ -406,6 +466,7 @@ Class AutocompleteDialog Extends NoTitleDialog
 		result.text=text
 		result.text=text
 		result.item=code
 		result.item=code
 		result.bySpace=bySpace
 		result.bySpace=bySpace
+		result.isTemplate=templ
 		OnChoosen( result )
 		OnChoosen( result )
 		Hide()
 		Hide()
 	End
 	End
@@ -430,6 +491,23 @@ Class AutocompleteDialog Extends NoTitleDialog
 		_keywords[fileType]=list
 		_keywords[fileType]=list
 	End
 	End
 	
 	
+	Method UpdateTemplates( fileType:String )
+	
+		'live templates
+		Local templates:=LiveTemplates.All( fileType )
+		Local list:=New List<ListViewItem>
+		If templates <> Null
+			For Local i:=Eachin templates
+				Local si:=New TemplateListViewItem( i.Key,i.Value )
+				list.AddLast( si )
+			Next
+			list.Sort( Lambda:Int(l:ListViewItem,r:ListViewItem)
+				Return l.Text<=>r.Text
+			End )
+		Endif
+		_templates[fileType]=list
+	End
+	
 	Method UpdateParsers( fileType:String )
 	Method UpdateParsers( fileType:String )
 		_parsers[fileType]=ParsersManager.Get( fileType )
 		_parsers[fileType]=ParsersManager.Get( fileType )
 	End
 	End

+ 21 - 0
view/BuildErrorListViewItem.monkey2

@@ -0,0 +1,21 @@
+
+Namespace ted2go
+
+
+Class BuildErrorListViewItem Extends ListViewItem
+	
+	Field error:BuildError
+	
+	Method New( text:String,icon:Image )
+		
+		Super.New( text,icon )
+	End
+	
+	Method New( err:BuildError )
+	
+		Super.New( err.msg )
+		Text="~q"+err.msg.Trim()+"~q at line "+(err.line+1)+" ("+err.path+")"
+		error=err
+	End
+	
+End

+ 24 - 37
view/CodeMapView.monkey2

@@ -16,18 +16,18 @@ Class CodeMapView Extends View
 		
 		
 		_codeView=sourceView
 		_codeView=sourceView
 	
 	
-		_selColor=App.Theme.GetColor( "codemap-selection" )
-		_padding=PAD*App.Theme.Scale.x
-		App.ThemeChanged+=Lambda()
-			_selColor=App.Theme.GetColor( "codemap-selection" )
-			_padding=PAD*App.Theme.Scale.x
-		End
-		
+		OnThemeChanged()
 	End
 	End
 	
 	
 	
 	
 	Protected
 	Protected
 	
 	
+	Method OnThemeChanged() Override
+		
+		_selColor=App.Theme.GetColor( "codemap-selection" )
+		_padding=PAD*App.Theme.Scale.x
+	End
+	
 	Method OnMeasure:Vec2i() Override
 	Method OnMeasure:Vec2i() Override
 	
 	
 		Local ww:=WIDTH*App.Theme.Scale.x
 		Local ww:=WIDTH*App.Theme.Scale.x
@@ -119,7 +119,7 @@ Class CodeMapView Extends View
 	
 	
 	Property ScrollKoef:Float()
 	Property ScrollKoef:Float()
 	
 	
-		Local hh:=_codeView.ContentView.Frame.Height
+		Local hh:=OwnerContentHeight
 		_maxSelfScroll=Max( Float(0.0),hh*scale-VisibleHeight )
 		_maxSelfScroll=Max( Float(0.0),hh*scale-VisibleHeight )
 		_maxOwnerScroll=Max( 0.0,hh-VisibleHeight )
 		_maxOwnerScroll=Max( 0.0,hh-VisibleHeight )
 	
 	
@@ -131,6 +131,11 @@ Class CodeMapView Extends View
 		Return _codeView.ContentView.Frame.Height
 		Return _codeView.ContentView.Frame.Height
 	End
 	End
 	
 	
+	Property OwnerContentWidht:Float()
+	
+		Return _codeView.ContentView.Frame.Width
+	End
+	
 	Property BubbleHeight:Float()
 	Property BubbleHeight:Float()
 	
 	
 		Return VisibleHeight*scale
 		Return VisibleHeight*scale
@@ -164,37 +169,19 @@ Class CodeMapView Extends View
 	
 	
 		canvas.Translate( _padding,-yy*ScrollKoef+_padding )
 		canvas.Translate( _padding,-yy*ScrollKoef+_padding )
 		canvas.Scale( scale,scale )
 		canvas.Scale( scale,scale )
-	
-		Local times:=Int(OwnerContentHeight/VisibleHeight)+1
-		Local sc:=_codeView.Scroll
-		Local sc2:=New Vec2i
-		Local dy:=VisibleHeight+_codeView.LineHeight
+		
 		Local whiteSpaces:=_codeView.ShowWhiteSpaces
 		Local whiteSpaces:=_codeView.ShowWhiteSpaces
+		
 		_codeView.ShowWhiteSpaces=False
 		_codeView.ShowWhiteSpaces=False
-		Local top:=-yy*ScrollKoef
-		For Local k:=0 Until times
-	
-			' check visibility area
-			If top+VisibleHeight*scale < 0
-				top+=dy*scale
-				sc2.Y=sc2.y+dy
-				Continue
-			Endif
-			If top>VisibleHeight
-				Exit
-			Endif
-			top+=dy*scale
-	
-			_codeView.Scroll=sc2
-			CodeTextViewBridge.ProcessRender( _codeView,canvas )
-			sc2.Y=sc2.y+dy
-			
-		Next
-		_codeView.Scroll=sc
+		Local top:=yy*ScrollKoef/scale
+		
+		Local r:=New Recti( 0,top,OwnerContentWidht,top+VisibleHeight/scale )
+		CodeTextViewBridge.ProcessRender( _codeView,r,canvas )
+		
 		_codeView.ShowWhiteSpaces=whiteSpaces
 		_codeView.ShowWhiteSpaces=whiteSpaces
-	
+		
 		canvas.PopMatrix()
 		canvas.PopMatrix()
-	
+		
 	End
 	End
 	
 	
 End
 End
@@ -206,9 +193,9 @@ Private
 
 
 Class CodeTextViewBridge Extends CodeTextView Abstract
 Class CodeTextViewBridge Extends CodeTextView Abstract
 
 
-	Function ProcessRender( item:CodeTextView,canvas:Canvas )
+	Function ProcessRender( item:CodeTextView,rect:Recti,canvas:Canvas )
 		
 		
-		item.OnRenderContent( canvas )
+		item.OnRenderContent( canvas,rect )
 	End
 	End
 	
 	
 End
 End

+ 24 - 4
view/CodeTextView.monkey2

@@ -18,6 +18,7 @@ Class CodeTextView Extends TextView
 		BlockCursor=False
 		BlockCursor=False
 		
 		
 		CursorMoved += OnCursorMoved
 		CursorMoved += OnCursorMoved
+		Document.TextChanged += TextChanged
 		
 		
 		UpdateThemeColors()
 		UpdateThemeColors()
 	End
 	End
@@ -202,6 +203,19 @@ Class CodeTextView Extends TextView
 		
 		
 				Scroll-=New Vec2i( 0,RenderStyle.Font.Height*event.Wheel.Y*3 )
 				Scroll-=New Vec2i( 0,RenderStyle.Font.Height*event.Wheel.Y*3 )
 				Return
 				Return
+			
+			Case EventType.MouseDown 'prevent selection by dragging with right-button
+				
+				If event.Button = MouseButton.Right Return
+				
+				
+			Case EventType.MouseUp
+				
+				If event.Button = MouseButton.Right
+					
+					MainWindow.ShowEditorMenu( Self )
+					Return
+				Endif
 				
 				
 		End
 		End
 
 
@@ -359,7 +373,15 @@ Class CodeTextView Extends TextView
 		Endif
 		Endif
 	End
 	End
 	
 	
-	Method SmartPaste()
+	Method SmartPaste( customText:String=Null )
+	
+		Local txt:= customText ? customText Else App.ClipboardText
+	
+		ReplaceText( PrepareSmartPaste( txt ) )
+		
+	End
+	
+	Method PrepareSmartPaste:String( txt:String )
 	
 	
 		' get indent of cursor's line
 		' get indent of cursor's line
 		Local cur:=Min( Cursor,Anchor )
 		Local cur:=Min( Cursor,Anchor )
@@ -368,7 +390,6 @@ Class CodeTextView Extends TextView
 		Local posInLine:=cur-Document.StartOfLine( line )
 		Local posInLine:=cur-Document.StartOfLine( line )
 		indent=Min( indent,posInLine )
 		indent=Min( indent,posInLine )
 	
 	
-		Local txt:=App.ClipboardText
 		txt=txt.Replace( "~r~n","~n" )
 		txt=txt.Replace( "~r~n","~n" )
 		txt=txt.Replace( "~r","~n" )
 		txt=txt.Replace( "~r","~n" )
 		Local lines:=txt.Split( "~n" )
 		Local lines:=txt.Split( "~n" )
@@ -388,8 +409,7 @@ Class CodeTextView Extends TextView
 			result+=lines[i]
 			result+=lines[i]
 		Next
 		Next
 	
 	
-		ReplaceText( result )
-	
+		Return result
 	End
 	End
 	
 	
 	Method DoFormat( all:Bool )
 	Method DoFormat( all:Bool )

+ 77 - 45
view/CodeTreeView.monkey2

@@ -7,9 +7,15 @@ Class CodeTreeView Extends TreeViewExt
 	Field SortByType:=True
 	Field SortByType:=True
 	Field ShowInherited:=False
 	Field ShowInherited:=False
 	
 	
-	Method Fill( fileType:String,path:String )
 	
 	
-		StoreTreeExpands()
+	Method New()
+		
+		_expander=New TreeViewExpander( Self )
+	End
+	
+	Method Fill( fileType:String,path:String,expandIfOnlyOneItem:Bool=True )
+	
+		_expander.Store()
 		
 		
 		Local stack:=New Stack<TreeView.Node>
 		Local stack:=New Stack<TreeView.Node>
 		Local parser:=ParsersManager.Get( fileType )
 		Local parser:=ParsersManager.Get( fileType )
@@ -29,6 +35,9 @@ Class CodeTreeView Extends TreeViewExt
 			AddTreeItem( i,node,parser )
 			AddTreeItem( i,node,parser )
 		Next
 		Next
 		
 		
+		If expandIfOnlyOneItem And RootNode.NumChildren=1
+			RootNode.Children[0].Expanded=True
+		Endif
 	End
 	End
 	
 	
 	Method SelectByScope( scope:CodeItem )
 	Method SelectByScope( scope:CodeItem )
@@ -42,7 +51,7 @@ Class CodeTreeView Extends TreeViewExt
 	
 	
 	Private
 	Private
 	
 	
-	Field _expands:=New StringMap<Bool>
+	Field _expander:TreeViewExpander
 	
 	
 	
 	
 	Method FindNode:TreeView.Node( treeNode:TreeView.Node,item:CodeItem )
 	Method FindNode:TreeView.Node( treeNode:TreeView.Node,item:CodeItem )
@@ -62,53 +71,12 @@ Class CodeTreeView Extends TreeViewExt
 		Return Null
 		Return Null
 	End
 	End
 	
 	
-	Method StoreTreeExpands()
-	
-		_expands.Clear()
-		StoreNodeExpand( RootNode )
-		
-	End
-	
-	Method StoreNodeExpand( node:TreeView.Node )
-		
-		If Not node.Expanded Return
-		
-		Local key:=GetNodePath( node )
-		_expands[key]=node.Expanded
-		
-		If node.Children = Null Return
-		
-		For Local i:=Eachin node.Children
-			StoreNodeExpand( i )
-		Next
-		
-	End
-	
-	Method RestoreNodeExpand( node:TreeView.Node )
-	
-		Local key:=GetNodePath( node )
-		node.Expanded=_expands[key]
-		
-	End
-	
-	Method GetNodePath:String( node:TreeView.Node )
-	
-		Local s:=node.Text
-		Local i:=node.Parent
-		While i <> Null
-			s=i.Text+"\"+s
-			i=i.Parent
-		Wend
-		Return s
-		
-	End
-		
 	Method AddTreeItem( item:CodeItem,node:TreeView.Node,parser:ICodeParser )
 	Method AddTreeItem( item:CodeItem,node:TreeView.Node,parser:ICodeParser )
 	
 	
 		Local n:=New CodeTreeNode( item,node )
 		Local n:=New CodeTreeNode( item,node )
 		
 		
 		' restore expand state
 		' restore expand state
-		RestoreNodeExpand( n )
+		_expander.RestoreNode( n )
 		
 		
 		If item.Children = Null And Not ShowInherited Return
 		If item.Children = Null And Not ShowInherited Return
 		
 		
@@ -210,3 +178,67 @@ Class CodeTreeNode Extends TreeView.Node
 	Field _code:CodeItem
 	Field _code:CodeItem
 	
 	
 End
 End
+
+
+Class TreeViewExpander
+	
+	Method New( tree:TreeView )
+		
+		_tree=tree
+	End
+	
+	Method Store()
+	
+		_expands.Clear()
+		StoreNode( _tree.RootNode )
+	End
+	
+	Method Restore()
+	
+		RestoreNode( _tree.RootNode )
+	End
+	
+	Method RestoreNode( node:TreeView.Node )
+	
+		Local key:=GetNodePath( node )
+		node.Expanded=_expands[key]
+		
+		If node.Children = Null Return
+		
+		For Local i:=Eachin node.Children
+			RestoreNode( i )
+		Next
+	End
+	
+	Private
+	
+	Field _tree:TreeView
+	Field _expands:=New StringMap<Bool>
+	
+	Method GetNodePath:String( node:TreeView.Node )
+	
+		Local s:=node.Text
+		Local i:=node.Parent
+		While i <> Null
+			s=i.Text+"\"+s
+			i=i.Parent
+		Wend
+		Return s
+	End
+	
+	Method StoreNode( node:TreeView.Node )
+	
+		If Not node.Expanded Return
+	
+		Local key:=GetNodePath( node )
+		_expands[key]=node.Expanded
+	
+		If node.Children = Null Return
+	
+		For Local i:=Eachin node.Children
+			StoreNode( i )
+		Next
+	End
+	
+End
+

+ 9 - 0
view/FileBrowserExt.monkey2

@@ -11,6 +11,7 @@ Class FileBrowserExt Extends TreeView
 	Field FileDoubleClicked:Void( path:String )
 	Field FileDoubleClicked:Void( path:String )
 	
 	
 	Method New( rootPath:String="." )
 	Method New( rootPath:String="." )
+		
 		Style=GetStyle( "FileBrowser" )
 		Style=GetStyle( "FileBrowser" )
 		
 		
 		GetFileTypeIcons()
 		GetFileTypeIcons()
@@ -28,6 +29,8 @@ Class FileBrowserExt Extends TreeView
 		
 		
 		RootNode=_rootNode
 		RootNode=_rootNode
 		
 		
+		_expander=New TreeViewExpander( Self )
+		
 		Update()
 		Update()
 	End
 	End
 	
 	
@@ -49,7 +52,11 @@ Class FileBrowserExt Extends TreeView
 	#end
 	#end
 	Method Update()
 	Method Update()
 	
 	
+		_expander.Store()
+		
 		UpdateNode( _rootNode,_rootPath,True )
 		UpdateNode( _rootNode,_rootPath,True )
+		
+		_expander.Restore()
 	End
 	End
 	
 	
 	Protected
 	Protected
@@ -83,6 +90,8 @@ Class FileBrowserExt Extends TreeView
 	Field _dirIcon:Image
 	Field _dirIcon:Image
 	Field _fileIcon:Image
 	Field _fileIcon:Image
 	
 	
+	Field _expander:TreeViewExpander
+	
 	Method OnNodeClicked( tnode:TreeView.Node )
 	Method OnNodeClicked( tnode:TreeView.Node )
 	
 	
 		Local node:=Cast<Node>( tnode )
 		Local node:=Cast<Node>( tnode )

+ 1 - 0
view/IRCView.monkey2

@@ -929,6 +929,7 @@ Class IRCView Extends DockingView
 		inputField.BlockCursor=False
 		inputField.BlockCursor=False
 		inputField.CursorType=CursorType.Line
 		inputField.CursorType=CursorType.Line
 		inputField.CursorBlinkRate=2.5
 		inputField.CursorBlinkRate=2.5
+		inputField.MaxLength=512
 		inputField.Entered+=Lambda()
 		inputField.Entered+=Lambda()
 			SendInput(inputField.Text)
 			SendInput(inputField.Text)
 			inputField.Text=Null
 			inputField.Text=Null

+ 36 - 6
view/ListViewExt.monkey2

@@ -9,7 +9,7 @@ Class ListViewItem
 	Setter( value:String )
 	Setter( value:String )
 		_text=value
 		_text=value
 	End
 	End
-	
+
 	Property Icon:Image()
 	Property Icon:Image()
 		Return _icon
 		Return _icon
 	Setter( value:Image )
 	Setter( value:Image )
@@ -30,7 +30,7 @@ Class ListViewItem
 		canvas.Color=App.Theme.DefaultStyle.TextColor
 		canvas.Color=App.Theme.DefaultStyle.TextColor
 		canvas.DrawText( _text,x+dx,y,handleX,handleY )
 		canvas.DrawText( _text,x+dx,y,handleX,handleY )
 	End
 	End
-	
+
 	
 	
 	Private
 	Private
 	
 	
@@ -44,9 +44,13 @@ Class ListViewExt Extends ScrollableView
 
 
 	Field OnItemChoosen:Void()
 	Field OnItemChoosen:Void()
 	
 	
+	Method New()
+		Self.New( 20,50 )
+	End
+	
 	Method New( lineHeight:Int,maxLines:Int )
 	Method New( lineHeight:Int,maxLines:Int )
 		
 		
-		_lineH=lineHeight
+		_lineHeightEtalon=lineHeight
 		_maxLines=maxLines
 		_maxLines=maxLines
 		
 		
 		_items=New List<ListViewItem>
 		_items=New List<ListViewItem>
@@ -56,6 +60,7 @@ Class ListViewExt Extends ScrollableView
 		_selColor=App.Theme.GetColor( "content" )
 		_selColor=App.Theme.GetColor( "content" )
 		_hoverColor=App.Theme.GetColor( "knob" )
 		_hoverColor=App.Theme.GetColor( "knob" )
 		
 		
+		OnThemeChanged()
 	End
 	End
 	
 	
 	Method AddItems( items:Stack<ListViewItem> )
 	Method AddItems( items:Stack<ListViewItem> )
@@ -67,18 +72,37 @@ Class ListViewExt Extends ScrollableView
 		_visibleCount=Min( _maxLines,_count )
 		_visibleCount=Min( _maxLines,_count )
 	End
 	End
 	
 	
+	Method AddItem( item:ListViewItem )
+	
+		_items.AddLast( item )
+		_count=_items.Count()
+		_visibleCount=Min( _maxLines,_count )
+	End
+	
 	Method SetItems<T>( items:Stack<T> ) Where T Extends ListViewItem
 	Method SetItems<T>( items:Stack<T> ) Where T Extends ListViewItem
 		
 		
 		_items.Clear()
 		_items.Clear()
 		AddItems( items )
 		AddItems( items )
 	End
 	End
 	
 	
+	Method SetItems<T>( items:T[] ) Where T Extends ListViewItem
+	
+		_items.Clear()
+		AddItems( items )
+	End
+	
 	Method Reset()
 	Method Reset()
 		
 		
 		_selIndex=0
 		_selIndex=0
 		Scroll=New Vec2i
 		Scroll=New Vec2i
 	End
 	End
 	
 	
+	Method Clear()
+	
+		Reset()
+		_items.Clear()
+	End
+	
 	Property LineHeight:Float()
 	Property LineHeight:Float()
 		Return _lineH
 		Return _lineH
 	End
 	End
@@ -155,7 +179,9 @@ Class ListViewExt Extends ScrollableView
 	
 	
 	Protected
 	Protected
 	
 	
-	Method New()
+	Method OnThemeChanged() Override
+	
+		_lineH=_lineHeightEtalon*App.Theme.Scale.y
 	End
 	End
 	
 	
 	Method SelectPrevInternal( ensureVis:Bool )
 	Method SelectPrevInternal( ensureVis:Bool )
@@ -271,13 +297,17 @@ Class ListViewExt Extends ScrollableView
 		
 		
 			Local index:=(MouseLocation.y+Scroll.y)/_lineH
 			Local index:=(MouseLocation.y+Scroll.y)/_lineH
 			
 			
+			If index < 0 Or index >= _count Return
+			
 			_selIndex=index
 			_selIndex=index
 			OnItemChoosen()
 			OnItemChoosen()
 			
 			
 		Case EventType.MouseClick
 		Case EventType.MouseClick
 		
 		
 			Local index:=(MouseLocation.y+Scroll.y)/_lineH
 			Local index:=(MouseLocation.y+Scroll.y)/_lineH
-		
+			
+			If index < 0 Or index >= _count Return
+			
 			_selIndex=index
 			_selIndex=index
 			OnItemChoosen()
 			OnItemChoosen()
 			
 			
@@ -291,7 +321,7 @@ Class ListViewExt Extends ScrollableView
 	Private
 	Private
 	
 	
 	Field _items:List<ListViewItem>
 	Field _items:List<ListViewItem>
-	Field _lineH:Int
+	Field _lineH:Int,_lineHeightEtalon:Int
 	Field _count:Int,_visibleCount:Int
 	Field _count:Int,_visibleCount:Int
 	Field _maxLines:Int
 	Field _maxLines:Int
 	Field _selIndex:Int
 	Field _selIndex:Int

+ 38 - 11
view/ProjectView.monkey2

@@ -72,28 +72,36 @@ Class ProjectView Extends ScrollView
 				
 				
 				menu.AddSeparator()
 				menu.AddSeparator()
 				
 				
+				menu.AddAction( "New class..." ).Triggered=Lambda()
+				
+					Local d:=New GenerateClassDialog( path )
+					d.Generated+=Lambda( filePath:String,fileContent:String )
+						
+						If CreateFileInternal( filePath,fileContent )
+						
+							MainWindow.OpenDocument( filePath )
+							browser.Refresh()
+						Endif
+					End
+					d.ShowModal()
+					Return
+				End
+				
+				menu.AddSeparator()
+				
 				menu.AddAction( "New file" ).Triggered=Lambda()
 				menu.AddAction( "New file" ).Triggered=Lambda()
 				
 				
 					Local file:=RequestString( "New file name:" )
 					Local file:=RequestString( "New file name:" )
 					If Not file Return
 					If Not file Return
 					
 					
-					If ExtractExt(file)="" Then file+=".monkey2"
-					
 					Local tpath:=path+"/"+file
 					Local tpath:=path+"/"+file
 					
 					
-					If GetFileType( tpath )<>FileType.None
-						Alert( "A file or directory already exists at '"+tpath+"'" )
-						Return
-					End
-					
-					If Not CreateFile( tpath )
-						Alert( "Failed to create file '"+file+"'" )
-					Endif
+					CreateFileInternal( tpath )
 					
 					
 					browser.Refresh()
 					browser.Refresh()
 					Return
 					Return
 				End
 				End
-		
+				
 				menu.AddAction( "New folder" ).Triggered=Lambda()
 				menu.AddAction( "New folder" ).Triggered=Lambda()
 				
 				
 					Local dir:=RequestString( "New folder name:" )
 					Local dir:=RequestString( "New folder name:" )
@@ -360,4 +368,23 @@ Class ProjectView Extends ScrollView
 		Return succ>0
 		Return succ>0
 	End
 	End
 	
 	
+	Method CreateFileInternal:Bool( path:String,content:String=Null )
+		
+		If ExtractExt(path)="" Then path+=".monkey2"
+		
+		If GetFileType( path )<>FileType.None
+			Alert( "A file or directory already exists at '"+path+"'" )
+			Return False
+		End
+		
+		If Not CreateFile( path )
+			Alert( "Failed to create file '"+StripDir( path )+"'" )
+			Return False
+		Endif
+		
+		If content Then SaveString( content,path )
+		
+		Return True
+	End
+	
 End
 End

+ 49 - 0
view/Ted2CodeTextView.monkey2

@@ -0,0 +1,49 @@
+
+Namespace ted2go
+
+
+Class Ted2CodeTextView Extends CodeTextView
+
+	Property FileType:String() 'where else we can store this type?
+		return _type
+	Setter( value:String )
+		_type=value
+		Keywords = KeywordsManager.Get(_type)
+		Highlighter = HighlightersManager.Get(_type)
+		Formatter = FormattersManager.Get(_type)
+		Document.TextHighlighter = Highlighter.Painter
+	End
+	
+	Property FilePath:String()
+		return _path
+	Setter(value:String)
+		_path = value
+	End
+	
+	Method LoadCode( path:String,type:String=".monkey2" )
+		
+		If Not type Then type=ExtractExt( path )
+		FileType=type
+		FilePath=path
+		Text=LoadString( path )
+	End
+	
+	
+	Protected
+	
+	Method OnKeyEvent( event:KeyEvent ) Override
+	
+		TextViewKeyEventFilter.FilterKeyEvent( event,Self,FileType )
+		
+		If Not event.Eaten
+			Super.OnKeyEvent( event )
+		Endif
+		
+	End
+
+	Private
+	
+	Field _type:String
+	Field _path:String
+	
+End

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