Browse Source

Squashed 'src/ted2go/' changes from 8d1358d9..358f7111

358f7111 Merge branch 'dev'
f1a4b3cc #87 (Remembering open folders in project tree even if they are closed - but children are opened).
2931e268 Update modules dialog - now stores targets state.
3ff3652e Added x64 logo and tweaked android product.
1f4262dd #86. Rebuild modules dialog now stores its checkboxes.
3f69425e Fix for crashes because of incorrect params-hint detection.
9d4c378c Fixes for switching to fullscreen mode from maximized state.
55a10919 Updates in menu items - Edit and Goto.
39f22c77 Updates in text editing, including new shortcuts.
a33ecee9 Updates in fullscreen mode.
89265a36 Change Fullscreen mode to Borderless Fullscreen (#85)
91f160c8 Added patrons; removed incorrect globals; added 'join the community' into Help menu; added 'close all tabs' in right click menu on tabs.
5d0126ae Added feature "Remove word before cursor" on windows/linux by Ctrl+Backspace.
ae63a504 Fixed #84. (opened incorrect tab if filename casing is incorrect)
36d619cb Fixed #83. (crashes on start when toolbar is hidden)
1791535a Fixed #82. (Strange bug in Rightclick Menu.)
17cf135b Merge branch 'dev'
b166ba7b Bump version.
b2c81127 Merge branch 'dev'
0b2c4eb4 Don't add 'Override' for interface members.
87531c64 Improvements in Source code tree (expanded state fixes).
aa7e490d Added fading for about dialog (to avoid dialog 'blending' with bananas showcase at the first run).
d1f5abe3 Search in docs improvements - try to be more accurately by F1.
99d025b1 Said goodbye to "optimization" for completion list - it ate our results!
81d012f6 Fixed #81. (if you use 'save' to change filetype, the editor thinks it's still the old type.)
b191d482 Fullscreen editor - added status bar and dirty-state-changed detection.
c9099f37 Added comment/uncomment to editor rightclick menu.
8102fd48 Fixed #79 by renaming png files. (Not all themes elements are changed by switching theme.)
478cb847 Updated.
ba64fee4 Fixed issue with non-existant module in module.json "depends" array.
6aded373 Added patrons to special thanks section (a few were already there).
5f8ca9e8 Save/load Verbose mode into prefs.
9ff2d560 Add Verbose CheckButton (#76)
d1de31ac Fixed #70 - sorting in docs tab.
8404ef44 Now uses SetConfig to set default theme.
2fb67b4b Changed AppInstance creation.
7c68d646 Hotkeys for Zoom in, out, default (#75)
ea1abb47 #73 Fix for fullscreen mode.
ffc15221 Added ability to change docs while in fullscreen mode.
140d3fbb Added "Fullscreen editor" mode in which we have editor view only (temporarily closing all other views).
2712cba8 Fix for json viewer.
7d6b50fe Json viewer - added ability to jump to values by clicking on Source tree view nodes.
8bc34b94 Enabled monkey2's highlighter for .json files.
906bf520 Don't reset syntax errors on document save.
0dce9252 Added fulscreen mode: menu Window -- Fullscreen mode (F11).
516b3f67 Fixed #67 - Can’t read the last item in completion list.
d580064a Attemp to pass event from hint to editor.
967c8d6b Close params hint by mouse click.
a79a6007 Merge branch 'params_hint' into dev
6a43bbe3 Done with hint for parameters. Added option into Preferences to enable / disable this hint.
784d8159 Almost done params hint.
036958b9 Added support for multiple module dirs via MX2_MODULE_DIRS env var.
a339f42d Removed unused imports.
322b93d3 (wip) Params hint.
b15b143d (wip) Params hint.
2f508071 Fixed file renaming (case-insensitive file system on Windows).
88155f33 Updates in docs selection.
81bcf8f9 #70. Fixed search-by-namespace in docs.
54b6e16a Updated mojo3d's template up to v1.1.08.
226dc456 Theme update.
905d60a6 MacOS Improvements (#69)
627b8754 Closed #68. Added - closing tabs by pressing middle mouse button.
d8dcce3d Some updates for "first app launch" - moved Source tab into left panel, changed bananas image sizes to fit into window.
2e8c8df0 Updated themes.
d2d55b5c Fixed Docs tree - open docs by second F1, improved node filtering.
c9c7b7d3 Fixed incorrect selection in tree views.
d5bfcbf6 Added '#Reflect' keyword.
552176d8 Improvement in parsing.
fbde4be9 Merge branch 'dev' of https://github.com/engor/Ted2Go into dev
467e2dc4 Removed unused imports.
d52150fb Project tree - added Cut / Copy / Paste actions on files and foldes.
b3e167db Fixed "Close tabs to the right" behaviour.
ddf08f96 Fixed #62.
6990910e Project tree - added confirm to replace items when drag-n-drop.
bd6df470 Added ability to drop files / folders from desktop explorer directly into specified folder inside of project tree. Added ability to copy dragged items by holding Ctrl key.
e7e16f94 Done with drag-n-drop inside of Project tree.
8de195b1 (wip) project tree
b0b11eb4 (wip) draggable project tree.
2174a913 Extract draggable tabs logic into own class to reuse for other cases.

git-subtree-dir: src/ted2go
git-subtree-split: 358f7111d41d5b4788d864cb1cf7d54711bfe316
Mark Sibly 7 years ago
parent
commit
1b419253cf
72 changed files with 3173 additions and 1007 deletions
  1. 2 1
      .gitignore
  2. 352 148
      MainWindow.monkey2
  3. 1 1
      Plugin.monkey2
  4. 3 0
      Prefs.monkey2
  5. 15 11
      Ted2.monkey2
  6. 94 0
      Tree.monkey2
  7. 67 16
      action/BuildActions.monkey2
  8. 106 1
      action/EditActions.monkey2
  9. 1 1
      action/FileActions.monkey2
  10. 36 32
      action/HelpActions.monkey2
  11. 3 3
      action/ViewActions.monkey2
  12. 76 0
      action/WindowActions.monkey2
  13. 1 1
      assets/aboutTed2Go.html
  14. 5 6
      assets/newfiles/Simple_Mojo3d_App.monkey2
  15. 0 0
      assets/themes/hollow_assets/hollow_checkbox_icons.png
  16. 0 0
      assets/themes/hollow_assets/hollow_dialog_skin.png
  17. 0 0
      assets/themes/hollow_assets/hollow_progressbar_icons.png
  18. 0 0
      assets/themes/hollow_assets/hollow_tabclose_icons.png
  19. 0 0
      assets/themes/hollow_assets/hollow_treeview_icons.png
  20. 0 0
      assets/themes/prime_assets/prime_checkbox_icons.png
  21. 0 0
      assets/themes/prime_assets/prime_dialog_skin.png
  22. 0 0
      assets/themes/prime_assets/prime_progressbar_icons.png
  23. 0 0
      assets/themes/prime_assets/prime_tabclose_icons.png
  24. 0 0
      assets/themes/prime_assets/prime_treeview_icons.png
  25. 0 0
      assets/themes/smooth_assets/smooth_button_skin.png
  26. 0 0
      assets/themes/smooth_assets/smooth_checkbox_icons.png
  27. 0 0
      assets/themes/smooth_assets/smooth_dialog_skin.png
  28. 0 0
      assets/themes/smooth_assets/smooth_progressbar_icons.png
  29. BIN
      assets/themes/smooth_assets/smooth_tabbutton_locked_skin.png
  30. 0 0
      assets/themes/smooth_assets/smooth_tabbutton_selected_skin.png
  31. 0 0
      assets/themes/smooth_assets/smooth_tabbutton_skin.png
  32. 0 0
      assets/themes/smooth_assets/smooth_tabclose_icons.png
  33. 0 0
      assets/themes/smooth_assets/smooth_treeview_icons.png
  34. 8 3
      assets/themes/ted2-default.json
  35. 14 7
      assets/themes/theme-hollow.json
  36. 11 6
      assets/themes/theme-prime-base.json
  37. 14 9
      assets/themes/theme-smooth.json
  38. 1 1
      assets/themes/theme-warm.json
  39. 42 0
      dialog/DialogExt.monkey2
  40. 1 1
      dialog/GenerateClassDialog.monkey2
  41. 7 1
      dialog/PrefsDialog.monkey2
  42. 47 54
      dialog/UpdateModulesDialog.monkey2
  43. 18 12
      document/BananasDocument.monkey2
  44. 441 49
      document/CodeDocument.monkey2
  45. 54 21
      document/DocumentManager.monkey2
  46. 59 4
      document/JsonDocument.monkey2
  47. 28 22
      document/Ted2Document.monkey2
  48. 1 5
      eventfilter/Monkey2KeyEventFilter.monkey2
  49. BIN
      logo/resource_x64.o
  50. 28 22
      parser/CodeItem.monkey2
  51. 132 46
      parser/Monkey2Parser.monkey2
  52. 11 3
      parser/Parser.monkey2
  53. 3 1
      product/BuildProduct.monkey2
  54. 50 40
      product/ModuleManager.monkey2
  55. 14 2
      product/Mx2ccEnv.monkey2
  56. 2 2
      syntax/Monkey2Highlighter.monkey2
  57. 11 0
      testing/ParserTests.monkey2
  58. 86 0
      testing/pixelPerfect.json
  59. 5 4
      utils/JsonUtils.monkey2
  60. 117 1
      utils/Utils.monkey2
  61. 33 33
      view/AutocompleteView.monkey2
  62. 131 35
      view/CodeTextView.monkey2
  63. 9 7
      view/CodeTreeView.monkey2
  64. 160 0
      view/DraggableViewListener.monkey2
  65. 198 99
      view/HelpTreeView.monkey2
  66. 12 2
      view/ListViewExt.monkey2
  67. 256 27
      view/ProjectBrowserView.monkey2
  68. 179 70
      view/ProjectView.monkey2
  69. 83 179
      view/TabViewExt.monkey2
  70. 31 7
      view/Ted2CodeTextView.monkey2
  71. 1 1
      view/ToolBarViewExt.monkey2
  72. 113 10
      view/TreeViewExt.monkey2

+ 2 - 1
.gitignore

@@ -2,4 +2,5 @@
 *.bak
 *.bak
 *.buildv*
 *.buildv*
 *.products/
 *.products/
-*.app
+*.app
+*.DS_*

+ 352 - 148
MainWindow.monkey2

@@ -45,13 +45,18 @@ Class MainWindowInstance Extends Window
 		_docsManager.CurrentDocumentChanged+=Lambda()
 		_docsManager.CurrentDocumentChanged+=Lambda()
 			
 			
 			UpdateKeyView()
 			UpdateKeyView()
-			CodeDocument.HideAutocomplete()
+			CodeDocument.HideAllPopups()
 			
 			
 			Local doc:=Cast<CodeTextView>( _docsManager.CurrentTextView )
 			Local doc:=Cast<CodeTextView>( _docsManager.CurrentTextView )
 			Local mode:=doc ? doc.OverwriteMode Else False
 			Local mode:=doc ? doc.OverwriteMode Else False
 			OverwriteTextMode=mode
 			OverwriteTextMode=mode
 			
 			
 			_findReplaceView.CodeView=Cast<CodeTextView>( _docsManager.CurrentTextView )
 			_findReplaceView.CodeView=Cast<CodeTextView>( _docsManager.CurrentTextView )
+			
+			If _fullscreenState=FullscreenState.Editor
+				SwapFullscreenEditor( False,1 )
+			Endif
+			
 		End
 		End
 		
 		
 		_docsManager.DocumentDoubleClicked+=Lambda( doc:Ted2Document )
 		_docsManager.DocumentDoubleClicked+=Lambda( doc:Ted2Document )
@@ -241,6 +246,7 @@ Class MainWindowInstance Extends Window
 		_tabMenu.AddAction( _fileActions.close )
 		_tabMenu.AddAction( _fileActions.close )
 		_tabMenu.AddAction( _fileActions.closeOthers )
 		_tabMenu.AddAction( _fileActions.closeOthers )
 		_tabMenu.AddAction( _fileActions.closeToRight )
 		_tabMenu.AddAction( _fileActions.closeToRight )
+		_tabMenu.AddAction( _fileActions.closeAll )
 		_tabMenu.AddSeparator()
 		_tabMenu.AddSeparator()
 		_tabMenu.AddAction( _fileActions.save )
 		_tabMenu.AddAction( _fileActions.save )
 		_tabMenu.AddAction( _fileActions.saveAs )
 		_tabMenu.AddAction( _fileActions.saveAs )
@@ -312,8 +318,30 @@ Class MainWindowInstance Extends Window
 		_editMenu.AddSeparator()
 		_editMenu.AddSeparator()
 		_editMenu.AddAction( _editActions.selectAll )
 		_editMenu.AddAction( _editActions.selectAll )
 		_editMenu.AddSeparator()
 		_editMenu.AddSeparator()
+		' Edit -- Text
+		Local subText:=New MenuExt( "Text" )
+		subText.AddAction( _editActions.textDeleteWordForward )
+		subText.AddAction( _editActions.textDeleteWordBackward )
+		subText.AddAction( _editActions.textDeleteLine )
+		subText.AddAction( _editActions.textDeleteToEnd )
+		subText.AddAction( _editActions.textDeleteToBegin )
+		_editMenu.AddSubMenu( subText )
+		' Edit -- Comment
+		Local subComment:=New MenuExt( "Comment" )
+		subComment.AddAction( _viewActions.comment )
+		subComment.AddAction( _viewActions.uncomment )
+		_editMenu.AddSubMenu( subComment )
+		' Edit -- Convert case
+		Local subCase:=New MenuExt( "Convert case" )
+		subCase.AddAction( _editActions.textUppercase )
+		subCase.AddAction( _editActions.textLowercase )
+		subCase.AddAction( _editActions.textSwapCase )
+		_editMenu.AddSubMenu( subCase )
+		'
+		_editMenu.AddSeparator()
 		_editMenu.AddAction( _editActions.wordWrap )
 		_editMenu.AddAction( _editActions.wordWrap )
 		
 		
+		
 		'Find menu
 		'Find menu
 		'
 		'
 		_findMenu=New MenuExt( "Find" )
 		_findMenu=New MenuExt( "Find" )
@@ -324,17 +352,14 @@ Class MainWindowInstance Extends Window
 		_findMenu.AddSeparator()
 		_findMenu.AddSeparator()
 		_findMenu.AddAction( _findActions.findInFiles )
 		_findMenu.AddAction( _findActions.findInFiles )
 		
 		
-		'View menu
+		'Goto menu
 		'
 		'
-		_viewMenu=New MenuExt( "View" )
-		_viewMenu.AddAction( _viewActions.gotoLine )
-		_viewMenu.AddAction( _viewActions.gotoDeclaration )
-		_viewMenu.AddSeparator()
-		_viewMenu.AddAction( _viewActions.comment )
-		_viewMenu.AddAction( _viewActions.uncomment )
-		_viewMenu.AddSeparator()
-		_viewMenu.AddAction( _viewActions.goBack )
-		_viewMenu.AddAction( _viewActions.goForward )
+		_gotoMenu=New MenuExt( "Goto" )
+		_gotoMenu.AddAction( _viewActions.gotoLine )
+		_gotoMenu.AddAction( _viewActions.gotoDeclaration )
+		_gotoMenu.AddSeparator()
+		_gotoMenu.AddAction( _viewActions.goBack )
+		_gotoMenu.AddAction( _viewActions.goForward )
 		
 		
 		'Build menu
 		'Build menu
 		'
 		'
@@ -366,15 +391,19 @@ Class MainWindowInstance Extends Window
 		
 		
 		'Window menu
 		'Window menu
 		'
 		'
+		Local windowActions:=New WindowActions( _docsManager )
 		_windowMenu=New MenuExt( "Window" )
 		_windowMenu=New MenuExt( "Window" )
-		_windowMenu.AddAction( _docsManager.nextDocument )
-		_windowMenu.AddAction( _docsManager.prevDocument )
+		_windowMenu.AddAction( windowActions.nextTab )
+		_windowMenu.AddAction( windowActions.prevTab )
 		_windowMenu.AddSeparator()
 		_windowMenu.AddSeparator()
-		
-		_themesMenu=CreateThemesMenu( "Themes" )
-		
-		AddZoomActions( _windowMenu )
+		_windowMenu.AddAction( windowActions.fullscreenWindow )
+		_windowMenu.AddAction( windowActions.fullscreenEditor )
 		_windowMenu.AddSeparator()
 		_windowMenu.AddSeparator()
+		_windowMenu.AddAction( windowActions.zoomIn )
+		_windowMenu.AddAction( windowActions.zoomOut )
+		_windowMenu.AddAction( windowActions.zoomDefault )
+		_windowMenu.AddSeparator()
+		_themesMenu=CreateThemesMenu( "Themes" )
 		_windowMenu.AddSubMenu( _themesMenu )
 		_windowMenu.AddSubMenu( _themesMenu )
 		
 		
 		
 		
@@ -395,6 +424,7 @@ Class MainWindowInstance Extends Window
 		_helpMenu.AddAction( _helpActions.aboutTed2go )
 		_helpMenu.AddAction( _helpActions.aboutTed2go )
 		_helpMenu.AddSeparator()
 		_helpMenu.AddSeparator()
 		_helpMenu.AddAction( _helpActions.makeBetter )
 		_helpMenu.AddAction( _helpActions.makeBetter )
+		_helpMenu.AddAction( _helpActions.joinCommunity )
 		
 		
 		'Menu bar
 		'Menu bar
 		'
 		'
@@ -402,7 +432,7 @@ Class MainWindowInstance Extends Window
 		_menuBar.AddMenu( _fileMenu )
 		_menuBar.AddMenu( _fileMenu )
 		_menuBar.AddMenu( _editMenu )
 		_menuBar.AddMenu( _editMenu )
 		_menuBar.AddMenu( _findMenu )
 		_menuBar.AddMenu( _findMenu )
-		_menuBar.AddMenu( _viewMenu )
+		_menuBar.AddMenu( _gotoMenu )
 		_menuBar.AddMenu( _buildMenu )
 		_menuBar.AddMenu( _buildMenu )
 		_menuBar.AddMenu( _windowMenu )
 		_menuBar.AddMenu( _windowMenu )
 		_menuBar.AddMenu( _helpMenu )
 		_menuBar.AddMenu( _helpMenu )
@@ -425,8 +455,10 @@ Class MainWindowInstance Extends Window
 		
 		
 		ArrangeElements()
 		ArrangeElements()
 		
 		
+		'_helpTree.QuickHelp( "" )
+		
 		ContentView=_contentView
 		ContentView=_contentView
-
+		
 		OnCreatePlugins() 'init plugins before loadstate, to register doctypes before open last opened files
 		OnCreatePlugins() 'init plugins before loadstate, to register doctypes before open last opened files
 		
 		
 		LoadState( jobj )
 		LoadState( jobj )
@@ -592,6 +624,7 @@ Class MainWindowInstance Extends Window
 	Method Terminate()
 	Method Terminate()
 		
 		
 		_isTerminating=True
 		_isTerminating=True
+		
 		SaveState()
 		SaveState()
 		_enableSaving=False
 		_enableSaving=False
 		OnForceStop() ' kill build process if started
 		OnForceStop() ' kill build process if started
@@ -665,6 +698,96 @@ Class MainWindowInstance Extends Window
 		_modsDir=RealPath( "modules/" )
 		_modsDir=RealPath( "modules/" )
 	End
 	End
 	
 	
+	Method SwapFullscreenWindow()
+		
+		If _fullscreenState=FullscreenState.Editor
+			SwapFullscreenEditor()
+			Return
+		Endif
+		
+		If Not _fullscreen
+			_storedSize=Frame
+			_storedMaximized=Maximized
+		Endif
+		
+		_fullscreen=Not _fullscreen
+		_fullscreenState=_fullscreen ? FullscreenState.Window Else FullscreenState.None
+		
+		UpdateFullscreenMode()
+		
+	End
+	
+	' customState: -1 - make windowed, 1 - make fullscreen
+	'
+	Method SwapFullscreenEditor( justStarted:Bool=False,customState:Int=0 )
+		
+		If Not justStarted And _docsManager.CurrentDocument=Null
+			Alert( "There is no editor to be fullscreened!","Fullscreen" )
+			Return
+		Endif
+		
+		If Not _fullscreen
+			_storedSize=Frame
+			_storedMaximized=Maximized
+		Endif
+		
+		' restore
+		If _fullscreenHelper.storedContentView<>Null
+			Local view:=_fullscreenHelper.editorContainer.ContentView
+			view.Layout="fill"
+			_fullscreenHelper.editorContainer.ContentView=Null
+			_fullscreenHelper.statusContainer.ContentView=Null
+			_statusBarContainer.ContentView=_statusBar
+			ContentView=_fullscreenHelper.storedContentView
+			_docsTabView.SetTabView( _fullscreenHelper.storedTabIndex,view )
+			_docsTabView.EnsureVisibleCurrentTab()
+			_docsManager.UpdateCurrentTabLabel()
+			_docsManager.CurrentDocument?.DirtyChanged-=_fullscreenHelper.UpdateTitle
+			_fullscreenHelper.storedContentView=Null
+		Endif
+		
+		' stay in fullscreen
+		If _fullscreenPrevState=FullscreenState.Window 
+			_fullscreenState=FullscreenState.Window 
+			_fullscreenPrevState=FullscreenState.None 
+			Return
+		Endif
+		
+		_fullscreenPrevState=_fullscreenState
+		
+		Local state:=Not _fullscreen
+		
+		If customState<>0 Then state=(customState > 0)
+		If _fullscreenState<>FullscreenState.Window Then _fullscreen=state
+		
+		_fullscreenState=_fullscreen ? FullscreenState.Editor Else FullscreenState.None
+		
+		UpdateFullscreenMode()
+		
+		If _fullscreen
+			_fullscreenHelper.storedContentView=ContentView
+			_fullscreenHelper.storedTabIndex=_docsTabView.CurrentIndex
+			_docsTabView.SetTabView( _fullscreenHelper.storedTabIndex,Null )
+			Local view:=_docsManager.CurrentView
+			view.Layout="fill-y"
+			view.Gravity=New Vec2f( .5,0 )
+			Local sz:=New Vec2i( Int(App.DesktopSize.x*.7),100000 )
+			view.MaxSize=sz
+			view.MinSize=sz
+			_fullscreenHelper.editorContainer.ContentView=view
+			_fullscreenHelper.titleLabel.Text=_docsManager.CurrentDocumentLabel
+			_docsManager.CurrentDocument?.DirtyChanged+=_fullscreenHelper.UpdateTitle
+			' status bar
+			_statusBarContainer.ContentView=Null
+			_fullscreenHelper.statusContainer.ContentView=_statusBar
+			'
+			ContentView=_fullscreenHelper.editorContainer
+			
+			_docsManager.CurrentTextView?.MakeKeyView()
+			
+		Endif
+	End
+	
 	Method StoreConsoleVisibility()
 	Method StoreConsoleVisibility()
 	
 	
 		'If Prefs.SiblyMode return
 		'If Prefs.SiblyMode return
@@ -853,99 +976,115 @@ Class MainWindowInstance Extends Window
 		
 		
 		Local tab:=_tabsWrap.tabs["Build"]
 		Local tab:=_tabsWrap.tabs["Build"]
 		tab.Activate()
 		tab.Activate()
-		If vis tab.ParentDock.Visible=True
+		If vis tab.CurrentHolder.Visible=True
 	End
 	End
 	
 	
 	Method ShowOutputConsole( vis:Bool=True )
 	Method ShowOutputConsole( vis:Bool=True )
 		
 		
 		Local tab:=_tabsWrap.tabs["Output"]
 		Local tab:=_tabsWrap.tabs["Output"]
 		tab.Activate()
 		tab.Activate()
-		If vis tab.ParentDock.Visible=True
+		If vis tab.CurrentHolder.Visible=True
 	End
 	End
 	
 	
-	Method ShowHelpView()
+	Method ShowDocsView( expandTree:Bool=False )
 		
 		
 		Local tab:=_tabsWrap.tabs["Docs"]
 		Local tab:=_tabsWrap.tabs["Docs"]
 		tab.Activate()
 		tab.Activate()
-		tab.ParentDock.Visible=True
+		tab.CurrentHolder.Visible=True
+		
+		If expandTree
+			_helpTree.Visible=False
+			_helpSwitcher.Clicked()
+		Endif
 	End
 	End
 	
 	
 	Method ShowFindResults()
 	Method ShowFindResults()
 		
 		
 		Local tab:=_tabsWrap.tabs["Find"]
 		Local tab:=_tabsWrap.tabs["Find"]
 		tab.Activate()
 		tab.Activate()
-		tab.ParentDock.Visible=True
+		tab.CurrentHolder.Visible=True
 	End
 	End
 	
 	
-	Method ShowFindInDocs()
+	Method RebuildDocs()
 		
 		
-		Local doc:=Cast<CodeDocumentView>( _docsManager.CurrentTextView )
-		If Not doc Return
-		
-		Local ident:=doc.WordAtCursor
-		Print "ident: "+ident
-		_helpTree.QuickHelp( ident )
-		_helpTree.Visible=False
-		_helpSwitcher.Clicked()
-		_tabsWrap.tabs["Docs"].Activate()
+		_buildActions.rebuildHelp.Trigger()
 	End
 	End
 	
 	
-	Method ShowQuickHelp()
+	Method ShowHelp( url:String="",searchMode:Bool=False )
+		
+		' direct jump
+		If url
+			_helpView.Navigate( url )
+			_helpView.Scroll=New Vec2i( 0,0 )
+			ShowDocsView()
+			Return
+		Endif
 		
 		
 		Local doc:=Cast<CodeDocumentView>( _docsManager.CurrentTextView )
 		Local doc:=Cast<CodeDocumentView>( _docsManager.CurrentTextView )
 		If Not doc Return
 		If Not doc Return
 		
 		
+		' don't check with parser, just find in docs tree
+		If searchMode
+			Local ident:=doc.WordAtCursor
+			_helpTree.QuickHelp( ident )
+			ShowDocsView( True )
+			Return
+		Endif
+		
 		Local ident:=doc.FullIdentAtCursor
 		Local ident:=doc.FullIdentAtCursor
 		
 		
 		If Not ident Return
 		If Not ident Return
 		
 		
 		Local parser:=ParsersManager.Get( doc.FileType )
 		Local parser:=ParsersManager.Get( doc.FileType )
 		Local item:=parser.ItemAtScope( ident,doc.FilePath,doc.LineNumAtCursor )
 		Local item:=parser.ItemAtScope( ident,doc.FilePath,doc.LineNumAtCursor )
+		
 		If item
 		If item
-			Local s:=item.Namespac
-			If s
-				Local i:=s.Find( "." )
-				If i<>-1 Then s=s.Slice( 0,i )
-			Endif
-			Local ident2:="",parentIdent:=""
-			ident=s+":"+item.Namespac+"."
-			If item.Parent
-				If item.Parent.IsLikeClass
-					parentIdent=item.Parent.Ident
-					ident2=s+":"+parentIdent+"."+item.Ident
-				Endif
-				ident+=item.Parent.Ident+"."
-			Endif
-			ident+=item.Ident
 			
 			
-			If ident=_helpIdent
-				If item.IsModuleMember
-					Local url:=_helpTree.PageUrl( ident )
-					If GetFileType( url )<>FileType.File Then url=_helpTree.PageUrl( ident2 )
+			ident=item.Ident
+			
+			Local pathTemplate:=Prefs.MonkeyRootPath+"docs/modules/{mod-name}/module/{path-to-ident}.html"
+			Local modName:=item.ModuleName
+			
+			Local pathToIdent:=(item.Namespac+"."+item.Scope).Replace( ".","-" )
+			Local path:=pathTemplate.Replace( "{mod-name}",modName ).Replace( "{path-to-ident}",pathToIdent )
+			
+			Global __prevPath:=""
+			
+			If path=__prevPath
+				
+				If modName ' show docs for modules members
+					
+					_helpTree.QuickHelp( ident )
+					
+					_helpView.Navigate( path )
+					_helpView.Scroll=New Vec2i( 0,0 )
+					
+					_helpTree.Selected=_helpTree.FindByText( ident )
+					
+					ShowDocsView( True )
+					
+				Else ' or jump to non modules members
 					
 					
-					If GetFileType( url )<>FileType.File
-						Local ext:=ExtractExt( url )
-						Repeat
-							Local i:=url.FindLast( "-" )
-							If i=-1
-								url=""
-								Exit
-							Endif
-							url=url.Slice( 0,i )+ext
-						Forever
-					Endif
-					If url ShowHelp( url )
-				Else
 					GotoCodePosition( item.FilePath,item.ScopeStartPos )
 					GotoCodePosition( item.FilePath,item.ScopeStartPos )
+					
 				Endif
 				Endif
 			Else
 			Else
+				
+				Local parentIdent:=""
+				If item.Parent
+					If item.Parent.IsLikeClass
+						parentIdent=item.Parent.Ident
+					Endif
+				Endif
+				
 				Local nmspace:=item.Namespac
 				Local nmspace:=item.Namespac
 				If parentIdent Then nmspace+="."+parentIdent
 				If parentIdent Then nmspace+="."+parentIdent
 				Local ext:=item.IsExtension ? "(ext) " Else ""
 				Local ext:=item.IsExtension ? "(ext) " Else ""
 				ShowStatusBarText( ext+"("+item.KindStr+") "+item.Text+"    |  "+nmspace+"  |  "+StripDir( item.FilePath )+"  |  line "+(item.ScopeStartPos.x+1) )
 				ShowStatusBarText( ext+"("+item.KindStr+") "+item.Text+"    |  "+nmspace+"  |  "+StripDir( item.FilePath )+"  |  line "+(item.ScopeStartPos.x+1) )
+			
 			Endif
 			Endif
 			
 			
-			_helpIdent=ident
+			__prevPath=path
 			
 			
 		ElseIf KeywordsManager.Get( doc.FileType ).Contains( ident )
 		ElseIf KeywordsManager.Get( doc.FileType ).Contains( ident )
 			
 			
@@ -953,19 +1092,12 @@ Class MainWindowInstance Extends Window
 		
 		
 		Else
 		Else
 			
 			
-			ShowFindInDocs()
+			ShowHelp( "",True ) ' try to search ident
 			
 			
 		Endif
 		Endif
 		
 		
 	End
 	End
 	
 	
-	Method ShowHelp( url:String )
-		
-		ShowHelpView()
-		_helpView.Navigate( url )
-		_helpView.Scroll=New Vec2i( 0,0 )
-	End
-	
 	Method ShowEditorMenu( tv:TextView )
 	Method ShowEditorMenu( tv:TextView )
 		
 		
 		If Not tv Then tv=_docsManager.CurrentTextView
 		If Not tv Then tv=_docsManager.CurrentTextView
@@ -978,24 +1110,31 @@ Class MainWindowInstance Extends Window
 			_editorMenu.AddAction( _editActions.cut )
 			_editorMenu.AddAction( _editActions.cut )
 			_editorMenu.AddAction( _editActions.copy )
 			_editorMenu.AddAction( _editActions.copy )
 			_editorMenu.AddAction( _editActions.paste )
 			_editorMenu.AddAction( _editActions.paste )
+			_editorMenu.AddSeparator()
+			_editorMenu.AddAction( _viewActions.comment )
+			_editorMenu.AddAction( _viewActions.uncomment )
 		Endif
 		Endif
 		
 		
 		_editorMenu.Open()
 		_editorMenu.Open()
 	End
 	End
 	
 	
 	Method UpdateHelpTree()
 	Method UpdateHelpTree()
-		_helpTree.Update()
+		
+		_helpTree.Update( True )
 	End
 	End
 	
 	
 	Method ShowBananasShowcase()
 	Method ShowBananasShowcase()
+		
 		OpenDocument( Prefs.MonkeyRootPath+"bananas/ted2go-showcase/all.bananas" )
 		OpenDocument( Prefs.MonkeyRootPath+"bananas/ted2go-showcase/all.bananas" )
 	End
 	End
 	
 	
 	Method ReadError( path:String )
 	Method ReadError( path:String )
+		
 		Alert( "I/O Error reading file '"+path+"'" )
 		Alert( "I/O Error reading file '"+path+"'" )
 	End
 	End
 	
 	
 	Method WriteError( path:String )
 	Method WriteError( path:String )
+		
 		Alert( "I/O Error writing file '"+path+"'" )
 		Alert( "I/O Error writing file '"+path+"'" )
 	End
 	End
 
 
@@ -1012,6 +1151,31 @@ Class MainWindowInstance Extends Window
 		Endif
 		Endif
 	End
 	End
 	
 	
+	Method UpdateFullscreenMode()
+		
+		If _fullscreen
+			
+			Local bounds:SDL_Rect
+			SDL_GetDisplayBounds( SDL_GetWindowDisplayIndex(Window.SDLWindow),Varptr bounds )
+			
+			If _storedMaximized Then Restore()
+			
+			SDL_SetWindowSize( Window.SDLWindow,bounds.w,bounds.h )
+			SDL_SetWindowPosition( Window.SDLWindow,bounds.x,bounds.y )
+			
+			' Frame=... doesn't work here
+		Else
+			
+			SDL_SetWindowSize( Window.SDLWindow,_storedSize.Width,_storedSize.Height )
+			SDL_SetWindowPosition( Window.SDLWindow,_storedSize.Left,_storedSize.Top )
+			
+			If _storedMaximized Then Maximize()
+			
+		End
+		
+		SendWindowEvent( New WindowEvent( EventType.WindowResized,Self ) )
+	End
+	
 	Method GotoCodePosition( docPath:String,pos:Vec2i,lenToSelect:Int=0 )
 	Method GotoCodePosition( docPath:String,pos:Vec2i,lenToSelect:Int=0 )
 		
 		
 		Local doc:=Cast<CodeDocument>( _docsManager.OpenDocument( docPath,True ) )
 		Local doc:=Cast<CodeDocument>( _docsManager.OpenDocument( docPath,True ) )
@@ -1053,12 +1217,16 @@ Class MainWindowInstance Extends Window
 	End
 	End
 	
 	
 	Method SaveState()
 	Method SaveState()
-	
+		
 		If Not _enableSaving Return
 		If Not _enableSaving Return
-
+		
 		Local jobj:=New JsonObject
 		Local jobj:=New JsonObject
 		
 		
-		jobj["windowRect"]=ToJson( Frame )
+		Local state:=_fullscreenState
+		If state=FullscreenState.None Then _storedSize=Frame
+		
+		jobj["windowRect"]=ToJson( _storedSize )
+		jobj["windowState"]=New JsonNumber( Int(state) )
 		
 		
 		SaveTabsState( jobj )
 		SaveTabsState( jobj )
 		
 		
@@ -1120,13 +1288,11 @@ Class MainWindowInstance Extends Window
 
 
 	Private
 	Private
 	
 	
-	Field _inited:=False
-	Field _helpIdent:String
-	
 	Method OnRender( canvas:Canvas ) Override
 	Method OnRender( canvas:Canvas ) Override
 		
 		
-		If Not _inited
-			_inited=True
+		Global __inited:=False
+		If Not __inited
+			__inited=True
 			OnInit()
 			OnInit()
 		Endif
 		Endif
 		
 		
@@ -1150,11 +1316,14 @@ Class MainWindowInstance Extends Window
 	
 	
 	Method OnFileDropped( path:String )
 	Method OnFileDropped( path:String )
 		
 		
-		If FileExists( path )
-			_docsManager.OpenDocument( path,True )
-		Else
-			_projectView.OpenProject( path )
-		Endif
+		New Fiber( Lambda()
+			
+			Local ok:=_projectView.OnFileDropped( path )
+			If Not ok And FileExists( path ) 'file
+				_docsManager.OpenDocument( path,True )
+			Endif
+			
+		End )
 	End
 	End
 	
 	
 	Method OnAppClose()
 	Method OnAppClose()
@@ -1248,7 +1417,7 @@ Class MainWindowInstance Extends Window
 				mentionStr+=message.fromUser+" in "
 				mentionStr+=message.fromUser+" in "
 				mentionStr+=container.name
 				mentionStr+=container.name
 				
 				
-				Local dock:=_tabsWrap.tabs["Chat"].ParentDock '_tabsWrap.docks["bottom"]
+				Local dock:=_tabsWrap.tabs["Chat"].CurrentHolder '_tabsWrap.docks["bottom"]
 				ShowHint( mentionStr, New Vec2i( 0, -GetStyle( "Hint" ).Font.Height*4 ), dock, 20000 )
 				ShowHint( mentionStr, New Vec2i( 0, -GetStyle( "Hint" ).Font.Height*4 ), dock, 20000 )
 				
 				
 			Endif
 			Endif
@@ -1308,7 +1477,7 @@ Class MainWindowInstance Extends Window
 		InitTabs()
 		InitTabs()
 		
 		
 		_contentView.RemoveView( _toolBar )
 		_contentView.RemoveView( _toolBar )
-		_contentView.RemoveView( _statusBar )
+		_contentView.RemoveView( _statusBarContainer )
 		_contentView.RemoveView( _findReplaceView )
 		_contentView.RemoveView( _findReplaceView )
 		
 		
 		_tabsWrap.DetachFromParent()
 		_tabsWrap.DetachFromParent()
@@ -1318,7 +1487,11 @@ Class MainWindowInstance Extends Window
 			_contentView.AddView( _toolBar,"top" )
 			_contentView.AddView( _toolBar,"top" )
 		Endif
 		Endif
 		
 		
-		_contentView.AddView( _statusBar,"bottom" )
+		If Not _statusBarContainer
+			_statusBarContainer=New DockingView
+			_statusBarContainer.ContentView=_statusBar
+		Endif
+		_contentView.AddView( _statusBarContainer,"bottom" )
 		
 		
 		_tabsWrap.AttachToParent( _contentView )
 		_tabsWrap.AttachToParent( _contentView )
 		
 		
@@ -1328,23 +1501,22 @@ Class MainWindowInstance Extends Window
 		
 		
 		_contentView.ContentView=_docsTabView
 		_contentView.ContentView=_docsTabView
 		
 		
-		
 	End
 	End
 	
 	
 	Method LoadTabsState( jobj:JsonObject )
 	Method LoadTabsState( jobj:JsonObject )
 		
 		
 		Global places:=New StringMap<StringStack>
 		Global places:=New StringMap<StringStack>
 		' defaults
 		' defaults
-		Local s:=""
-		places["left"]=New StringStack
-		s="Project,Source,Debug,Help"
+		Local s:="Source"
+		places["left"]=New StringStack( s.Split( "," ) )
+		s="Project,Debug"
 		places["right"]=New StringStack( s.Split( "," ) )
 		places["right"]=New StringStack( s.Split( "," ) )
 		s="Build,Output,Docs,Find,Chat"
 		s="Build,Output,Docs,Find,Chat"
 		places["bottom"]=New StringStack( s.Split( "," ) )
 		places["bottom"]=New StringStack( s.Split( "," ) )
 		
 		
 		Global actives:=New StringMap<String>
 		Global actives:=New StringMap<String>
 		' defaults
 		' defaults
-		actives["left"]="Project"
+		actives["left"]="Source"
 		actives["right"]="Project"
 		actives["right"]="Project"
 		actives["bottom"]="Docs"
 		actives["bottom"]="Docs"
 		
 		
@@ -1409,7 +1581,7 @@ Class MainWindowInstance Extends Window
 		
 		
 		For Local edge:=Eachin edges
 		For Local edge:=Eachin edges
 			Local dock:=_tabsWrap.docks[edge]
 			Local dock:=_tabsWrap.docks[edge]
-			jj[edge+"Tabs"]=JsonArray.Create( dock.TabsNames )
+			jj[edge+"Tabs"]=JsonArray.FromStrings( dock.TabsNames )
 			jj[edge+"Active"]=New JsonString( dock.ActiveName )
 			jj[edge+"Active"]=New JsonString( dock.ActiveName )
 			jj[edge+"Visible"]=New JsonBool( dock.Visible )
 			jj[edge+"Visible"]=New JsonBool( dock.Visible )
 			jj[edge+"Size"]=New JsonString( _tabsWrap.GetDockSize( dock ) )
 			jj[edge+"Size"]=New JsonString( _tabsWrap.GetDockSize( dock ) )
@@ -1417,7 +1589,7 @@ Class MainWindowInstance Extends Window
 	End
 	End
 	
 	
 	Method LoadState( jobj:JsonObject )
 	Method LoadState( jobj:JsonObject )
-	
+		
 		LoadTabsState( jobj )
 		LoadTabsState( jobj )
 		
 		
 		If jobj.Contains( "docsTab" )
 		If jobj.Contains( "docsTab" )
@@ -1448,8 +1620,8 @@ Class MainWindowInstance Extends Window
 		If jobj.Contains( "theme" ) ThemeName=jobj.GetString( "theme" )
 		If jobj.Contains( "theme" ) ThemeName=jobj.GetString( "theme" )
 		
 		
 		If jobj.Contains( "themeScale" )
 		If jobj.Contains( "themeScale" )
-			_themeScale=jobj.GetNumber( "themeScale" )
-			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+			Local sc:=jobj.GetNumber( "themeScale" )
+			App.Theme.Scale=New Vec2f( sc )
 		Endif
 		Endif
 		
 		
 		If jobj.Contains( "mx2ccDir" )
 		If jobj.Contains( "mx2ccDir" )
@@ -1469,9 +1641,17 @@ Class MainWindowInstance Extends Window
 			UpdateRecentFilesMenu()
 			UpdateRecentFilesMenu()
 			UpdateRecentProjectsMenu()
 			UpdateRecentProjectsMenu()
 			UpdateCloseProjectMenu()
 			UpdateCloseProjectMenu()
-
+			
 			DeleteTmps()
 			DeleteTmps()
 			
 			
+			' enter fullscreen mode
+			Local state:=Json_GetInt( jobj.Data,"windowState",0 )
+			If state=1
+				SwapFullscreenWindow()
+			Elseif state=2
+				SwapFullscreenEditor( True )
+			Endif
+			
 		End
 		End
 	End
 	End
 	
 	
@@ -1486,6 +1666,11 @@ Class MainWindowInstance Extends Window
 			Select event.Key
 			Select event.Key
 			Case Key.Escape
 			Case Key.Escape
 				
 				
+				If _fullscreenState=FullscreenState.Editor
+					SwapFullscreenEditor()
+					Return
+				Endif
+					
 				' hide find / replace panel
 				' hide find / replace panel
 				If HideFindPanel()
 				If HideFindPanel()
 					Return
 					Return
@@ -1579,7 +1764,7 @@ Class MainWindowInstance Extends Window
 	Field _fileMenu:MenuExt
 	Field _fileMenu:MenuExt
 	Field _editMenu:MenuExt
 	Field _editMenu:MenuExt
 	Field _findMenu:MenuExt
 	Field _findMenu:MenuExt
-	Field _viewMenu:MenuExt
+	Field _gotoMenu:MenuExt
 	Field _buildMenu:MenuExt
 	Field _buildMenu:MenuExt
 	Field _windowMenu:MenuExt
 	Field _windowMenu:MenuExt
 	Field _helpMenu:MenuExt
 	Field _helpMenu:MenuExt
@@ -1588,7 +1773,6 @@ Class MainWindowInstance Extends Window
 	Field _themesMenu:MenuExt
 	Field _themesMenu:MenuExt
 	
 	
 	Field _theme:="default"
 	Field _theme:="default"
-	Field _themeScale:=1.0
 	
 	
 	Field _contentView:DockingView
 	Field _contentView:DockingView
 	
 	
@@ -1599,6 +1783,7 @@ Class MainWindowInstance Extends Window
 	Field _recentProjectsMenu:MenuExt
 	Field _recentProjectsMenu:MenuExt
 	Field _closeProjectMenu:MenuExt
 	Field _closeProjectMenu:MenuExt
 	Field _statusBar:StatusBarView
 	Field _statusBar:StatusBarView
+	Field _statusBarContainer:DockingView
 	Field _ovdMode:=False
 	Field _ovdMode:=False
 	Field _storedConsoleVisible:Bool
 	Field _storedConsoleVisible:Bool
 	Field _consoleVisibleCounter:=0
 	Field _consoleVisibleCounter:=0
@@ -1608,6 +1793,11 @@ Class MainWindowInstance Extends Window
 	Field _findReplaceView:FindReplaceView
 	Field _findReplaceView:FindReplaceView
 	Field _tabsWrap:=New DraggableTabs
 	Field _tabsWrap:=New DraggableTabs
 	
 	
+	Field _fullscreen:Bool
+	Field _fullscreenState:=FullscreenState.None,_fullscreenPrevState:=FullscreenState.None
+	Field _fullscreenHelper:= New FullscreenHelper
+	Field _storedSize:Recti,_storedMaximized:Bool
+	
 	Method ToJson:JsonValue( rect:Recti )
 	Method ToJson:JsonValue( rect:Recti )
 		Return New JsonArray( New JsonValue[]( New JsonNumber( rect.min.x ),New JsonNumber( rect.min.y ),New JsonNumber( rect.max.x ),New JsonNumber( rect.max.y ) ) )
 		Return New JsonArray( New JsonValue[]( New JsonNumber( rect.min.x ),New JsonNumber( rect.min.y ),New JsonNumber( rect.max.x ),New JsonNumber( rect.max.y ) ) )
 	End
 	End
@@ -1692,53 +1882,26 @@ Class MainWindowInstance Extends Window
 		Next
 		Next
 	End
 	End
 	
 	
-	Method AddZoomActions( menu:MenuExt )
-		
-		menu.AddAction( "Zoom in" ).Triggered=Lambda()
-			If _themeScale>=4 Return
-			
-			_themeScale+=.125
-
-			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
-		End
-		
-		menu.AddAction( "Zoom out" ).Triggered=Lambda()
-			If _themeScale<=.5 Return
-			
-			_themeScale-=.125
-
-			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
-		End
-		
-		menu.AddAction( "Reset zoom" ).Triggered=Lambda()
-		
-			_themeScale=1
-			
-			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
-		End
-	End
-
 	Method ThemeScaleMouseFilter( event:MouseEvent )
 	Method ThemeScaleMouseFilter( event:MouseEvent )
-	
+		
 		If event.Eaten Return
 		If event.Eaten Return
-			
+		
 		If event.Type=EventType.MouseWheel And event.Modifiers & Modifier.Menu
 		If event.Type=EventType.MouseWheel And event.Modifiers & Modifier.Menu
 			
 			
+			Local sc:=App.Theme.Scale.x
 			If event.Wheel.y>0
 			If event.Wheel.y>0
-				If _themeScale<4 _themeScale+=0.125
+				If sc<4 sc+=0.125
 			Else
 			Else
-				If _themeScale>.5 _themeScale-=0.125
+				If sc>.5 sc-=0.125
 			Endif
 			Endif
-				
-			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
-
+			
+			App.Theme.Scale=New Vec2f( sc )
+			
 			event.Eat()
 			event.Eat()
-				
+			
 		Else If event.Type=EventType.MouseDown And event.Button=MouseButton.Middle And event.Modifiers & Modifier.Menu
 		Else If event.Type=EventType.MouseDown And event.Button=MouseButton.Middle And event.Modifiers & Modifier.Menu
 			
 			
-			_themeScale=1
-
-			App.Theme.Scale=New Vec2f( _themeScale,_themeScale )
+			App.Theme.Scale=New Vec2f( 1 )
 			
 			
 			event.Eat()
 			event.Eat()
 		Endif
 		Endif
@@ -1760,15 +1923,16 @@ Class MainWindowInstance Extends Window
 				If value=ThemeName Return
 				If value=ThemeName Return
 				
 				
 				ThemeName=value
 				ThemeName=value
+				Local sc:=App.Theme.Scale.x
 				
 				
-				App.Theme.Load( _theme,New Vec2f( _themeScale ) )
+				App.Theme.Load( _theme,New Vec2f( sc ) )
 				SaveState()
 				SaveState()
 			End
 			End
 		Next
 		Next
 		
 		
 		Return menu
 		Return menu
 	End
 	End
-		
+	
 	Method OnAppIdle()
 	Method OnAppIdle()
 		
 		
 		_docsManager.Update()
 		_docsManager.Update()
@@ -1778,9 +1942,11 @@ Class MainWindowInstance Extends Window
 		_buildActions.Update()
 		_buildActions.Update()
 		
 		
 		_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 )
+		
+		If _saveItem ' when toolbar is visible
+			_saveItem.SetIcon( _fileActions.save.Enabled ? 1 Else 0 )
+			_saveAllItem.SetIcon( _fileActions.saveAll.Enabled ? 1 Else 0 )
+		Endif
 		
 		
 		App.Idle+=OnAppIdle
 		App.Idle+=OnAppIdle
 		
 		
@@ -1791,6 +1957,44 @@ End
 
 
 Private
 Private
 
 
+Enum FullscreenState
+	None=0
+	Window=1
+	Editor=2
+End
+
+
+Class FullscreenHelper
+	
+	Field state:FullscreenState
+	Field frame:Recti
+	Field storedContentView:View
+	Field storedTabIndex:Int
+	Field editorContainer:DockingView
+	Field statusContainer:DockingView
+	Field titleLabel:Label
+	
+	Method New()
+		
+		editorContainer=New DockingView
+		
+		titleLabel=New Label
+		titleLabel.Gravity=New Vec2f( .5,0 )
+		titleLabel.Layout="float"
+		editorContainer.AddView( titleLabel,"top" )
+		
+		statusContainer=New DockingView
+		editorContainer.AddView( statusContainer,"bottom" )
+	End
+	
+	Method UpdateTitle()
+		
+		titleLabel.Text=MainWindow.DocsManager.CurrentDocumentLabel
+	End
+	
+End
+
+
 Class DraggableTabs
 Class DraggableTabs
 	
 	
 	Const Edges:=New String[]( "left","right","bottom" )
 	Const Edges:=New String[]( "left","right","bottom" )
@@ -1801,7 +2005,7 @@ Class DraggableTabs
 	
 	
 	Method New()
 	Method New()
 		
 		
-		sizes["left"]="300"
+		sizes["left"]="250"
 		sizes["right"]="300"
 		sizes["right"]="300"
 		sizes["bottom"]="250"
 		sizes["bottom"]="250"
 		
 		

+ 1 - 1
Plugin.monkey2

@@ -53,7 +53,7 @@ Class PluginDependsOnFileType Extends Plugin Implements IDependsOnFileType
 	End
 	End
 	
 	
 	Method New()
 	Method New()
-		_types = New String[]("*")
+		_types=New String[]( "*" )
 	End
 	End
 	
 	
 	Method GetFileTypes:String[]() Virtual
 	Method GetFileTypes:String[]() Virtual

+ 3 - 0
Prefs.monkey2

@@ -38,6 +38,7 @@ Class PrefsInstance
 	Field EditorAutoIndent:=True
 	Field EditorAutoIndent:=True
 	Field EditorAutoPairs:=True
 	Field EditorAutoPairs:=True
 	Field EditorSurroundSelection:=True
 	Field EditorSurroundSelection:=True
+	Field EditorShowParamsHint:=True
 	'
 	'
 	Field SourceSortByType:=True
 	Field SourceSortByType:=True
 	Field SourceShowInherited:=False
 	Field SourceShowInherited:=False
@@ -106,6 +107,7 @@ Class PrefsInstance
 			EditorAutoIndent=Json_GetBool( j2,"autoIndent",EditorAutoIndent )
 			EditorAutoIndent=Json_GetBool( j2,"autoIndent",EditorAutoIndent )
 			EditorAutoPairs=Json_GetBool( j2,"autoPairs",EditorAutoPairs )
 			EditorAutoPairs=Json_GetBool( j2,"autoPairs",EditorAutoPairs )
 			EditorSurroundSelection=Json_GetBool( j2,"surroundSelection",EditorSurroundSelection )
 			EditorSurroundSelection=Json_GetBool( j2,"surroundSelection",EditorSurroundSelection )
+			EditorShowParamsHint=Json_GetBool( j2,"showParamsHint",EditorShowParamsHint )
 			
 			
 		Endif
 		Endif
 		
 		
@@ -165,6 +167,7 @@ Class PrefsInstance
 		j["autoIndent"]=New JsonBool( EditorAutoIndent )
 		j["autoIndent"]=New JsonBool( EditorAutoIndent )
 		j["autoPairs"]=New JsonBool( EditorAutoPairs )
 		j["autoPairs"]=New JsonBool( EditorAutoPairs )
 		j["surroundSelection"]=New JsonBool( EditorSurroundSelection )
 		j["surroundSelection"]=New JsonBool( EditorSurroundSelection )
+		j["showParamsHint"]=New JsonBool( EditorShowParamsHint )
 		
 		
 		j=New JsonObject
 		j=New JsonObject
 		json["source"]=j
 		json["source"]=j

+ 15 - 11
Ted2.monkey2

@@ -7,7 +7,11 @@
 '
 '
 'windres resource.rc resource.o
 'windres resource.rc resource.o
 
 
+#If __ARCH__="x86"
 #Import "logo/resource.o"
 #Import "logo/resource.o"
+#Elseif __ARCH__="x64"
+#Import "logo/resource_x64.o"
+#Endif
 
 
 #Endif
 #Endif
 
 
@@ -19,6 +23,7 @@
 #Import "<mojo>"
 #Import "<mojo>"
 #Import "<mojox>"
 #Import "<mojox>"
 #Import "<tinyxml2>"
 #Import "<tinyxml2>"
+#Import "<sdl2>"
 
 
 #Import "action/FileActions"
 #Import "action/FileActions"
 #Import "action/EditActions"
 #Import "action/EditActions"
@@ -26,6 +31,7 @@
 #Import "action/HelpActions"
 #Import "action/HelpActions"
 #Import "action/FindActions"
 #Import "action/FindActions"
 #Import "action/ViewActions"
 #Import "action/ViewActions"
+#Import "action/WindowActions"
 
 
 #Import "dialog/FindDialog"
 #Import "dialog/FindDialog"
 #Import "dialog/PrefsDialog"
 #Import "dialog/PrefsDialog"
@@ -35,7 +41,6 @@
 #Import "dialog/FindInFilesDialog"
 #Import "dialog/FindInFilesDialog"
 #Import "dialog/UpdateModulesDialog"
 #Import "dialog/UpdateModulesDialog"
 #Import "dialog/GenerateClassDialog"
 #Import "dialog/GenerateClassDialog"
-#Import "dialog/LiveTemplateDialog"
 
 
 #Import "document/DocumentManager"
 #Import "document/DocumentManager"
 #Import "document/Ted2Document"
 #Import "document/Ted2Document"
@@ -84,7 +89,6 @@
 #Import "view/AutocompleteView"
 #Import "view/AutocompleteView"
 #Import "view/TreeViewExt"
 #Import "view/TreeViewExt"
 #Import "view/CodeTreeView"
 #Import "view/CodeTreeView"
-'#Import "view/FileBrowserExt"
 #Import "view/CodeGutterView"
 #Import "view/CodeGutterView"
 #Import "view/ToolBarViewExt"
 #Import "view/ToolBarViewExt"
 #Import "view/HintView"
 #Import "view/HintView"
@@ -109,14 +113,15 @@
 #Import "view/FindReplaceView"
 #Import "view/FindReplaceView"
 #Import "view/ViewExtensions"
 #Import "view/ViewExtensions"
 #Import "view/DockingViewExt"
 #Import "view/DockingViewExt"
+#Import "view/DraggableViewListener"
 
 
+#Import "Tree"
 #Import "Tuple"
 #Import "Tuple"
 #Import "Plugin"
 #Import "Plugin"
 #Import "ThemeImages"
 #Import "ThemeImages"
 #Import "Prefs"
 #Import "Prefs"
 #Import "ProcessReader"
 #Import "ProcessReader"
 #Import "LiveTemplates"
 #Import "LiveTemplates"
-#Import "DraggableTabs"
 #Import "MainWindow"
 #Import "MainWindow"
 
 
 
 
@@ -126,11 +131,11 @@ Using std..
 Using mojo..
 Using mojo..
 Using mojox..
 Using mojox..
 Using tinyxml2..
 Using tinyxml2..
-
+Using sdl2..
 
 
 Const MONKEY2_DOMAIN:="http://monkeycoder.co.nz"
 Const MONKEY2_DOMAIN:="http://monkeycoder.co.nz"
 
 
-Global AppTitle:="Ted2Go v2.7"
+Global AppTitle:="Ted2Go v2.8"
 
 
 
 
 Function Main()
 Function Main()
@@ -159,18 +164,17 @@ Function Main()
 	
 	
 	'initial theme
 	'initial theme
 	'
 	'
-	If Not jobj.Contains( "theme" ) jobj["theme"]=New JsonString( "theme-prime-blue" )
+	If Not jobj.Contains( "theme" ) jobj["theme"]=New JsonString( "theme-warm" )
 
 
 	If Not jobj.Contains( "themeScale" ) jobj["themeScale"]=New JsonNumber( 1 )
 	If Not jobj.Contains( "themeScale" ) jobj["themeScale"]=New JsonNumber( 1 )
 	
 	
-	Local config:=New StringMap<String>
+	SetConfig( "MOJO_INITIAL_THEME",jobj.GetString( "theme" ) )
 	
 	
-	config["initialTheme"]=jobj.GetString( "theme" )
-	config["initialThemeScale"]=jobj.GetNumber( "themeScale" )
+	SetConfig( "MOJO_INITIAL_THEME_SCALE",jobj.GetString( "themeScale" ) )
 	
 	
 	'start the app!
 	'start the app!
 	'
 	'
-	New AppInstance( config )
+	New AppInstance
 	
 	
 	'initial window state
 	'initial window state
 	'
 	'
@@ -181,7 +185,7 @@ Function Main()
 	If jobj.Contains( "windowRect" ) 
 	If jobj.Contains( "windowRect" ) 
 		rect=ToRecti( jobj["windowRect"] )
 		rect=ToRecti( jobj["windowRect"] )
 	Else
 	Else
-		Local w:=Min( 1380,App.DesktopSize.x-40 )
+		Local w:=Min( 1480,App.DesktopSize.x-40 )
 		Local h:=Min( 970,App.DesktopSize.y-64 )
 		Local h:=Min( 970,App.DesktopSize.y-64 )
 		rect=New Recti( 0,0,w,h )
 		rect=New Recti( 0,0,w,h )
 		flags|=WindowFlags.Center
 		flags|=WindowFlags.Center

+ 94 - 0
Tree.monkey2

@@ -0,0 +1,94 @@
+
+Namespace ted2go
+
+
+Class Tree
+	
+	Class Node
+		
+		Field Text:String
+		Field UserData:Variant
+		
+		Property Children:Stack<Node>()
+			Return _children
+		End
+		
+		Property NumChildren:Int()
+			Return Children?.Length
+		End
+		
+		Property Parent:Node()
+			Return _parent
+		Setter( value:Node )
+			If _parent Then _parent-=Self
+			_parent=value
+			If _parent Then _parent+=Self
+		End
+		
+		Property ParentsHierarchy:Stack<Node>()
+			
+			Local result:=New Stack<Node>
+			Local p:=_parent
+			While p
+				result.Insert( 0,p )
+				p=p.Parent
+			Wend
+			Return result
+		End
+		
+		Method New( text:String,parent:Node=Null,userData:Variant=Null )
+			
+			Text=text
+			Parent=parent
+			UserData=userData
+		End
+		
+		Method GetUserData<T>:T()
+			
+			Return UserData ? Cast<T>( UserData ) Else Null
+		End
+		
+		Operator +=( child:Node )
+			
+			If Not _children Then _children=New Stack<Node>
+			_children.Add( child )
+		End
+		
+		Operator -=( child:Node )
+			
+			If Not _children Return
+			_children.Remove( child )
+		End
+		
+		Method Clear()
+			
+			_children?.Clear()
+		End
+		
+		
+		Private
+		
+		Field _parent:Node
+		Field _children:Stack<Node>
+		
+	End
+	
+	Method New()
+		
+		_root=New Node( "" )
+	End
+	
+	Property RootNode:Node()
+		Return _root
+	End
+	
+	Method Clear()
+	
+		_root.Clear()
+	End
+	
+	Private
+	
+	Field _root:Node
+	
+End

+ 67 - 16
action/BuildActions.monkey2

@@ -26,7 +26,11 @@ End
 
 
 Interface IModuleBuilder
 Interface IModuleBuilder
 	
 	
-	Method BuildModules:Bool( clean:Bool,modules:String="",configs:String="debug release" )
+	' cleanState: 
+	' -1: don't clean
+	' 0: use previous
+	' 1: clean
+	Method BuildModules:Bool( modules:String="",configs:String="",cleanState:Int=0 )
 	
 	
 End
 End
 
 
@@ -149,6 +153,9 @@ Class BuildActions Implements IModuleBuilder
 		_iosTarget=New CheckButton( "iOS",,group )
 		_iosTarget=New CheckButton( "iOS",,group )
 		_iosTarget.Layout="fill-x"
 		_iosTarget.Layout="fill-x"
 		
 		
+		_verboseMode=New CheckButton( "Verbose")
+		_verboseMode.Layout="fill-x"
+		
 		targetMenu=New MenuExt( "Build target" )
 		targetMenu=New MenuExt( "Build target" )
 		targetMenu.AddView( _debugConfig )
 		targetMenu.AddView( _debugConfig )
 		targetMenu.AddView( _releaseConfig )
 		targetMenu.AddView( _releaseConfig )
@@ -159,6 +166,8 @@ Class BuildActions Implements IModuleBuilder
 		targetMenu.AddView( _iosTarget )
 		targetMenu.AddView( _iosTarget )
 		targetMenu.AddSeparator()
 		targetMenu.AddSeparator()
 		targetMenu.AddAction( buildSettings )
 		targetMenu.AddAction( buildSettings )
+		targetMenu.AddSeparator()
+		targetMenu.AddView( _verboseMode )
 		
 		
 		'check valid targets...WIP...
 		'check valid targets...WIP...
 		
 		
@@ -204,6 +213,11 @@ Class BuildActions Implements IModuleBuilder
 		Return _locked
 		Return _locked
 	End
 	End
 	
 	
+	Property Verbosed:Bool()
+	
+		Return _verboseMode.Checked
+	End
+	
 	Method LockBuildFile()
 	Method LockBuildFile()
 		
 		
 		Local doc:=Cast<CodeDocument>( _docs.CurrentDocument )
 		Local doc:=Cast<CodeDocument>( _docs.CurrentDocument )
@@ -217,6 +231,8 @@ Class BuildActions Implements IModuleBuilder
 		jobj["buildConfig"]=New JsonString( _buildConfig )
 		jobj["buildConfig"]=New JsonString( _buildConfig )
 		
 		
 		jobj["buildTarget"]=New JsonString( _buildTarget )
 		jobj["buildTarget"]=New JsonString( _buildTarget )
+		
+		jobj["buildVerbose"]=New JsonBool( _verboseMode.Checked )
 	End
 	End
 		
 		
 	Method LoadState( jobj:JsonObject )
 	Method LoadState( jobj:JsonObject )
@@ -239,12 +255,12 @@ Class BuildActions Implements IModuleBuilder
 		Endif
 		Endif
 		
 		
 		If jobj.Contains( "buildTarget" )
 		If jobj.Contains( "buildTarget" )
-					
+			
 			local target:=jobj["buildTarget"].ToString()
 			local target:=jobj["buildTarget"].ToString()
-
-			If _validTargets.Contains( target )
 			
 			
-				 _buildTarget=target
+			If _validTargets.Contains( target )
+				
+				_buildTarget=target
 				
 				
 				Select _buildTarget
 				Select _buildTarget
 				Case "desktop"
 				Case "desktop"
@@ -261,6 +277,10 @@ Class BuildActions Implements IModuleBuilder
 			
 			
 		Endif
 		Endif
 		
 		
+		If jobj.Contains( "buildVerbose" )
+			_verboseMode.Checked=jobj.GetBool( "buildVerbose" )
+		Endif
+		
 	End
 	End
 	
 	
 	Method Update()
 	Method Update()
@@ -279,27 +299,48 @@ Class BuildActions Implements IModuleBuilder
 		rebuildHelp.Enabled=idle
 		rebuildHelp.Enabled=idle
 		moduleManager.Enabled=idle
 		moduleManager.Enabled=idle
 	End
 	End
-
-	Method BuildModules:Bool( clean:Bool,modules:String="",configs:String="debug release" )
 	
 	
-		Local dialog:=New UpdateModulesDialog( _validTargets,modules,configs,clean )
+	Method BuildModules:Bool( modules:String="",configs:String="",cleanState:Int=0 )
+		
+		If Not modules Then modules=_storedModules
+		
+		If Not configs
+			configs=_storedConfigs
+			If Not configs Then configs="debug release"
+		Endif
+		
+		Local clean:Bool
+		If cleanState=0
+			clean=_storedClean
+		Else
+			clean=(cleanState=1)
+		Endif
+		
+		Local selTargets:=(_storedTargets ?Else "desktop")
+		
+		Local dialog:=New UpdateModulesDialog( _validTargets,selTargets,modules,configs,clean )
 		dialog.Title="Update / Rebuild modules"
 		dialog.Title="Update / Rebuild modules"
 		
 		
 		Local ok:=dialog.ShowModal()
 		Local ok:=dialog.ShowModal()
 		If Not ok Return False
 		If Not ok Return False
 		
 		
-		Local result:=True
+		Local result:Bool
 		
 		
 		Local targets:=dialog.SelectedTargets
 		Local targets:=dialog.SelectedTargets
 		modules=dialog.SelectedModules
 		modules=dialog.SelectedModules
-		
-		clean=dialog.NeedClean
 		configs=dialog.SelectedConfigs
 		configs=dialog.SelectedConfigs
+		clean=dialog.NeedClean
+		
+		' store
+		_storedTargets=targets.Join( " " )
+		_storedModules=modules
+		_storedConfigs=configs
+		_storedClean=clean
 		
 		
 		Local time:=Millisecs()
 		Local time:=Millisecs()
 		
 		
 		For Local target:=Eachin targets
 		For Local target:=Eachin targets
-			result=BuildModules( clean,target,modules,configs )
+			result=BuildModules( target,modules,configs,clean )
 			If result=False Exit
 			If result=False Exit
 		Next
 		Next
 		
 		
@@ -318,7 +359,7 @@ Class BuildActions Implements IModuleBuilder
 	
 	
 	Method GotoError( err:BuildError )
 	Method GotoError( err:BuildError )
 	
 	
-		Local doc:=Cast<CodeDocument>( _docs.OpenDocument( err.path,True ) )
+		Local doc:=Cast<CodeDocument>( _docs.OpenDocument( GetCaseSensitivePath( err.path ),True ) )
 		If Not doc Return
 		If Not doc Return
 	
 	
 		Local tv := doc.CodeView
 		Local tv := doc.CodeView
@@ -349,10 +390,15 @@ Class BuildActions Implements IModuleBuilder
 	Field _emscriptenTarget:CheckButton
 	Field _emscriptenTarget:CheckButton
 	Field _androidTarget:CheckButton
 	Field _androidTarget:CheckButton
 	Field _iosTarget:CheckButton
 	Field _iosTarget:CheckButton
+	Field _verboseMode:CheckButton
 	
 	
 	Field _validTargets:StringStack
 	Field _validTargets:StringStack
 	Field _timing:Long
 	Field _timing:Long
 	
 	
+	Field _storedModules:String
+	Field _storedConfigs:String
+	Field _storedTargets:String
+	Field _storedClean:Bool
 	
 	
 	Method BuildDoc:CodeDocument()
 	Method BuildDoc:CodeDocument()
 		
 		
@@ -434,7 +480,7 @@ Class BuildActions Implements IModuleBuilder
 						Local msg:=stdout.Slice( i+12 )
 						Local msg:=stdout.Slice( i+12 )
 						
 						
 						Local err:=New BuildError( path,line,msg )
 						Local err:=New BuildError( path,line,msg )
-						Local doc:=Cast<CodeDocument>( _docs.OpenDocument( path,False ) )
+						Local doc:=Cast<CodeDocument>( _docs.OpenDocument( GetCaseSensitivePath( path ),False ) )
 						
 						
 						If doc
 						If doc
 							doc.AddError( err )
 							doc.AddError( err )
@@ -477,7 +523,7 @@ Class BuildActions Implements IModuleBuilder
 		Return _console.ExitCode=0
 		Return _console.ExitCode=0
 	End
 	End
 
 
-	Method BuildModules:Bool( clean:Bool,target:String,modules:String,configs:String="debug release" )
+	Method BuildModules:Bool( target:String,modules:String,configs:String,clean:Bool )
 		
 		
 		PreBuildModules()
 		PreBuildModules()
 		
 		
@@ -490,6 +536,7 @@ Class BuildActions Implements IModuleBuilder
 			
 			
 			Local cmd:=MainWindow.Mx2ccPath+" makemods -target="+target
 			Local cmd:=MainWindow.Mx2ccPath+" makemods -target="+target
 			If clean cmd+=" -clean"
 			If clean cmd+=" -clean"
+			If Verbosed cmd+=" -verbose"
 			cmd+=" -config="+cfg
 			cmd+=" -config="+cfg
 			If modules Then cmd+=" "+modules
 			If modules Then cmd+=" "+modules
 			
 			
@@ -523,6 +570,7 @@ Class BuildActions Implements IModuleBuilder
 		If run Then action="build"
 		If run Then action="build"
 
 
 		Local cmd:=MainWindow.Mx2ccPath+" makeapp -"+action+" "+opts
 		Local cmd:=MainWindow.Mx2ccPath+" makeapp -"+action+" "+opts
+		If Verbosed cmd+=" -verbose"
 		cmd+=" -config="+config
 		cmd+=" -config="+config
 		cmd+=" -target="+target
 		cmd+=" -target="+target
 		cmd+=" ~q"+buildDoc.Path+"~q"
 		cmd+=" ~q"+buildDoc.Path+"~q"
@@ -623,6 +671,8 @@ Class BuildActions Implements IModuleBuilder
 		
 		
 		_locked=doc
 		_locked=doc
 		SetLockedState( _locked,True )
 		SetLockedState( _locked,True )
+		
+		
 	End
 	End
 	
 	
 	Method SetLockedState( doc:CodeDocument,locked:Bool )
 	Method SetLockedState( doc:CodeDocument,locked:Bool )
@@ -630,6 +680,7 @@ Class BuildActions Implements IModuleBuilder
 		doc.State=locked ? "+" Else ""
 		doc.State=locked ? "+" Else ""
 		Local tab:=_docs.FindTab( doc.View )
 		Local tab:=_docs.FindTab( doc.View )
 		If tab Then tab.SetLockedState( locked )
 		If tab Then tab.SetLockedState( locked )
+		_docs.CurrentDocumentChanged()
 	End
 	End
 	
 	
 	Method OnBuildFileSettings()
 	Method OnBuildFileSettings()
@@ -644,7 +695,7 @@ Class BuildActions Implements IModuleBuilder
 		
 		
 		If _console.Running Return
 		If _console.Running Return
 	
 	
-		BuildModules( False )
+		BuildModules()
 	End
 	End
 	
 	
 	Method OnModuleManager()
 	Method OnModuleManager()

+ 106 - 1
action/EditActions.monkey2

@@ -11,7 +11,15 @@ Class EditActions
 	Field paste:Action
 	Field paste:Action
 	Field selectAll:Action
 	Field selectAll:Action
 	Field wordWrap:Action
 	Field wordWrap:Action
-	
+	' Edit -- Text
+	Field textDeleteWordForward:Action
+	Field textDeleteWordBackward:Action
+	Field textDeleteLine:Action
+	Field textDeleteToEnd:Action
+	Field textDeleteToBegin:Action
+	Field textLowercase:Action
+	Field textUppercase:Action
+	Field textSwapCase:Action
 	
 	
 	Method New( docs:DocumentManager )
 	Method New( docs:DocumentManager )
 	
 	
@@ -57,6 +65,58 @@ Class EditActions
 		wordWrap.HotKey=Key.Z
 		wordWrap.HotKey=Key.Z
 		wordWrap.HotKeyModifiers=Modifier.Alt
 		wordWrap.HotKeyModifiers=Modifier.Alt
 		
 		
+		textDeleteLine=New Action( "Delete line" )
+		textDeleteLine.Triggered=OnDeleteLine
+		#If __TARGET__="macos"
+		textDeleteLine.HotKey=Key.K
+		textDeleteLine.HotKeyModifiers=Modifier.Control|Modifier.Shift
+		#Else
+		textDeleteLine.HotKey=Key.E
+		textDeleteLine.HotKeyModifiers=Modifier.Control
+		#Endif
+		
+		textDeleteWordForward=New Action( "Delete word forward" )
+		textDeleteWordForward.Triggered=OnDeleteWordForward
+		textDeleteWordForward.HotKey=Key.KeyDelete
+		textDeleteWordForward.HotKeyModifiers=Modifier.Control
+		
+		textDeleteWordBackward=New Action( "Delete word backward" )
+		textDeleteWordBackward.Triggered=OnDeleteWordBackward
+		textDeleteWordBackward.HotKey=Key.Backspace
+		textDeleteWordBackward.HotKeyModifiers=Modifier.Control
+		
+		textDeleteToBegin=New Action( "Delete to beginning" )
+		textDeleteToBegin.Triggered=OnDeleteToBegin
+		textDeleteToBegin.HotKey=Key.Backspace
+		#If __TARGET__="macos"
+		textDeleteToBegin.HotKeyModifiers=Modifier.Menu
+		#Else
+		textDeleteToBegin.HotKeyModifiers=Modifier.Menu|Modifier.Shift
+		#Endif
+		
+		textDeleteToEnd=New Action( "Delete to end" )
+		textDeleteToEnd.Triggered=OnDeleteToEnd
+		#If __TARGET__="macos"
+		textDeleteToEnd.HotKey=Key.K
+		textDeleteToEnd.HotKeyModifiers=Modifier.Control
+		#Else
+		textDeleteToEnd.HotKey=Key.KeyDelete
+		textDeleteToEnd.HotKeyModifiers=Modifier.Control|Modifier.Shift
+		#Endif
+		
+		textLowercase=New Action( "lowercace" )
+		textLowercase.Triggered=OnLowercase
+		textLowercase.HotKey=Key.L
+		textLowercase.HotKeyModifiers=Modifier.Control|Modifier.Shift
+		
+		textUppercase=New Action( "UPPERCASE" )
+		textUppercase.Triggered=OnUppercase
+		textUppercase.HotKey=Key.U
+		textUppercase.HotKeyModifiers=Modifier.Control|Modifier.Shift
+		
+		textSwapCase=New Action( "Swap case" )
+		textSwapCase.Triggered=OnSwapCase
+		
 	End
 	End
 	
 	
 	Method Update()
 	Method Update()
@@ -75,6 +135,51 @@ Class EditActions
 	
 	
 	Field _docs:DocumentManager
 	Field _docs:DocumentManager
 	
 	
+	Property CurrentCodeDocument:CodeTextView()
+		
+		Return Cast<CodeTextView>( App.KeyView )
+	End
+	
+	Method OnDeleteLine()
+		
+		CurrentCodeDocument?.DeleteLineAtCursor()
+	End
+	
+	Method OnDeleteWordForward()
+		
+		CurrentCodeDocument?.DeleteWordForward()
+	End
+	
+	Method OnDeleteWordBackward()
+		
+		CurrentCodeDocument?.DeleteWordBackward()
+	End
+	
+	Method OnDeleteToBegin()
+		
+		CurrentCodeDocument?.DeleteToBegin()
+	End
+	
+	Method OnDeleteToEnd()
+	
+		CurrentCodeDocument?.DeleteToEnd()
+	End
+	
+	Method OnLowercase()
+	
+		CurrentCodeDocument?.LowercaseSelection()
+	End
+	
+	Method OnUppercase()
+	
+		CurrentCodeDocument?.UppercaseSelection()
+	End
+	
+	Method OnSwapCase()
+		
+		CurrentCodeDocument?.SwapCaseSelection()
+	End
+	
 	Method OnUndo()
 	Method OnUndo()
 
 
 		Local tv:=Cast<TextView>( App.KeyView )
 		Local tv:=Cast<TextView>( App.KeyView )

+ 1 - 1
action/FileActions.monkey2

@@ -144,7 +144,7 @@ Class FileActions
 		Local name:=StripDir( doc.Path )
 		Local name:=StripDir( doc.Path )
 		Local path:=MainWindow.RequestFile( "Save As",name,True )
 		Local path:=MainWindow.RequestFile( "Save As",name,True )
 		If Not path Return Null
 		If Not path Return Null
-				
+		
 		If Not ExtractExt( path ) path+=ExtractExt( doc.Path )
 		If Not ExtractExt( path ) path+=ExtractExt( doc.Path )
 		
 		
 		Return _docs.RenameDocument( doc,path )
 		Return _docs.RenameDocument( doc,path )

+ 36 - 32
action/HelpActions.monkey2

@@ -13,8 +13,9 @@ Class HelpActions
 	Field makeBetter:Action
 	Field makeBetter:Action
 	Field mx2homepage:Action
 	Field mx2homepage:Action
 	Field bananas:Action
 	Field bananas:Action
+	Field joinCommunity:Action
+	
 	
 	
-
 	Method New()
 	Method New()
 	
 	
 		quickHelp=New Action( "Quick help" )
 		quickHelp=New Action( "Quick help" )
@@ -22,7 +23,7 @@ Class HelpActions
 		quickHelp.HotKey=Key.F1
 		quickHelp.HotKey=Key.F1
 		
 		
 		onlineHelp=New Action( "Online help" )
 		onlineHelp=New Action( "Online help" )
-		onlineHelp.Triggered=lambda()
+		onlineHelp.Triggered=Lambda()
 		
 		
 			OpenUrl( MONKEY2_DOMAIN+"/monkey2-docs/" )
 			OpenUrl( MONKEY2_DOMAIN+"/monkey2-docs/" )
 		End
 		End
@@ -38,58 +39,44 @@ Class HelpActions
 		
 		
 			GotoUploadModulesPage()
 			GotoUploadModulesPage()
 		End
 		End
-
+		
 		about=New Action( "About monkey2" )
 		about=New Action( "About monkey2" )
 		about.Triggered=Lambda()
 		about.Triggered=Lambda()
 		
 		
-			Local htmlView:=New HtmlView
-			htmlView.Go( MainWindow.AboutPagePath )
-	
-			Local dialog:=New Dialog( "About monkey2" )
-			dialog.ContentView=htmlView
-
-			dialog.MinSize=New Vec2i( 640,600 )
-
-			dialog.AddAction( "Okay!" ).Triggered=dialog.Close
-			
-			dialog.Open()
+			OnAboutDialog( "About monkey2",MainWindow.AboutPagePath )
 		End
 		End
-
+		
 		aboutTed2go=New Action( "About ted2go" )
 		aboutTed2go=New Action( "About ted2go" )
 		aboutTed2go.Triggered=Lambda()
 		aboutTed2go.Triggered=Lambda()
 		
 		
-			Local htmlView:=New HtmlView
-			htmlView.Go( "asset::ted2/aboutTed2Go.html" )
-	
-			Local dialog:=New Dialog( "About ted2go" )
-			dialog.ContentView=htmlView
-
-			dialog.MinSize=New Vec2i( 640,600 )
-
-			dialog.AddAction( "Okay!" ).Triggered=dialog.Close
-			
-			dialog.Open()
+			OnAboutDialog( "About ted2go","asset::ted2/aboutTed2Go.html" )
 		End
 		End
 		
 		
-		makeBetter=New Action( "Make this app better! (paypal)" )
+		makeBetter=New Action( "Make this app better! (PayPal)" )
 		makeBetter.Triggered=Lambda()
 		makeBetter.Triggered=Lambda()
 		
 		
 			OpenUrl( "https://paypal.me/engor/10" )
 			OpenUrl( "https://paypal.me/engor/10" )
 		End
 		End
 		
 		
 		mx2homepage=New Action( "Monkey2 homepage" )
 		mx2homepage=New Action( "Monkey2 homepage" )
-		mx2homepage.Triggered=lambda()
+		mx2homepage.Triggered=Lambda()
 		
 		
 			OpenUrl( MONKEY2_DOMAIN )
 			OpenUrl( MONKEY2_DOMAIN )
 		End
 		End
 		
 		
 		bananas=New Action( "Bananas showcase" )
 		bananas=New Action( "Bananas showcase" )
-		bananas.Triggered=lambda()
-		
+		bananas.Triggered=Lambda()
+			
 			MainWindow.ShowBananasShowcase()
 			MainWindow.ShowBananasShowcase()
 		End
 		End
+		
+		joinCommunity=New Action( "Join the community (Discord)" )
+		joinCommunity.Triggered=Lambda()
+		
+			OpenUrl( "https://discord.gg/A2C6AMM" )
+		End
+		
 	End
 	End
-
 	
 	
 	Private
 	Private
 	
 	
@@ -97,7 +84,24 @@ Class HelpActions
 	
 	
 	Method OnQuickHelp()
 	Method OnQuickHelp()
 	
 	
-		MainWindow.ShowQuickHelp()
+		MainWindow.ShowHelp()
+	End
+	
+	Method OnAboutDialog( title:String,url:String,okButton:String="Okay!" )
+	
+		Local htmlView:=New HtmlView
+		htmlView.Go( url )
+	
+		Local dialog:=New DialogExt( title,htmlView )
+	
+		dialog.MinSize=New Vec2i( 640,600 )
+	
+		dialog.AddAction( okButton ).Triggered=dialog.Hide
+	
+		dialog.FadeEnabled=True ' faded
+	
+		dialog.Show()
+	
 	End
 	End
 	
 	
 End
 End

+ 3 - 3
action/ViewActions.monkey2

@@ -15,12 +15,12 @@ Class ViewActions
 		
 		
 		_docs=docs
 		_docs=docs
 		
 		
-		goBack=New Action( "Go back" )
+		goBack=New Action( "Jump back" )
 		goBack.Triggered=OnGoBack
 		goBack.Triggered=OnGoBack
 		goBack.HotKey=Key.Left
 		goBack.HotKey=Key.Left
 		goBack.HotKeyModifiers=Modifier.Alt|Modifier.Menu
 		goBack.HotKeyModifiers=Modifier.Alt|Modifier.Menu
 		
 		
-		goForward=New Action( "Go forward" )
+		goForward=New Action( "Jump forward" )
 		goForward.Triggered=OnGoForward
 		goForward.Triggered=OnGoForward
 		goForward.HotKey=Key.Right
 		goForward.HotKey=Key.Right
 		goForward.HotKeyModifiers=Modifier.Alt|Modifier.Menu
 		goForward.HotKeyModifiers=Modifier.Alt|Modifier.Menu
@@ -48,7 +48,7 @@ Class ViewActions
 		gotoLine.HotKey=Key.G
 		gotoLine.HotKey=Key.G
 		gotoLine.HotKeyModifiers=Modifier.Menu
 		gotoLine.HotKeyModifiers=Modifier.Menu
 		
 		
-		gotoDeclaration=New Action( "Goto declaration" )
+		gotoDeclaration=New Action( "Goto definition" )
 		gotoDeclaration.Triggered=OnGotoDeclaration
 		gotoDeclaration.Triggered=OnGotoDeclaration
 		gotoDeclaration.HotKey=Key.F12
 		gotoDeclaration.HotKey=Key.F12
 	End
 	End

+ 76 - 0
action/WindowActions.monkey2

@@ -0,0 +1,76 @@
+
+Namespace ted2go
+
+
+Class WindowActions
+
+	Field nextTab:Action
+	Field prevTab:Action
+	Field zoomIn:Action
+	Field zoomOut:Action
+	Field zoomDefault:Action
+	Field themes:Action
+	Field fullscreenWindow:Action
+	Field fullscreenEditor:Action
+	
+	Method New( docs:DocumentManager )
+		
+		nextTab=docs.nextDocument
+		prevTab=docs.prevDocument
+		
+		fullscreenWindow=New Action( "Fullscreen window" )
+#If __TARGET__="macos"
+		fullscreenWindow.HotKey=Key.F
+		fullscreenWindow.HotKeyModifiers=Modifier.Menu|Modifier.Control
+#Else
+		fullscreenWindow.HotKey=Key.F11
+#Endif
+		fullscreenWindow.Triggered=Lambda()
+			MainWindow.SwapFullscreenWindow()
+		End
+		
+		fullscreenEditor=New Action( "Fullscreen editor" )
+#If __TARGET__="macos"
+		fullscreenEditor.HotKey=Key.F
+		fullscreenEditor.HotKeyModifiers=Modifier.Menu|Modifier.Control|Modifier.Shift
+#Else
+		fullscreenEditor.HotKey=Key.F11
+		fullscreenEditor.HotKeyModifiers=Modifier.Shift
+#Endif
+		fullscreenEditor.Triggered=Lambda()
+			MainWindow.SwapFullscreenEditor()
+		End
+		
+		zoomIn=New Action( "Zoom in" )
+		zoomIn.HotKey=Key.KeypadPlus
+		zoomIn.HotKeyModifiers=Modifier.Control
+		zoomIn.Triggered=Lambda()
+		
+			Local sc:=App.Theme.Scale.x
+			If sc>=4 Return
+			sc+=.125
+			App.Theme.Scale=New Vec2f( sc )
+		End
+		
+		zoomOut=New Action( "Zoom out" )
+		zoomOut.HotKey=Key.KeypadMinus
+		zoomOut.HotKeyModifiers=Modifier.Control
+		zoomOut.Triggered=Lambda()
+		
+			Local sc:=App.Theme.Scale.x
+			If sc<=.5 Return
+			sc-=.125
+			App.Theme.Scale=New Vec2f( sc )
+		End
+		
+		zoomDefault=New Action( "Reset zoom" )
+		zoomDefault.HotKey=Key.Keypad0
+		zoomDefault.HotKeyModifiers=Modifier.Control
+		zoomDefault.Triggered=Lambda()
+		
+			App.Theme.Scale=New Vec2f( 1 )
+		End
+		
+	End
+	
+End

+ 1 - 1
assets/aboutTed2Go.html

@@ -124,7 +124,7 @@ ToolBar icons were taken from <a href="https://icons8.com/icon/new-icons/win8">i
 
 
 <h3>Special thanks</h3>
 <h3>Special thanks</h3>
 
 
-<p>Matthew Bowen, Mark Mcvittie, Simon Armstrong, Rudy van Etten, Hezkore, Sal Gunduz, Peter Scheutz, Matthieu Chemin, David Maziarka, Leonardo Teixeira, Jesus Perez, Mark Sibly, Philipp Moeller, Lee Wade.</p>
+<p>Rajasekaran Senthil Kumaran, abakobo, Peter Rigby, Dmitry Fadeev, James Boyd, Sam Fisher, Matthew Bowen, Mark Mcvittie, Simon Armstrong, Rudy van Etten, Hezkore, Sal Gunduz, Peter Scheutz, Matthieu Chemin, David Maziarka, Leonardo Teixeira, Jesus Perez, Mark Sibly, Philipp Moeller, Lee Wade.</p>
 
 
 </body>
 </body>
 
 

+ 5 - 6
assets/newfiles/Simple_Mojo3d_App.monkey2

@@ -1,13 +1,9 @@
-Namespace myapp
+Namespace myapp3d
 
 
 #Import "<std>"
 #Import "<std>"
 #Import "<mojo>"
 #Import "<mojo>"
 #Import "<mojo3d>"
 #Import "<mojo3d>"
 
 
-#Import "assets/"
-
-#Import "util"
-
 Using std..
 Using std..
 Using mojo..
 Using mojo..
 Using mojo3d..
 Using mojo3d..
@@ -42,6 +38,7 @@ Class MyWindow Extends Window
 		_camera.Near=.1
 		_camera.Near=.1
 		_camera.Far=100
 		_camera.Far=100
 		_camera.Move( 0,10,-10 )
 		_camera.Move( 0,10,-10 )
+		_camera.AddComponent<FlyBehaviour>()
 		
 		
 		'create light
 		'create light
 		'
 		'
@@ -61,11 +58,13 @@ Class MyWindow Extends Window
 	
 	
 		RequestRender()
 		RequestRender()
 		
 		
+		If Keyboard.KeyHit( Key.Escape ) App.Terminate()
+		
 		If Keyboard.KeyHit( Key.Space ) _donut.Visible=Not _donut.Visible
 		If Keyboard.KeyHit( Key.Space ) _donut.Visible=Not _donut.Visible
 		
 		
 		_donut.Rotate( .2,.4,.6 )
 		_donut.Rotate( .2,.4,.6 )
 		
 		
-		util.Fly( _camera,Self )
+		_scene.Update()
 		
 		
 		_scene.Render( canvas,_camera )
 		_scene.Render( canvas,_camera )
 		
 		

+ 0 - 0
assets/themes/hollow_assets/checkbox_icons.png → assets/themes/hollow_assets/hollow_checkbox_icons.png


+ 0 - 0
assets/themes/hollow_assets/dialog_skin.png → assets/themes/hollow_assets/hollow_dialog_skin.png


+ 0 - 0
assets/themes/hollow_assets/progressbar_icons.png → assets/themes/hollow_assets/hollow_progressbar_icons.png


+ 0 - 0
assets/themes/hollow_assets/tabclose_icons.png → assets/themes/hollow_assets/hollow_tabclose_icons.png


+ 0 - 0
assets/themes/hollow_assets/treeview_icons.png → assets/themes/hollow_assets/hollow_treeview_icons.png


+ 0 - 0
assets/themes/prime_assets/checkbox_icons.png → assets/themes/prime_assets/prime_checkbox_icons.png


+ 0 - 0
assets/themes/prime_assets/dialog_skin.png → assets/themes/prime_assets/prime_dialog_skin.png


+ 0 - 0
assets/themes/prime_assets/progressbar_icons.png → assets/themes/prime_assets/prime_progressbar_icons.png


+ 0 - 0
assets/themes/prime_assets/tabclose_icons.png → assets/themes/prime_assets/prime_tabclose_icons.png


+ 0 - 0
assets/themes/prime_assets/treeview_icons.png → assets/themes/prime_assets/prime_treeview_icons.png


+ 0 - 0
assets/themes/smooth_assets/button_skin.png → assets/themes/smooth_assets/smooth_button_skin.png


+ 0 - 0
assets/themes/smooth_assets/checkbox_icons.png → assets/themes/smooth_assets/smooth_checkbox_icons.png


+ 0 - 0
assets/themes/smooth_assets/dialog_skin.png → assets/themes/smooth_assets/smooth_dialog_skin.png


+ 0 - 0
assets/themes/smooth_assets/progressbar_icons.png → assets/themes/smooth_assets/smooth_progressbar_icons.png


BIN
assets/themes/smooth_assets/smooth_tabbutton_locked_skin.png


+ 0 - 0
assets/themes/smooth_assets/tabbutton_selected_skin.png → assets/themes/smooth_assets/smooth_tabbutton_selected_skin.png


+ 0 - 0
assets/themes/smooth_assets/tabbutton_skin.png → assets/themes/smooth_assets/smooth_tabbutton_skin.png


+ 0 - 0
assets/themes/smooth_assets/tabclose_icons.png → assets/themes/smooth_assets/smooth_tabclose_icons.png


+ 0 - 0
assets/themes/smooth_assets/treeview_icons.png → assets/themes/smooth_assets/smooth_treeview_icons.png


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

@@ -11,7 +11,9 @@
 		"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",
+		"params-hint-common": "textview-color1",
+		"params-hint-selected": "textview-color4"
 	},
 	},
 
 
 	"fonts":{
 	"fonts":{
@@ -21,8 +23,7 @@
 	},
 	},
 	
 	
 	"styles":{
 	"styles":{
-				
-
+		
 		"GutterView":{
 		"GutterView":{
 			"extends":"TextView",
 			"extends":"TextView",
 			"textColor":"text-disabled",
 			"textColor":"text-disabled",
@@ -47,6 +48,10 @@
 			"backgroundColor":"panel"
 			"backgroundColor":"panel"
 		},
 		},
 
 
+		"ParamsHint":{
+			"extends":"Hint"
+		},
+
 		"ToolBarExt":{
 		"ToolBarExt":{
 			"extends":"ToolBar",
 			"extends":"ToolBar",
 			"padding":[ 0 ],
 			"padding":[ 0 ],

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

@@ -23,6 +23,8 @@
 		"brighter": "#665C54",
 		"brighter": "#665C54",
 		"brightest": "#7C6F64",
 		"brightest": "#7C6F64",
 
 
+		"separator": "#2A2828",
+
 		"text-default": "#CECECE",
 		"text-default": "#CECECE",
 		"text-highlight": "#FFFFFF",
 		"text-highlight": "#FFFFFF",
 		"text-disabled": "#6F6F6F",
 		"text-disabled": "#6F6F6F",
@@ -130,7 +132,7 @@
 		},
 		},
 
 
 		"ProgressBar":{
 		"ProgressBar":{
-			"icons":"hollow_assets/progressbar_icons.png"
+			"icons":"hollow_assets/hollow_progressbar_icons.png"
 		},
 		},
 
 
 		"StatusBar":{
 		"StatusBar":{
@@ -232,7 +234,7 @@
 		},
 		},
 		
 		
 		"CheckBox":{
 		"CheckBox":{
-			"icons":"hollow_assets/checkbox_icons.png",
+			"icons":"hollow_assets/hollow_checkbox_icons.png",
 			"iconColor":"textview-color7",
 			"iconColor":"textview-color7",
 			"margin":[0,0,0,0]
 			"margin":[0,0,0,0]
 		},
 		},
@@ -302,7 +304,7 @@
 		"Menu":{
 		"Menu":{
 			"extends":"DockingView",
 			"extends":"DockingView",
 			"padding":[ 0 ],
 			"padding":[ 0 ],
-			"skin":"hollow_assets/dialog_skin.png",
+			"skin":"hollow_assets/hollow_dialog_skin.png",
 			"skinColor":"dark"
 			"skinColor":"dark"
 		},
 		},
 		
 		
@@ -334,7 +336,7 @@
 		
 		
 		"MenuSeparator":{
 		"MenuSeparator":{
 			"padding":[ 0,0,0,1 ],
 			"padding":[ 0,0,0,1 ],
-			"backgroundColor":"dark",
+			"backgroundColor":"separator",
 			"border":[ 8,8,7,7 ]
 			"border":[ 8,8,7,7 ]
 		},
 		},
 
 
@@ -370,9 +372,14 @@
 			}
 			}
 		},
 		},
 		
 		
+		"TabButtonLocked":{
+			"extends":"TabButton",
+			"borderColor":"#F26522"
+		},
+		
 		"TabClose":{
 		"TabClose":{
 			"margin":[32,0,0,0 ],
 			"margin":[32,0,0,0 ],
-			"icons":"hollow_assets/tabclose_icons.png",
+			"icons":"hollow_assets/hollow_tabclose_icons.png",
 			"iconColor":"text-disabled",
 			"iconColor":"text-disabled",
 			"states":{
 			"states":{
 				"hover":{
 				"hover":{
@@ -399,7 +406,7 @@
 		
 		
 		"TreeView":{
 		"TreeView":{
 			"backgroundColor":"darker",
 			"backgroundColor":"darker",
-			"icons":"hollow_assets/treeview_icons.png",
+			"icons":"hollow_assets/hollow_treeview_icons.png",
 			"iconColor":"text-background"
 			"iconColor":"text-background"
 		},
 		},
 		
 		
@@ -454,7 +461,7 @@
 		},
 		},
 		
 		
 		"Dialog":{
 		"Dialog":{
-			"skin":"hollow_assets/dialog_skin.png",
+			"skin":"hollow_assets/hollow_dialog_skin.png",
 			"skinColor":"bright"
 			"skinColor":"bright"
 		},
 		},
 		
 		

+ 11 - 6
assets/themes/theme-prime-base.json

@@ -142,7 +142,7 @@
 
 
 		"ProgressBar":{
 		"ProgressBar":{
 			"iconColor":"accent",
 			"iconColor":"accent",
-			"icons":"prime_assets/progressbar_icons.png"
+			"icons":"prime_assets/prime_progressbar_icons.png"
 		},
 		},
 
 
 		"StatusBar":{
 		"StatusBar":{
@@ -222,7 +222,7 @@
 		},
 		},
 		
 		
 		"CheckBox":{
 		"CheckBox":{
-			"icons":"prime_assets/checkbox_icons.png",
+			"icons":"prime_assets/prime_checkbox_icons.png",
 			"iconColor":"accent",
 			"iconColor":"accent",
 			"margin":[0,0,0,0]
 			"margin":[0,0,0,0]
 		},
 		},
@@ -292,7 +292,7 @@
 		"Menu":{
 		"Menu":{
 			"extends":"DockingView",
 			"extends":"DockingView",
 			"padding":[ 0 ],
 			"padding":[ 0 ],
-			"skin":"prime_assets/dialog_skin.png",
+			"skin":"prime_assets/prime_dialog_skin.png",
 			"skinColor":"darkest"
 			"skinColor":"darkest"
 		},
 		},
 		
 		
@@ -358,10 +358,15 @@
 				}
 				}
 			}
 			}
 		},
 		},
+
+		"TabButtonLocked":{
+			"extends":"TabButton",
+			"borderColor":"textview-color4"
+		},
 		
 		
 		"TabClose":{
 		"TabClose":{
 			"margin":[32,0,0,0 ],
 			"margin":[32,0,0,0 ],
-			"icons":"prime_assets/tabclose_icons.png",
+			"icons":"prime_assets/prime_tabclose_icons.png",
 			"iconColor":"text-disabled",
 			"iconColor":"text-disabled",
 			"states":{
 			"states":{
 				"hover":{
 				"hover":{
@@ -388,7 +393,7 @@
 		
 		
 		"TreeView":{
 		"TreeView":{
 			"backgroundColor":"dark",
 			"backgroundColor":"dark",
-			"icons":"prime_assets/treeview_icons.png",
+			"icons":"prime_assets/prime_treeview_icons.png",
 			"iconColor":"#8fff"
 			"iconColor":"#8fff"
 		},
 		},
 		
 		
@@ -444,7 +449,7 @@
 		},
 		},
 		
 		
 		"Dialog":{
 		"Dialog":{
-			"skin":"prime_assets/dialog_skin.png",
+			"skin":"prime_assets/prime_dialog_skin.png",
 			"skinColor":"bright"
 			"skinColor":"bright"
 		},
 		},
 		
 		

+ 14 - 9
assets/themes/theme-smooth.json

@@ -49,7 +49,7 @@
 
 
 		"Hint":{
 		"Hint":{
 			"textColor":"text-highlight",
 			"textColor":"text-highlight",
-			"skin":"smooth_assets/button_skin.png",
+			"skin":"smooth_assets/smooth_button_skin.png",
 			"skinColor":"#9EBEFF"
 			"skinColor":"#9EBEFF"
 		},
 		},
 
 
@@ -79,14 +79,14 @@
 		},
 		},
 
 
 		"ProgressBar":{
 		"ProgressBar":{
-			"icons":"smooth_assets/progressbar_icons.png"
+			"icons":"smooth_assets/smooth_progressbar_icons.png"
 		},
 		},
 
 
 		"Button":{
 		"Button":{
 			"font":"small",
 			"font":"small",
 			"extends":"Label",
 			"extends":"Label",
 			"padding":[4,2],
 			"padding":[4,2],
-			"skin":"smooth_assets/button_skin.png",
+			"skin":"smooth_assets/smooth_button_skin.png",
 			"skinColor":"panel",
 			"skinColor":"panel",
 
 
 			"states":{
 			"states":{
@@ -103,7 +103,7 @@
 		},
 		},
 
 
 		"Dialog":{
 		"Dialog":{
-			"skin":"smooth_assets/dialog_skin.png",
+			"skin":"smooth_assets/smooth_dialog_skin.png",
 			"skinColor":"panel"
 			"skinColor":"panel"
 		},
 		},
 
 
@@ -115,7 +115,7 @@
         "TreeView":{
         "TreeView":{
             "borderColor":"border",
             "borderColor":"border",
             "backgroundColor":"content",
             "backgroundColor":"content",
-            "icons":"smooth_assets/treeview_icons.png",
+            "icons":"smooth_assets/smooth_treeview_icons.png",
             "iconColor":"#9DA5B4"
             "iconColor":"#9DA5B4"
         },
         },
 
 
@@ -140,7 +140,7 @@
 		},
 		},
 
 
 		"CheckBox":{
 		"CheckBox":{
-			"icons":"smooth_assets/checkbox_icons.png",
+			"icons":"smooth_assets/smooth_checkbox_icons.png",
 			"margin":[8,0,0,0]
 			"margin":[8,0,0,0]
 		},
 		},
 
 
@@ -197,7 +197,7 @@
             "margin":[0,0,-1,0],
             "margin":[0,0,-1,0],
 			"padding":[16,5,16,7],
 			"padding":[16,5,16,7],
 			"backgroundColor":"#0000",
 			"backgroundColor":"#0000",
-			"skin":"smooth_assets/tabbutton_skin.png",
+			"skin":"smooth_assets/smooth_tabbutton_skin.png",
 			"textColor":"text-background",
 			"textColor":"text-background",
 			"states":{
 			"states":{
 				"hover":{
 				"hover":{
@@ -205,7 +205,7 @@
 				"active":{
 				"active":{
 				},
 				},
 				"selected":{
 				"selected":{
-                    "skin":"smooth_assets/tabbutton_selected_skin.png",
+                    "skin":"smooth_assets/smooth_tabbutton_selected_skin.png",
                     "padding":[16,5,16,9],
                     "padding":[16,5,16,9],
 					"border":[0],
 					"border":[0],
 					"borderColor":"#507FDF",
 					"borderColor":"#507FDF",
@@ -214,9 +214,14 @@
 			}
 			}
 		},
 		},
 
 
+		"TabButtonLocked":{
+			"extends":"TabButton",
+			"skin":"smooth_assets/smooth_tabbutton_locked_skin.png"
+		},
+
 		"TabClose":{
 		"TabClose":{
 			"margin":[4,0,0,0],
 			"margin":[4,0,0,0],
-			"icons":"smooth_assets/tabclose_icons.png",
+			"icons":"smooth_assets/smooth_tabclose_icons.png",
 			"iconColor":"#373737",
 			"iconColor":"#373737",
 			"states":{
 			"states":{
 				"hover":{
 				"hover":{

+ 1 - 1
assets/themes/theme-warm.json

@@ -54,7 +54,7 @@
 
 
 		"TabClose":{
 		"TabClose":{
 			"margin":[8,8,8,8 ],
 			"margin":[8,8,8,8 ],
-			"icons":"prime_assets/tabclose_icons.png",
+			"icons":"prime_assets/prime_tabclose_icons.png",
 			"iconColor":"text-disabled",
 			"iconColor":"text-disabled",
 			"states":{
 			"states":{
 				"hover":{
 				"hover":{

+ 42 - 0
dialog/DialogExt.monkey2

@@ -7,14 +7,30 @@ Class DialogExt Extends Dialog
 	Field OnShow:Void()
 	Field OnShow:Void()
 	Field OnHide:Void()
 	Field OnHide:Void()
 	
 	
+	Method New()
+		Super.New()
+	End
+	
+	Method New( title:String,contentView:View=Null )
+		Super.New( title,contentView )
+	End
+	
 	Property IsOpened:Bool()
 	Property IsOpened:Bool()
 		Return _opened
 		Return _opened
 	End
 	End
 	
 	
+	Property FadeEnabled:Bool()
+		Return _fadeEnabled
+	Setter( value:Bool )
+		_fadeEnabled=value
+	End
+	
 	Method Show()
 	Method Show()
 		
 		
 		If _opened Return
 		If _opened Return
 		_opened = True
 		_opened = True
+		
+		TryAddFade()
 		Open()
 		Open()
 		OnShow()
 		OnShow()
 	End
 	End
@@ -24,6 +40,8 @@ Class DialogExt Extends Dialog
 		If _opened Return False
 		If _opened Return False
 		
 		
 		_opened = True
 		_opened = True
+		
+		TryAddFade()
 		Open()
 		Open()
 		OnShow()
 		OnShow()
 		
 		
@@ -45,6 +63,13 @@ Class DialogExt Extends Dialog
 		If Not _opened Return
 		If Not _opened Return
 		
 		
 		_opened = False
 		_opened = False
+		
+		If _fadeView
+			Local wnd:=App.ActiveWindow
+			wnd.RemoveChildView( _fadeView )
+			_fadeView=Null
+		Endif
+		
 		Close()
 		Close()
 		OnHide()
 		OnHide()
 		
 		
@@ -59,5 +84,22 @@ Class DialogExt Extends Dialog
 	
 	
 	Field _opened:Bool
 	Field _opened:Bool
 	Field _wait:Future<Bool>
 	Field _wait:Future<Bool>
+	Field _fadeEnabled:Bool
+	Field _fadeView:View
+	
+	Method TryAddFade()
+		
+		If Not _fadeEnabled Return
+		
+		Local wnd:=App.ActiveWindow
+		_fadeView=New Label
+		_fadeView.Layout="float"
+		_fadeView.Gravity=New Vec2f
+		_fadeView.MinSize=wnd.Frame.Size
+		Local st:=_fadeView.Style.Copy()
+		st.BackgroundColor=New Color( 0,0,0,0.33 )
+		_fadeView.Style=st
+		wnd.AddChildView( _fadeView )
+	End
 	
 	
 End
 End

+ 1 - 1
dialog/GenerateClassDialog.monkey2

@@ -16,7 +16,7 @@ Class GenerateClassDialog Extends DialogExt
 		
 		
 		Local dock:=New DockingView
 		Local dock:=New DockingView
 		
 		
-		_codeView=New Ted2CodeTextView
+		_codeView=New Ted2CodeTextView( Ted2Document.Empty )
 		_codeView.FileType=".monkey2"
 		_codeView.FileType=".monkey2"
 		_codeView.MinSize=New Vec2i( 200,200 )
 		_codeView.MinSize=New Vec2i( 200,200 )
 		dock.AddView( _codeView,"bottom" )
 		dock.AddView( _codeView,"bottom" )

+ 7 - 1
dialog/PrefsDialog.monkey2

@@ -79,6 +79,7 @@ Class PrefsDialog Extends DialogExt
 	Field _editorAutoIndent:CheckButton
 	Field _editorAutoIndent:CheckButton
 	Field _editorAutoPairs:CheckButton
 	Field _editorAutoPairs:CheckButton
 	Field _editorSurround:CheckButton
 	Field _editorSurround:CheckButton
+	Field _editorShowParamsHint:CheckButton
 	
 	
 	Field _mainToolBarVisible:CheckButton
 	Field _mainToolBarVisible:CheckButton
 	Field _mainProjectIcons:CheckButton
 	Field _mainProjectIcons:CheckButton
@@ -123,6 +124,7 @@ Class PrefsDialog Extends DialogExt
 		Prefs.EditorAutoIndent=_editorAutoIndent.Checked
 		Prefs.EditorAutoIndent=_editorAutoIndent.Checked
 		Prefs.EditorAutoPairs=_editorAutoPairs.Checked
 		Prefs.EditorAutoPairs=_editorAutoPairs.Checked
 		Prefs.EditorSurroundSelection=_editorSurround.Checked
 		Prefs.EditorSurroundSelection=_editorSurround.Checked
+		Prefs.EditorShowParamsHint=_editorShowParamsHint.Checked
 		
 		
 		Prefs.MainToolBarVisible=_mainToolBarVisible.Checked
 		Prefs.MainToolBarVisible=_mainToolBarVisible.Checked
 		Prefs.MainProjectIcons=_mainProjectIcons.Checked
 		Prefs.MainProjectIcons=_mainProjectIcons.Checked
@@ -229,6 +231,9 @@ Class PrefsDialog Extends DialogExt
 		_editorSurround=New CheckButton( "Surround selected text with ~q~q, (), []" )
 		_editorSurround=New CheckButton( "Surround selected text with ~q~q, (), []" )
 		_editorSurround.Checked=Prefs.EditorSurroundSelection
 		_editorSurround.Checked=Prefs.EditorSurroundSelection
 		
 		
+		_editorShowParamsHint=New CheckButton( "Show parameters hint" )
+		_editorShowParamsHint.Checked=Prefs.EditorShowParamsHint
+		
 		Local path:=Prefs.EditorFontPath
 		Local path:=Prefs.EditorFontPath
 		If Not path Then path=_defaultFont
 		If Not path Then path=_defaultFont
 		_editorFontPath=New TextFieldExt( "" )
 		_editorFontPath=New TextFieldExt( "" )
@@ -281,6 +286,7 @@ Class PrefsDialog Extends DialogExt
 		docker.AddView( _editorAutoIndent,"top" )
 		docker.AddView( _editorAutoIndent,"top" )
 		docker.AddView( _editorAutoPairs,"top" )
 		docker.AddView( _editorAutoPairs,"top" )
 		docker.AddView( _editorSurround,"top" )
 		docker.AddView( _editorSurround,"top" )
+		docker.AddView( _editorShowParamsHint,"top" )
 		docker.AddView( New Label( " " ),"top" )
 		docker.AddView( New Label( " " ),"top" )
 		
 		
 		Return docker
 		Return docker
@@ -414,7 +420,7 @@ Class PrefsDialog Extends DialogExt
 		Local docker1:=New DockingView
 		Local docker1:=New DockingView
 		docker1.AddView( treeDock,"left","170",True)
 		docker1.AddView( treeDock,"left","170",True)
 		
 		
-		_codeView=New Ted2CodeTextView
+		_codeView=New Ted2CodeTextView( Ted2Document.Empty )
 		_codeView.ShowWhiteSpaces=True
 		_codeView.ShowWhiteSpaces=True
 		_codeView.Document.TextChanged+=Lambda()
 		_codeView.Document.TextChanged+=Lambda()
 			
 			

+ 47 - 54
dialog/UpdateModulesDialog.monkey2

@@ -1,9 +1,9 @@
-Namespace ted2go
 
 
+Namespace ted2go
 
 
 Class UpdateModulesDialog Extends DialogExt
 Class UpdateModulesDialog Extends DialogExt
 	
 	
-	Method New( targets:StringStack,selectedModules:String,configs:String,clean:Bool )
+	Method New( targets:StringStack,selectedTargets:String,selectedModules:String,configs:String,clean:Bool )
 		
 		
 		_modsNames.Clear()
 		_modsNames.Clear()
 		GetModulesNames( _modsNames )
 		GetModulesNames( _modsNames )
@@ -53,13 +53,15 @@ Class UpdateModulesDialog Extends DialogExt
 		dock.AddView( table,"top" )
 		dock.AddView( table,"top" )
 		dock.AddView( New Label( " " ),"top" )
 		dock.AddView( New Label( " " ),"top" )
 		
 		
+		Local selTargets:=New StringStack( selectedTargets.Split( " " ) )
+		
 		dock.AddView( New Label( "Targets:" ),"top" )
 		dock.AddView( New Label( "Targets:" ),"top" )
 		Local targetDock:=New DockingView
 		Local targetDock:=New DockingView
 		For Local t:=Eachin targets
 		For Local t:=Eachin targets
 			Local chb:=New CheckButton( t )
 			Local chb:=New CheckButton( t )
 			targetDock.AddView( chb,"left" )
 			targetDock.AddView( chb,"left" )
 			_targetsViews.Add( chb )
 			_targetsViews.Add( chb )
-			chb.Checked=(t="desktop")
+			chb.Checked=selTargets.Contains( t )
 		Next
 		Next
 		dock.AddView( targetDock,"top" )
 		dock.AddView( targetDock,"top" )
 		dock.AddView( New Label( " " ),"top" )
 		dock.AddView( New Label( " " ),"top" )
@@ -171,11 +173,17 @@ Class UpdateModulesDialog Extends DialogExt
 	This sorts modules into dependancy order.
 	This sorts modules into dependancy order.
 	
 	
 	#end
 	#end
-	Function EnumModules( out:StringStack,cur:String,deps:StringMap<StringStack> )
-		If out.Contains( cur ) Return
+	Function EnumModules( out:StringStack,cur:String,src:String,deps:StringMap<StringStack> )
 		
 		
+		If Not deps.Contains( cur )
+'			Print "Can't find module dependancy '"+cur+"' - check module.json file for '"+src+"'"
+			Return
+		End
+		
+		If out.Contains( cur ) Return
+
 		For Local dep:=Eachin deps[cur]
 		For Local dep:=Eachin deps[cur]
-			EnumModules( out,dep,deps )
+			EnumModules( out,dep,cur,deps )
 		Next
 		Next
 		
 		
 		out.Push( cur )
 		out.Push( cur )
@@ -183,43 +191,46 @@ Class UpdateModulesDialog Extends DialogExt
 	
 	
 	Function EnumModules:String[]()
 	Function EnumModules:String[]()
 	
 	
+		LoadEnv()
+		
 		Local mods:=New StringMap<StringStack>
 		Local mods:=New StringMap<StringStack>
 		
 		
-		Local modsPath:=MainWindow.ModsPath
+		For Local moddir:=Eachin ModuleDirs
 	
 	
-		For Local f:=Eachin LoadDir( modsPath )
-		
-			Local dir:=modsPath+f+"/"
-			If GetFileType( dir )<>FileType.Directory Continue
-			
-			Local str:=LoadString( dir+"module.json" )
-			If Not str Continue
-			
-			Local obj:=JsonObject.Parse( str )
-			If Not obj 
-				Print "Error parsing json:"+dir+"module.json"
-				Continue
-			Endif
-			
-			Local name:=obj["module"].ToString()
-			If name<>f Continue
-			
-			Local deps:=New StringStack
-			If name<>"monkey" deps.Push( "monkey" )
+			For Local f:=Eachin LoadDir( moddir )
 			
 			
-			Local jdeps:=obj["depends"]
-			If jdeps
-				For Local dep:=Eachin jdeps.ToArray()
-					deps.Push( dep.ToString() )
-				Next
-			Endif
-			
-			mods[name]=deps
+				Local dir:=moddir+f+"/"
+				If GetFileType( dir )<>FileType.Directory Continue
+				
+				Local str:=LoadString( dir+"module.json" )
+				If Not str Continue
+				
+				Local obj:=JsonObject.Parse( str )
+				If Not obj 
+					Print "Error parsing json:"+dir+"module.json"
+					Continue
+				Endif
+				
+				Local name:=obj["module"].ToString()
+				If name<>f Continue
+				
+				Local deps:=New StringStack
+				If name<>"monkey" deps.Push( "monkey" )
+				
+				Local jdeps:=obj["depends"]
+				If jdeps
+					For Local dep:=Eachin jdeps.ToArray()
+						deps.Push( dep.ToString() )
+					Next
+				Endif
+				
+				mods[name]=deps
+			Next
 		Next
 		Next
-		
+				
 		Local out:=New StringStack
 		Local out:=New StringStack
 		For Local cur:=Eachin mods.Keys
 		For Local cur:=Eachin mods.Keys
-			EnumModules( out,cur,mods )
+			EnumModules( out,cur,"",mods )
 		Next
 		Next
 		
 		
 		Return out.ToArray()
 		Return out.ToArray()
@@ -230,22 +241,4 @@ Class UpdateModulesDialog Extends DialogExt
 		out.AddAll( EnumModules() )
 		out.AddAll( EnumModules() )
 	End
 	End
 
 
-#rem	
-	Function GetModulesNames( out:StringStack )
-	
-		Local modsPath:=MainWindow.ModsPath
-	
-		Local dd:=LoadDir( modsPath )
-	
-		For Local d:=Eachin dd
-			If GetFileType( modsPath+d ) = FileType.Directory
-				Local file:=modsPath + d + "/module.json"
-				If GetFileType( file ) = FileType.File
-					out.Add( d )
-				Endif
-			Endif
-		Next
-	End
-#end
-	
 End
 End

+ 18 - 12
document/BananasDocument.monkey2

@@ -21,8 +21,11 @@ Class BananasDocument Extends Ted2Document
 		_table.Gravity=New Vec2f( 0.5,0 )
 		_table.Gravity=New Vec2f( 0.5,0 )
 		scrollView.ContentView=_table
 		scrollView.ContentView=_table
 		
 		
-		_filterPanel=New ToolBar
-		scrollView.AddView( _filterPanel,"bottom" )
+		_filterPanel=New ToolBarExt
+		Local sbox:=New ScrollViewTabs( _filterPanel )
+		sbox.ScrollBarsVisible=False
+		
+		scrollView.AddView( sbox,"bottom" )
 		
 		
 		Local lab:=New Label( "Bananas Showcase" )
 		Local lab:=New Label( "Bananas Showcase" )
 		lab.Style=App.Theme.GetStyle( "BananasTitle" )
 		lab.Style=App.Theme.GetStyle( "BananasTitle" )
@@ -31,6 +34,9 @@ Class BananasDocument Extends Ted2Document
 		scrollView.AddView( lab,"top" )
 		scrollView.AddView( lab,"top" )
 		
 		
 		_list=New ListView
 		_list=New ListView
+		Local st:=_list.Style.Copy()
+		st.Padding=New Recti( -6,-6,6,6 )
+		_list.Style=st
 		_list.ItemDoubleClicked+=Lambda( item:ListView.Item )
 		_list.ItemDoubleClicked+=Lambda( item:ListView.Item )
 			
 			
 			OpenItem( FindItem( item.Text ) )
 			OpenItem( FindItem( item.Text ) )
@@ -64,8 +70,8 @@ Class BananasDocument Extends Ted2Document
 	Private
 	Private
 	
 	
 	Const EMPTY_TAG:="#"
 	Const EMPTY_TAG:="#"
-	Const MAX_WIDTH:=300
-	Const MAX_HEIGHT:=200
+	Const MAX_WIDTH:=256
+	Const MAX_HEIGHT:=196
 	Field _list:ListView
 	Field _list:ListView
 	Field _table:TableView
 	Field _table:TableView
 	Field _view:View
 	Field _view:View
@@ -75,7 +81,7 @@ Class BananasDocument Extends Ted2Document
 	Field _tags:=New StringStack
 	Field _tags:=New StringStack
 	Field _filterTags:=New StringStack
 	Field _filterTags:=New StringStack
 	Field _filterViews:=New Stack<ToolButtonExt>
 	Field _filterViews:=New Stack<ToolButtonExt>
-	Field _filterPanel:ToolBar
+	Field _filterPanel:ToolBarExt
 	
 	
 	Struct Item
 	Struct Item
 		
 		
@@ -353,13 +359,13 @@ Class BananasDocument Extends Ted2Document
 		If item.author Then dock.AddView( New Label( item.author ),"top" )
 		If item.author Then dock.AddView( New Label( item.author ),"top" )
 		
 		
 		' version and modified
 		' version and modified
-		Local vers:=item.version
-		If vers Then vers="v"+vers
-		If item.modified
-			If vers Then vers+=" at "
-			vers+=item.modified
-		Endif
-		If vers Then dock.AddView( New Label( vers ),"top" )
+'		Local vers:=item.version
+'		If vers Then vers="v"+vers
+'		If item.modified
+'			If vers Then vers+=" at "
+'			vers+=item.modified
+'		Endif
+'		If vers Then dock.AddView( New Label( vers ),"top" )
 		
 		
 		'tags
 		'tags
 		If item.tags Then dock.AddView( New Label( item.tags ),"top" )
 		If item.tags Then dock.AddView( New Label( item.tags ),"top" )

+ 441 - 49
document/CodeDocument.monkey2

@@ -32,16 +32,13 @@ Class CodeDocumentView Extends Ted2CodeTextView
 	
 	
 	
 	
 	Method New( doc:CodeDocument )
 	Method New( doc:CodeDocument )
-	
+		
+		Super.New( doc )
+		
 		_doc=doc
 		_doc=doc
 		
 		
 		ContentView.Style.Border=New Recti( -4,-4,4,4 )
 		ContentView.Style.Border=New Recti( -4,-4,4,4 )
 		
 		
-		'very important to set FileType for init
-		'formatter, highlighter and keywords
-		FileType=doc.FileExtension
-		FilePath=doc.Path
-		
 		'AutoComplete
 		'AutoComplete
 		If Not AutoComplete Then AutoComplete=New AutocompleteDialog
 		If Not AutoComplete Then AutoComplete=New AutocompleteDialog
 		AutoComplete.OnChoosen+=Lambda( result:AutocompleteResult )
 		AutoComplete.OnChoosen+=Lambda( result:AutocompleteResult )
@@ -117,12 +114,14 @@ Class CodeDocumentView Extends Ted2CodeTextView
 		_doc.ArrangeElements()
 		_doc.ArrangeElements()
 	End
 	End
 	
 	
-
+	
 	Protected
 	Protected
 	
 	
 	Method OnThemeChanged() Override
 	Method OnThemeChanged() Override
 		
 		
-		_doc.HideAutocomplete()
+		_doc.HideAllPopups()
+		
+		Super.OnThemeChanged()
 	End
 	End
 	
 	
 	Method OnRenderContent( canvas:Canvas ) Override
 	Method OnRenderContent( canvas:Canvas ) Override
@@ -177,6 +176,7 @@ Class CodeDocumentView Extends Ted2CodeTextView
 		Local alt:=(event.Modifiers & Modifier.Alt)
 		Local alt:=(event.Modifiers & Modifier.Alt)
 		Local ctrl:=(event.Modifiers & Modifier.Control)
 		Local ctrl:=(event.Modifiers & Modifier.Control)
 		Local shift:=(event.Modifiers & Modifier.Shift)
 		Local shift:=(event.Modifiers & Modifier.Shift)
+		Local menu:=(event.Modifiers & Modifier.Menu)
 		
 		
 		'ctrl+space - show autocomplete list
 		'ctrl+space - show autocomplete list
 		Select event.Type
 		Select event.Type
@@ -185,7 +185,19 @@ Class CodeDocumentView Extends Ted2CodeTextView
 			Local key:=FixNumpadKeys( event )
 			Local key:=FixNumpadKeys( event )
 			
 			
 			Select key
 			Select key
-			
+				
+'				#If __TARGET__="macos"
+'				Case Key.K
+'					If ctrl 
+'						If shift
+'							DeleteLineAtCursor()
+'						Else
+'							DeleteToEnd()
+'						Endif
+'						Return
+'					Endif
+'				#Endif
+				
 				Case Key.Space
 				Case Key.Space
 					If ctrl
 					If ctrl
 						Return
 						Return
@@ -207,17 +219,27 @@ Class CodeDocumentView Extends Ted2CodeTextView
 						
 						
 					Else
 					Else
 						
 						
-						#If __TARGET__="macos"
-						If ctrl
-							DeleteLineAtCursor()
-						Endif
-						#Endif
+'						#If __TARGET__="macos"
+'						If menu
+'							DeleteToBegin()
+'						Elseif ctrl
+'							DeleteWordBeforeCursor()
+'						Endif
+'						#Else
+'						If ctrl
+'							If shift
+'								DeleteToBegin()
+'							Else
+'								DeleteWordBeforeCursor()
+'							Endif
+'						Endif
+'						#Endif
 						
 						
 					Endif
 					Endif
 				
 				
-				Case Key.F11
-				
-					ShowJsonDialog()
+				'Case Key.F11
+				'
+				'	ShowJsonDialog()
 					
 					
 					
 					
 				#If __TARGET__="windows"
 				#If __TARGET__="windows"
@@ -261,7 +283,13 @@ Class CodeDocumentView Extends Ted2CodeTextView
 				Case Key.KeyDelete
 				Case Key.KeyDelete
 			
 			
 					If shift 'shift+del - cut selected
 					If shift 'shift+del - cut selected
-						If CanCopy Then OnCut()
+						If ctrl
+'							DeleteToEnd()
+						Elseif CanCopy
+							OnCut()
+						Endif
+'					Else If ctrl 'ctrl w/o shift
+'						DeleteWordAfterCursor()
 					Else
 					Else
 						If Anchor = Cursor
 						If Anchor = Cursor
 							Local len:=Text.Length
 							Local len:=Text.Length
@@ -745,16 +773,6 @@ Class CodeDocumentView Extends Ted2CodeTextView
 		Return False
 		Return False
 	End
 	End
 	
 	
-	Method DeleteLineAtCursor()
-		
-		Local line:=Document.FindLine( Cursor )
-		Local pos:=Cursor
-		SelectText( Document.StartOfLine( line ),Document.EndOfLine( line )+1 )
-		ReplaceText( "" )
-		pos=Min( pos,Document.EndOfLine( line ) )
-		SelectText( pos,pos )
-	End
-	
 End
 End
 
 
 
 
@@ -763,7 +781,14 @@ Class CodeDocument Extends Ted2Document
 	Method New( path:String )
 	Method New( path:String )
 		
 		
 		Super.New( path )
 		Super.New( path )
-	
+		
+		' if file type was changed
+		Renamed+=Lambda( newPath:String,oldPath:String )
+			
+			InitParser()
+			ResetErrors()
+		End
+		
 		_view=New DockingView
 		_view=New DockingView
 		
 		
 		' Editor
 		' Editor
@@ -797,11 +822,14 @@ Class CodeDocument Extends Ted2Document
 		End
 		End
 		
 		
 		_doc.TextChanged+=Lambda()
 		_doc.TextChanged+=Lambda()
+		
 			Dirty=True
 			Dirty=True
 			OnTextChanged()
 			OnTextChanged()
 			_codeView.TextChanged()
 			_codeView.TextChanged()
 		End
 		End
 		
 		
+		_codeView.CursorMoved+=OnCursorChanged
+		
 		' bar + editor
 		' bar + editor
 		_content=New DockingView
 		_content=New DockingView
 		_content.ContentView=_codeView
 		_content.ContentView=_codeView
@@ -817,9 +845,9 @@ Class CodeDocument Extends Ted2Document
 		End
 		End
 		
 		
 		' update 
 		' update 
-		Monkey2Parser.OnDoneParseModules+=Lambda( deltaMs:Int )
-			UpdateCodeTree()
-		End
+'		Monkey2Parser.OnDoneParseModules+=Lambda( deltaMs:Int )
+'			UpdateCodeTree()
+'		End
 		
 		
 		ArrangeElements()
 		ArrangeElements()
 	End
 	End
@@ -899,13 +927,15 @@ Class CodeDocument Extends Ted2Document
 		
 		
 		If FileExtension <> ".monkey2" Return ident
 		If FileExtension <> ".monkey2" Return ident
 		
 		
-		If ident <> text And item And item.IsLikeFunc 'not a keyword
+		If ident<>text And item And item.IsLikeFunc 'not a keyword
 			
 			
 			Local i:=textLine.Find( "Method " ) 'to simplify overriding - insert full text
 			Local i:=textLine.Find( "Method " ) 'to simplify overriding - insert full text
 			If i <> -1 And i < cursorPosInLine
 			If i <> -1 And i < cursorPosInLine
 				Local i2:=textLine.Find( "(" ) 'is inside of params?
 				Local i2:=textLine.Find( "(" ) 'is inside of params?
 				If i2 = -1 Or i2 > cursorPosInLine
 				If i2 = -1 Or i2 > cursorPosInLine
-					Return text.StartsWith( "New(" ) ? text Else text+" Override"
+					Local ovr:=Not text.StartsWith( "New(" )
+					If ovr And item.Parent And item.Parent.Kind=CodeItemKind.Interface_ Then ovr=False
+					Return ovr ? text+" Override" Else text
 				Endif
 				Endif
 			Endif
 			Endif
 			
 			
@@ -1008,6 +1038,7 @@ Class CodeDocument Extends Ted2Document
 	End
 	End
 	
 	
 	Property HasErrors:Bool()
 	Property HasErrors:Bool()
+		
 		Return Not _errors.Empty
 		Return Not _errors.Empty
 	End
 	End
 	
 	
@@ -1106,6 +1137,8 @@ Class CodeDocument Extends Ted2Document
 		
 		
 		If ident = "" Then ident=_codeView.IdentBeforeCursor()
 		If ident = "" Then ident=_codeView.IdentBeforeCursor()
 		
 		
+		Print "ident: "+ident
+		
 		'show
 		'show
 		Local lineNum:=TextDocument.FindLine( _codeView.Cursor )
 		Local lineNum:=TextDocument.FindLine( _codeView.Cursor )
 		Local lineStr:=TextDocument.GetLine( lineNum )
 		Local lineStr:=TextDocument.GetLine( lineNum )
@@ -1145,7 +1178,14 @@ Class CodeDocument Extends Ted2Document
 	End
 	End
 	
 	
 	Function HideAutocomplete()
 	Function HideAutocomplete()
-		If AutoComplete AutoComplete.Hide()
+	
+		AutoComplete?.Hide()
+	End
+	
+	Function HideAllPopups()
+	
+		AutoComplete?.Hide()
+		ParamsHint?.Hide()
 	End
 	End
 	
 	
 	Method GoBack()
 	Method GoBack()
@@ -1296,9 +1336,9 @@ Class CodeDocument Extends Ted2Document
 		Local text:=stringio.LoadString( Path )
 		Local text:=stringio.LoadString( Path )
 		
 		
 		_doc.Text=text
 		_doc.Text=text
+		Dirty=False
 		
 		
-		_parser=ParsersManager.Get( FileExtension )
-		_parsingEnabled=Not ParsersManager.IsFake( _parser )
+		InitParser()
 		
 		
 		ParsingDoc() 'start parsing right after loading, not by timer
 		ParsingDoc() 'start parsing right after loading, not by timer
 		
 		
@@ -1313,7 +1353,7 @@ Class CodeDocument Extends Ted2Document
 	
 	
 	Method OnSave:Bool() Override
 	Method OnSave:Bool() Override
 	
 	
-		ResetErrors()
+		'ResetErrors()
 		
 		
 		Local text:=_doc.Text
 		Local text:=_doc.Text
 		
 		
@@ -1343,7 +1383,7 @@ Class CodeDocument Extends Ted2Document
 	
 	
 	Method OnUpdateCurrentScope()
 	Method OnUpdateCurrentScope()
 		
 		
-		Local scope:=_parser.GetScope( Path,_codeView.LineNumAtCursor+1 )
+		Local scope:=_parser.GetNearestScope( Path,_codeView.LineNumAtCursor+1,True )
 		If scope
 		If scope
 			_treeView.SelectByScope( scope )
 			_treeView.SelectByScope( scope )
 		Endif
 		Endif
@@ -1355,8 +1395,14 @@ Class CodeDocument Extends Ted2Document
 		OnUpdateCurrentScope()
 		OnUpdateCurrentScope()
 	End
 	End
 	
 	
-	Field _timeTextChanged:=0
+	Method InitParser()
+		
+		_parser=ParsersManager.Get( FileExtension )
+		_parsingEnabled=Not ParsersManager.IsFake( _parser )
+	End
+	
 	Field _timeDocParsed:=0
 	Field _timeDocParsed:=0
+	Field _timeTextChanged:=0
 	Method ParsingOnTextChanged()
 	Method ParsingOnTextChanged()
 		
 		
 		If Not _parsingEnabled Return
 		If Not _parsingEnabled Return
@@ -1385,15 +1431,18 @@ Class CodeDocument Extends Ted2Document
 		_parsing=True
 		_parsing=True
 		
 		
 		New Fiber( Lambda()
 		New Fiber( Lambda()
-		
-			Local tmp:=MainWindow.AllocTmpPath( "_mx2cc_parse_",".monkey2" )
-			Local file:=StripDir( Path )
 			
 			
-			SaveString( _doc.Text,tmp )
+			Local dirty:=Dirty
+			
+			Local filePath:=Path
+			If dirty
+				filePath=MainWindow.AllocTmpPath( "_mx2cc_parse_",".monkey2" )
+				SaveString( _doc.Text,filePath )
+			Endif
 			
 			
-			ParsingFile( tmp )
+			ParsingFile( filePath )
 		
 		
-			DeleteFile( tmp )
+			If dirty Then DeleteFile( filePath )
 			
 			
 			_parsing=False
 			_parsing=False
 			
 			
@@ -1409,7 +1458,7 @@ Class CodeDocument Extends Ted2Document
 		
 		
 		ResetErrors()
 		ResetErrors()
 		
 		
-		Local errors:=_parser.ParseFile( Path,pathOnDisk,False )
+		Local errors:=_parser.ParseFile( Path,pathOnDisk,"" )
 		
 		
 		If MainWindow.IsTerminating Return
 		If MainWindow.IsTerminating Return
 		
 		
@@ -1456,6 +1505,207 @@ Class CodeDocument Extends Ted2Document
 		
 		
 	End
 	End
 	
 	
+	Method OnCursorChanged()
+		
+		' try to show hint for method parameters
+		
+		If Not Prefs.EditorShowParamsHint Return
+		
+		Global _storedPos:=-1,_storedIdent:=""
+		Global opts:=New ParserRequestOptions
+		Global results:=New Stack<CodeItem>
+		
+		'If _codeView.CanCopy Print "can copy, exit" ; Return ' has selection
+		
+		Local line:=_codeView.LineTextAtCursor
+		Local pos:=_codeView.PosInLineAtCursor
+		Local lower:=line.Trim().ToLower()
+		Local skip:=lower.StartsWith( "function " ) Or lower.StartsWith( "method " ) Or 
+						lower.StartsWith( "operator " ) Or lower.StartsWith( "property " )
+		If Not skip
+			Local i1:=line.Find( "(" )
+			skip=(i1<0 Or i1>=pos)
+		Endif
+		If skip
+			ParamsHint?.Hide()
+			_storedPos=-1
+			Return
+		Endif
+		
+		Local brackets:=0,quotes:=0
+		Local part:ParamsPart
+		Local parts:=New Stack<ParamsPart>
+		
+		For Local i:=0 Until pos
+			Local c:=line[i]
+			Select c
+				Case Chars.OPENED_ROUND_BRACKET
+					
+					If quotes Mod 2 <> 0 Continue
+					
+					brackets+=1
+					' skip spaces
+					Local j:=i-1
+					While j>=0 And line[j]<=32
+						j-=1
+					Wend
+					j+=1
+					Local pair:=GetIndentBeforePos_Mx2( line,j,True )
+					Local ident:=pair.Item1
+					'Print "ident: "+ident'+", paramIndex: "+paramIndex+", isNew: "+isNew
+					If ident
+						part=New ParamsPart
+						parts.Add( part )
+						part.ident=ident
+						part.ranges=New Stack<Vec2i>
+						part.ranges.Add( New Vec2i( i,0 ) )
+						
+						' check for 'New' keyword
+						j=pair.Item2-1 'where ident starts
+						While j>=0 And line[j]<=32
+							j-=1
+						Wend
+						'j+=1
+						Local s:=""
+						While j>=0 And IsAlpha( line[j] )
+							s=String.FromChar( line[j] )+s
+							j-=1
+						Wend
+						part.isNew=(s.ToLower()="new")
+					Endif
+					
+				Case Chars.CLOSED_ROUND_BRACKET
+					
+					If quotes Mod 2 <> 0 Continue
+					
+					brackets-=1
+					If brackets>0 And brackets<parts.Length
+						part=parts[brackets-1]
+						Local r:=part.current
+						r.y=i
+						part.current=r
+					Endif
+					
+				Case Chars.DOUBLE_QUOTE
+					
+					quotes+=1
+					
+				Case Chars.SINGLE_QUOTE 'comment char
+					
+					If quotes Mod 2 = 0
+						Exit
+					Endif
+					
+				Case Chars.COMMA
+					
+					If quotes Mod 2 = 0 And part<>Null
+						Local r:=part.current
+						r.y=i
+						part.current=r
+						r=New Vec2i( i+1,0 )
+						part.ranges.Add( r )
+						part.index+=1
+					Endif
+					
+			End
+		Next
+		
+		If brackets<=0 Or 	' outside of brackets
+			part=Null 		' found brackets w/o idents - in expressions
+			
+			ParamsHint?.Hide()
+			_storedPos=-1
+			Return
+		Endif
+		
+'		Local i:=brackets-1
+'		While part And _codeView.Keywords.Contains( part.ident )
+'			i-=1
+'			If i>=0
+'				Print "part: "+part.ident+", "+i
+'				part=parts[i]
+'			Else
+'				Return 'exit
+'			Endif
+'		Wend
+		
+		'If ident<>_storedIdent 'Or bracketPos<>_storedPos
+			
+			Local ident:=part.ident
+			Local paramIndex:=part.index
+			Local isNew:=part.isNew
+			
+			_storedIdent=ident
+			'_storedPos=bracketPos
+			
+			opts.ident=ident
+			opts.filePath=Path
+			opts.docLineNum=_codeView.LineNumAtCursor
+			opts.docLineStr=line
+			opts.docPosInLine=pos
+			opts.results=results
+			
+			results.Clear()
+			
+			If isNew
+				
+				Local item:=_parser.GetItem( ident )
+				If item Then _parser.GetConstructors( item,results )
+				
+			Else
+				
+				_parser.GetItemsForAutocomplete( opts )
+				
+				Local parts:=ident.Split( "." )
+				Local last:=parts[parts.Length-1]
+				
+				Local it:=results.All()
+				While Not it.AtEnd
+					If it.Current.Ident<>last
+						it.Erase()
+					Else
+						it.Bump()
+					Endif
+				Wend
+			Endif
+			
+			If results.Empty
+				ParamsHint?.Hide()
+				_storedPos=-1
+				Return
+			Endif
+			
+			If Not ParamsHint Then ParamsHint=New ParamsHintView
+			
+			Local startPos:=_codeView.StartOfLineAtCursor+part.ranges[0].x
+			Local r:=_codeView.CharRect( startPos )
+			Local location:=r.min-_codeView.Scroll
+			location.x+=80*App.Theme.Scale.x
+			
+			ParamsHint.Show( results,location,_codeView )
+			
+		'Else
+		'	Print "the same"
+		'Endif
+		
+		ParamsHint?.SetIndex( paramIndex )
+	End
+	
+	Class ParamsPart
+		
+		Field ident:String
+		Field ranges:=New Stack<Vec2i>
+		Field index:Int
+		Field isNew:Bool
+		
+		Property current:Vec2i()
+			Return ranges[index]
+		Setter( value:Vec2i )
+			ranges[index]=value
+		End
+	End
+	
+	
 	Method OnFindSelection()
 	Method OnFindSelection()
 		MainWindow.OnFind()
 		MainWindow.OnFind()
 	End
 	End
@@ -1511,11 +1761,11 @@ Class CodeDocumentType Extends Ted2DocumentType
 	End
 	End
 	
 	
 	Method OnCreateDocument:Ted2Document( path:String ) Override
 	Method OnCreateDocument:Ted2Document( path:String ) Override
-
+		
 		Return New CodeDocument( path )
 		Return New CodeDocument( path )
 	End
 	End
 	
 	
-		
+	
 	Private
 	Private
 	
 	
 	Global _instance:=New CodeDocumentType
 	Global _instance:=New CodeDocumentType
@@ -1748,3 +1998,145 @@ Function ScaledVal:Int( val:Int )
 	
 	
 	Return val*App.Theme.Scale.x
 	Return val*App.Theme.Scale.x
 End
 End
+
+
+Global ParamsHint:ParamsHintView
+
+Class ParamsHintView Extends TextView
+
+	Method New()
+		
+		Style=GetStyle( "ParamsHint" )
+		ReadOnly=True
+		Visible=False
+		Layout="float"
+		Gravity=New Vec2f( 0,1 )
+		
+		MainWindow.AddChildView( Self )
+		
+		OnThemeChanged()
+	End
+	
+	Method Show( items:Stack<CodeItem>,location:Vec2i,sender:CodeTextView )
+		
+		Hide()
+		
+		_items=items
+		_sender=sender
+		
+		Local s:=""
+		For Local i:=Eachin _items
+			If s Then s+="~n"
+			Local params:=i.Params
+			If Not params Then s+="<no params>" ; Continue
+			For Local j:=0 Until params.Length
+				If j>0 Then s+=", "
+				s+=params[j].ToString()
+			Next
+		Next
+		Text=s ' use it for TextView.OnMeasure
+		
+		Visible=True
+		
+		Local window:=sender.Window
+		
+		location=sender.TransformPointToView( location,window )
+		'Local dy:=New Vec2i( 0,-10 )
+		
+		' fit into window area
+'		Local size:=MeasureLayoutSize()
+'		Local dx:=location.x+size.x-window.Bounds.Right
+'		If dx>0
+'			location=location-New Vec2i( dx,0 )
+'		Endif
+'		If location.y+size.y+dy.y>window.Bounds.Bottom
+'			location=location-New Vec2i( 0,size.y )
+'			'dy=-dy
+'		Endif
+		Offset=location'+dy
+		
+	End
+	
+	Method Hide()
+		
+		Visible=False
+	End
+	
+	Method SetIndex( index:Int )
+		
+		_paramIndex=index
+	End
+	
+	Private
+	
+	Field _items:Stack<CodeItem>
+	Field _paramIndex:Int
+	Field _color1:Color,_color2:Color
+	Field _sender:CodeTextView
+	
+	Method OnRenderContent( canvas:Canvas ) Override
+		
+		Local stored:=canvas.Color
+		
+		Local x:Float,y:Float,s:=""
+		Local font:=RenderStyle.Font
+		For Local item:=Eachin _items
+			
+			Local params:=item.Params
+			If Not params
+				s="<no params>"
+				canvas.Color=(_paramIndex=0) ? _color2 Else _color1
+				canvas.DrawText( s,x,y )
+			Else
+				For Local i:=0 Until params.Length
+					
+					If i>0
+						canvas.Color=_color1
+						canvas.DrawText( ", ",x,y )
+						x+=font.TextWidth( ", " )
+					Endif
+					
+					s=params[i].ToString()
+					canvas.Color=(i=_paramIndex) ? _color2 Else _color1
+					canvas.DrawText( s,x,y )
+					x+=font.TextWidth( s )
+				Next
+				
+			Endif
+			
+			y+=font.Height
+			x=0
+		Next
+		
+		canvas.Color=stored
+	End
+	
+	Method OnThemeChanged() Override
+		
+		_color1=App.Theme.GetColor( "params-hint-common" )
+		_color2=App.Theme.GetColor( "params-hint-selected" )
+	End
+	
+	Method OnContentMouseEvent( event:MouseEvent ) Override
+		
+		If event.Type=EventType.MouseDown
+			
+'			Print App.MouseLocation
+'			Local me:=New MouseEvent( event.Type,_sender,App.MouseLocation,event.Button,event.Wheel,event.Modifiers,event.Clicks )
+'			CodeTextView_Bridge.OnContentMouseEvent( _sender,me )
+			
+			Hide()
+		Endif
+		
+	End
+	
+End
+
+'Class CodeTextView_Bridge Extends CodeTextView Final
+'	
+'	Function OnContentMouseEvent( view:CodeTextView,event:MouseEvent )
+'		
+'		view.OnContentMouseEvent( event )
+'	End
+'	
+'End

+ 54 - 21
document/DocumentManager.monkey2

@@ -87,10 +87,46 @@ Class DocumentManager
 	End
 	End
 	
 	
 	Property OpenDocuments:Ted2Document[]()
 	Property OpenDocuments:Ted2Document[]()
-	
+		
 		Return _openDocs.ToArray()
 		Return _openDocs.ToArray()
 	End
 	End
 	
 	
+	Property CurrentDocumentLabel:String()
+		
+		Return DocumentLabel( CurrentDocument )
+	End
+	
+	Method DocumentLabel:String( doc:Ted2Document )
+		
+		If Not doc Return ""
+		
+		Local label:=StripDir( doc.Path )
+	
+		If ExtractExt( doc.Path ).ToLower()=".monkey2"  label=StripExt( label )
+	
+		label=doc.State+label
+	
+		If doc.Dirty label+="*"
+	
+		Return label
+	End
+	
+	Method UpdateCurrentTabLabel()
+		
+		Local doc:=CurrentDocument
+		If doc _tabView.SetTabText( doc.View,DocumentLabel( doc ) )
+	End
+	
+	Method IsDocumentOpened:Bool( path:String )
+		
+		For Local i:=Eachin _openDocs
+			
+			If i.Path=path Return True
+		Next
+		
+		Return False
+	End
+	
 	Method OpenDocument:Ted2Document( path:String,makeCurrent:Bool=False,openByHand:Bool=True )
 	Method OpenDocument:Ted2Document( path:String,makeCurrent:Bool=False,openByHand:Bool=True )
 	
 	
 		path=RealPath( path )
 		path=RealPath( path )
@@ -110,10 +146,17 @@ Class DocumentManager
 		If Not doc.Load() Return Null
 		If Not doc.Load() Return Null
 
 
 		InitDoc( doc )
 		InitDoc( doc )
-	
-		_openDocs.Add( doc )
+		
 		Local addAtBegin:=(openByHand And Prefs.MainPlaceDocsAtBegin)
 		Local addAtBegin:=(openByHand And Prefs.MainPlaceDocsAtBegin)
-		Local tab:=_tabView.AddTab( TabText( doc ),doc.View,False,addAtBegin )
+		
+		If addAtBegin
+			_openDocs.Insert( 0,doc )
+		Else
+			_openDocs.Add( doc )
+		Endif
+		
+		Local tab:=_tabView.AddTab( DocumentLabel( doc ),doc.View,False,addAtBegin )
+		
 		tab.DoubleClicked+=Lambda()
 		tab.DoubleClicked+=Lambda()
 			DocumentDoubleClicked( doc )
 			DocumentDoubleClicked( doc )
 		End
 		End
@@ -148,12 +191,14 @@ Class DocumentManager
 			Endif
 			Endif
 			
 			
 			Local newDoc:=newType.CreateDocument( newPath )
 			Local newDoc:=newType.CreateDocument( newPath )
-			If Not newDoc.Load() Return Null
+			If Not newDoc.Load()
+				Return Null
+			Endif
 			
 			
 			InitDoc( newDoc )
 			InitDoc( newDoc )
 			
 			
 			_openDocs[i]=newDoc
 			_openDocs[i]=newDoc
-			_tabView.SetTabText( i,TabText( newDoc ) )
+			_tabView.SetTabText( i,DocumentLabel( newDoc ) )
 			_tabView.SetTabView( i,newDoc.View )
 			_tabView.SetTabView( i,newDoc.View )
 			
 			
 			doc.Close()
 			doc.Close()
@@ -163,7 +208,7 @@ Class DocumentManager
 			DocumentAdded( newDoc )
 			DocumentAdded( newDoc )
 			
 			
 			If doc=_currentDoc CurrentDocument=newDoc
 			If doc=_currentDoc CurrentDocument=newDoc
-
+			
 			Return newDoc
 			Return newDoc
 		Next
 		Next
 		
 		
@@ -246,6 +291,7 @@ Class DocumentManager
 	End
 	End
 
 
 	Method Update()
 	Method Update()
+		
 		nextDocument.Enabled=_openDocs.Length>1
 		nextDocument.Enabled=_openDocs.Length>1
 		prevDocument.Enabled=_openDocs.Length>1
 		prevDocument.Enabled=_openDocs.Length>1
 	End
 	End
@@ -301,22 +347,9 @@ Class DocumentManager
 		Endif
 		Endif
 	End
 	End
 	
 	
-	Method TabText:String( doc:Ted2Document )
-	
-		Local label:=StripDir( doc.Path )
-		
-		If ExtractExt( doc.Path ).ToLower()=".monkey2"  label=StripExt( label )
-		
-		label=doc.State+label
-		
-		If doc.Dirty label+="*"
-		
-		Return label
-	End
-	
 	Method UpdateTabLabel( doc:Ted2Document )
 	Method UpdateTabLabel( doc:Ted2Document )
 	
 	
-		If doc _tabView.SetTabText( doc.View,TabText( doc ) )
+		If doc _tabView.SetTabText( doc.View,DocumentLabel( doc ) )
 	End
 	End
 	
 	
 	Method UpdateWindowTitle( doc:Ted2Document )
 	Method UpdateWindowTitle( doc:Ted2Document )

+ 59 - 4
document/JsonDocument.monkey2

@@ -7,12 +7,30 @@ Class JsonDocument Extends Ted2Document
 	Method New( path:String )
 	Method New( path:String )
 		Super.New( path )
 		Super.New( path )
 		
 		
-		_doc=New TextDocument
+		_view=New JsonDocumentView( Self )
 		
 		
-		_view=New TextView( _doc )
+		_doc=_view.Document
 		
 		
 		_browser=New JsonTreeView
 		_browser=New JsonTreeView
-
+		
+		_browser.NodeClicked+=Lambda( node:TreeView.Node )
+			
+			Local i:=FindInText( node,-1 )
+			
+			If i=-1 Return
+			
+			Local from:=Min( _view.Cursor,_view.Anchor )
+			
+			If i=from
+				i=FindInText( node,from )
+				If i=-1 Return
+			Endif
+			
+			Local name:=node.Text.Slice( 0,node.Text.Find( ":" ) )
+			_view.SelectText( i,i+name.Length+2 ) '2 for quotes
+			_view.MakeCentered()
+		End
+		
 		_doc.TextChanged+=Lambda()
 		_doc.TextChanged+=Lambda()
 		
 		
 			_browser.Value=JsonValue.Parse( _doc.Text )
 			_browser.Value=JsonValue.Parse( _doc.Text )
@@ -59,11 +77,38 @@ Class JsonDocument Extends Ted2Document
 	
 	
 	Field _doc:TextDocument
 	Field _doc:TextDocument
 	
 	
-	Field _view:TextView
+	Field _view:JsonDocumentView
 	
 	
 	Field _browser:JsonTreeView
 	Field _browser:JsonTreeView
+	
+	Method FindInText:Int( node:TreeView.Node,fromIndex:Int )
+		
+		Local nodes:=New Stack<TreeView.Node>
+		While node And node.Text.Contains( ":" )
+			If node.Text.Contains( ":[" )
+				' skip array indexing nodes
+				nodes.Erase( 0 )
+			Endif
+			nodes.Insert( 0,node )
+			node=node.Parent
+		Wend
+		
+		Local index:=fromIndex
+		For Local n:=Eachin nodes
+			Local s:=n.Text
+			Local i:=s.Find( ":" )
+			Local name:="~q"+s.Slice( 0,i )+"~q"
+			i=_view.Text.Find( name,index+1 )
+			If i=-1 Return -1
+			index=i
+		Next
+		
+		Return index
+	End
+	
 End
 End
 
 
+
 Class JsonDocumentType Extends Ted2DocumentType
 Class JsonDocumentType Extends Ted2DocumentType
 
 
 	Protected
 	Protected
@@ -84,3 +129,13 @@ Class JsonDocumentType Extends Ted2DocumentType
 	Global _instance:=New JsonDocumentType
 	Global _instance:=New JsonDocumentType
 	
 	
 End
 End
+
+
+Class JsonDocumentView Extends Ted2CodeTextView
+	
+	Method New( doc:Ted2Document )
+		
+		Super.New( doc )
+	End
+	
+End

+ 28 - 22
document/Ted2Document.monkey2

@@ -3,18 +3,22 @@ Namespace ted2go
 
 
 
 
 Class Ted2Document
 Class Ted2Document
-
+	
+	Const Empty:=New Ted2Document("")
+	
 	Field DirtyChanged:Void()
 	Field DirtyChanged:Void()
 	
 	
 	Field StateChanged:Void()
 	Field StateChanged:Void()
 
 
 	Field Closed:Void()
 	Field Closed:Void()
+	
+	Field Renamed:Void( newPath:String,oldPath:String )
 
 
 	Method New( path:String )
 	Method New( path:String )
 	
 	
 		_path=path
 		_path=path
 		_fileExt=ExtractExt( _path )
 		_fileExt=ExtractExt( _path )
-				
+		
 		_modTime=GetFileTime( _path )
 		_modTime=GetFileTime( _path )
 	End
 	End
 	
 	
@@ -23,7 +27,7 @@ Class Ted2Document
 		Return _path
 		Return _path
 	End
 	End
 	
 	
-	Property FileExtension:String()'file extension
+	Property FileExtension:String()
 		
 		
 		Return _fileExt
 		Return _fileExt
 	End
 	End
@@ -106,11 +110,17 @@ Class Ted2Document
 		Return True
 		Return True
 	End
 	End
 
 
-	'DON'T USE YET!	
 	Method Rename( path:String )
 	Method Rename( path:String )
+		
+		If path=_path Return
+		
+		Local old:=_path
 		_path=path
 		_path=path
+		_fileExt=ExtractExt( _path )
 		
 		
 		Dirty=True
 		Dirty=True
+		
+		Renamed( path,old )
 	End
 	End
 	
 	
 	Method Close()
 	Method Close()
@@ -173,11 +183,11 @@ Class Ted2DocumentType Extends Plugin
 		ext=ext.ToLower()
 		ext=ext.ToLower()
 
 
 		Local types:=Plugin.PluginsOfType<Ted2DocumentType>()
 		Local types:=Plugin.PluginsOfType<Ted2DocumentType>()
-		Local defaultType:Ted2DocumentType = Null
+		Local defaultType:Ted2DocumentType=Null
 		
 		
 		For Local type:=Eachin types
 		For Local type:=Eachin types
 		
 		
-			For Local ext2:=Eachin type.Extensions	'Array.Contains() would be nice!
+			For Local ext2:=Eachin type.Extensions
 			
 			
 				If ext=ext2 Return type
 				If ext=ext2 Return type
 				If ext2 = ".*" Then defaultType = type
 				If ext2 = ".*" Then defaultType = type
@@ -185,9 +195,7 @@ Class Ted2DocumentType Extends Plugin
 			
 			
 		Next
 		Next
 		
 		
-		If defaultType <> Null Return defaultType 'use it if there is no registered extension
-		
-		Return Null
+		Return defaultType 'use it if there is no registered extension
 	End
 	End
 	
 	
 	Method CreateDocument:Ted2Document( path:String )
 	Method CreateDocument:Ted2Document( path:String )
@@ -204,25 +212,23 @@ Class Ted2DocumentType Extends Plugin
 	
 	
 	Property Extensions:String[]()
 	Property Extensions:String[]()
 	
 	
-		Return _exts
+		Return _exts.ToArray()
 	
 	
 	Setter( exts:String[] )
 	Setter( exts:String[] )
 	
 	
-		_exts=exts
+		_exts.Clear()
+		_exts.AddAll( exts )
 	End
 	End
 	
 	
 	Method AddExtensions( exts:String[] )
 	Method AddExtensions( exts:String[] )
-		If _exts = Null
-			_exts=exts
-			Return
-		Endif
-		' check  for duplicates here?
-		Local arr:=New String[_exts.Length+exts.Length]
-		_exts.CopyTo( arr,0,0,_exts.Length )
-		exts.CopyTo( arr,0,_exts.Length,exts.Length )
-		_exts=arr
-	End
 		
 		
+		For Local ext:=Eachin exts
+			If Not _exts.Contains( ext )
+				_exts.Add( ext )
+			Endif
+		Next
+	End
+	
 	Method OnCreateDocument:Ted2Document( path:String ) Virtual
 	Method OnCreateDocument:Ted2Document( path:String ) Virtual
 	
 	
 		Return Null	'should return hex editor!
 		Return Null	'should return hex editor!
@@ -230,7 +236,7 @@ Class Ted2DocumentType Extends Plugin
 
 
 	Private
 	Private
 	
 	
-	Field _exts:String[]
+	Field _exts:=New StringStack
 	
 	
 	
 	
 End
 End

+ 1 - 5
eventfilter/Monkey2KeyEventFilter.monkey2

@@ -23,11 +23,7 @@ Class Monkey2KeyEventFilter Extends TextViewKeyEventFilter
 				
 				
 				Case Key.F1
 				Case Key.F1
 					
 					
-					If ctrl
-						MainWindow.ShowFindInDocs()
-					Else
-						MainWindow.ShowQuickHelp()
-					Endif
+					MainWindow.ShowHelp( "",ctrl )
 					event.Eat()
 					event.Eat()
 					
 					
 				Case Key.F2
 				Case Key.F2

BIN
logo/resource_x64.o


+ 28 - 22
parser/CodeItem.monkey2

@@ -35,6 +35,7 @@ End
 Class CodeItem
 Class CodeItem
 	
 	
 	Field nspace:NSpace
 	Field nspace:NSpace
+	Field isAlias:=False
 	
 	
 	Method New( ident:String )
 	Method New( ident:String )
 		_ident=ident
 		_ident=ident
@@ -124,6 +125,11 @@ Class CodeItem
 		
 		
 	End
 	End
 	
 	
+	Property NumChildren:Int()
+		
+		Return _children?.Length
+	End
+	
 	Property Children:Stack<CodeItem>()
 	Property Children:Stack<CodeItem>()
 		Return _children
 		Return _children
 	Setter( value:Stack<CodeItem> )
 	Setter( value:Stack<CodeItem> )
@@ -145,19 +151,13 @@ Class CodeItem
 		_namespace=value
 		_namespace=value
 	End
 	End
 	
 	
-	Property IsModuleMember:Bool()
+	Property ModuleName:String()
 		
 		
-		If _isModuleMember=-1
-			Local p:=_parent
-			While p<>Null
-				_isModuleMember=p._isModuleMember
-				If _isModuleMember<>-1 Exit
-				p=p._parent
-			Wend
-		Endif
-		Return _isModuleMember=1 ? True Else False
-	Setter( value:Bool )
-		_isModuleMember=value ? 1 Else 0
+		Local s:=_modName
+		If Not s Then s=_parent?.ModuleName
+		Return s
+	Setter( value:String )
+		_modName=value
 	End
 	End
 	
 	
 	Property FilePath:String()
 	Property FilePath:String()
@@ -200,13 +200,13 @@ Class CodeItem
 		item.Parent=Self
 		item.Parent=Self
 	End
 	End
 	
 	
-	Property SuperTypes:List<CodeType>()
+	Property SuperTypes:Stack<CodeType>()
 		Return _superTypes
 		Return _superTypes
-	Setter( value:List<CodeType> )
+	Setter( value:Stack<CodeType> )
 		_superTypes=value
 		_superTypes=value
 	End
 	End
 	
 	
-	Property SuperTypesStr:List<String>()
+	Property SuperTypesStr:Stack<String>()
 		Return _superTypesStr
 		Return _superTypesStr
 	End
 	End
 	
 	
@@ -232,14 +232,20 @@ Class CodeItem
 		_isExtension=value
 		_isExtension=value
 	End
 	End
 	
 	
+	Property IsIfaceMember:Bool()
+		Return _isIfaceMember
+	Setter( value:Bool )
+		_isIfaceMember=value
+	End
+	
 	Method AddSuperType( type:CodeType )
 	Method AddSuperType( type:CodeType )
-		If Not _superTypes Then _superTypes=New List<CodeType>
-		_superTypes.AddLast( type )
+		If Not _superTypes Then _superTypes=New Stack<CodeType>
+		_superTypes.Add( type )
 	End
 	End
 	
 	
 	Method AddSuperTypeStr( type:String )
 	Method AddSuperTypeStr( type:String )
-		If Not _superTypesStr Then _superTypesStr=New List<String>
-		_superTypesStr.AddLast( type )
+		If Not _superTypesStr Then _superTypesStr=New Stack<String>
+		_superTypesStr.Add( type )
 	End
 	End
 	
 	
 	Method FindParent:CodeItem( parentIdent:String )
 	Method FindParent:CodeItem( parentIdent:String )
@@ -309,12 +315,12 @@ Class CodeItem
 	Field _namespace:String
 	Field _namespace:String
 	Field _filePath:String
 	Field _filePath:String
 	Field _scopeStartPos:Vec2i=New Vec2i,_scopeEndPos:Vec2i=New Vec2i
 	Field _scopeStartPos:Vec2i=New Vec2i,_scopeEndPos:Vec2i=New Vec2i
-	Field _superTypes:List<CodeType>,_superTypesStr:List<String>
+	Field _superTypes:Stack<CodeType>,_superTypesStr:Stack<String>
 	Field _params:CodeParam[]
 	Field _params:CodeParam[]
 	Field _paramsStr:String
 	Field _paramsStr:String
-	Field _isModuleMember:=-1
 	Field _isExtension:Bool
 	Field _isExtension:Bool
-	
+	Field _isIfaceMember:Bool
+	Field _modName:String
 	
 	
 	Private
 	Private
 	
 	

+ 132 - 46
parser/Monkey2Parser.monkey2

@@ -90,11 +90,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 		Return True
 		Return True
 	End
 	End
 	
 	
-	Method ParseFile:String( filePath:String,pathOnDisk:String,isModule:Bool )
-		
-		If Not isModule
-			isModule=filePath.StartsWith( _modsPath )
-		Endif
+	Method ParseFile:String( filePath:String,pathOnDisk:String,moduleName:String )
 		
 		
 		' is file modified?
 		' is file modified?
 		Local time:=GetFileTime( pathOnDisk )
 		Local time:=GetFileTime( pathOnDisk )
@@ -111,7 +107,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 		Endif
 		Endif
 		
 		
 		' start parsing process
 		' start parsing process
-		Local str:=StartParsing( pathOnDisk,isModule )
+		Local str:=StartParsing( pathOnDisk )
 		
 		
 		If Not str Return "#" 'special kind of error
 		If Not str Return "#" 'special kind of error
 		
 		
@@ -138,7 +134,6 @@ Class Monkey2Parser Extends CodeParserPlugin
 		
 		
 		Local nspace:= jobj.Contains( "namespace" ) ? jobj["namespace"].ToString() Else ""
 		Local nspace:= jobj.Contains( "namespace" ) ? jobj["namespace"].ToString() Else ""
 		
 		
-		
 		If jobj.Contains( "members" )
 		If jobj.Contains( "members" )
 			Local items:=New Stack<CodeItem>
 			Local items:=New Stack<CodeItem>
 			Local members:=jobj["members"].ToArray()
 			Local members:=jobj["members"].ToArray()
@@ -147,7 +142,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 			Items.AddAll( items )
 			Items.AddAll( items )
 			
 			
 			For Local i:=Eachin items
 			For Local i:=Eachin items
-				i.IsModuleMember=isModule
+				i.ModuleName=moduleName
 				NSpace.AddItem( nspace,i )
 				NSpace.AddItem( nspace,i )
 			Next
 			Next
 			'Print "file parsed: "+filePath+", items.count: "+items.Count()
 			'Print "file parsed: "+filePath+", items.count: "+items.Count()
@@ -169,7 +164,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 				Endif
 				Endif
 				file=folder+file
 				file=folder+file
 				'Print "parse import: "+file+"  mod: "+Int(isModule)
 				'Print "parse import: "+file+"  mod: "+Int(isModule)
-				ParseFile( file,file,isModule )
+				ParseFile( file,file,moduleName )
 			Next
 			Next
 		Endif
 		Endif
 		
 		
@@ -221,7 +216,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 			arr=endPos.Split( ":" )
 			arr=endPos.Split( ":" )
 			item.ScopeEndPos=New Vec2i( Int(arr[0])-1,Int(arr[1]) )
 			item.ScopeEndPos=New Vec2i( Int(arr[0])-1,Int(arr[1]) )
 			item.Namespac=namespac
 			item.Namespac=namespac
-			
+			item.IsIfaceMember=(flags & Flags.DECL_IFACEMEMBER <> 0)
 			'Print "parser. add item: "+item.Scope+" "+kind
 			'Print "parser. add item: "+item.Scope+" "+kind
 			
 			
 			If kind="class" Or kind="struct" Or kind="interface" Or kind="enum"
 			If kind="class" Or kind="struct" Or kind="interface" Or kind="enum"
@@ -254,6 +249,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 				' alias
 				' alias
 				If kind = "alias"
 				If kind = "alias"
 					_aliases.Add( ident,item )
 					_aliases.Add( ident,item )
+					item.isAlias=True
 				End
 				End
 				
 				
 			Endif
 			Endif
@@ -263,6 +259,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 				Local supIdent:=sup["ident"]
 				Local supIdent:=sup["ident"]
 				If supIdent Then item.AddSuperTypeStr( supIdent.ToString() )
 				If supIdent Then item.AddSuperTypeStr( supIdent.ToString() )
 			Endif
 			Endif
+			
 			If jobj.Contains( "ifaceTypes" )
 			If jobj.Contains( "ifaceTypes" )
 				Local ifaces:=jobj["ifaceTypes"].ToArray()
 				Local ifaces:=jobj["ifaceTypes"].ToArray()
 				For Local ifaceType:=Eachin ifaces
 				For Local ifaceType:=Eachin ifaces
@@ -272,7 +269,6 @@ Class Monkey2Parser Extends CodeParserPlugin
 				Next
 				Next
 			Endif
 			Endif
 			
 			
-			
 			If parent
 			If parent
 				item.SetParent( parent )
 				item.SetParent( parent )
 				If parent.IsExtension
 				If parent.IsExtension
@@ -318,7 +314,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 		Next
 		Next
 		
 		
 		If result
 		If result
-			' try to check is we inside of method/ property / etc
+			' try to check - are we inside of method/ property / etc
 			Repeat
 			Repeat
 				Local i:=GetInnerScope( result,docLine )
 				Local i:=GetInnerScope( result,docLine )
 				If i = Null Exit
 				If i = Null Exit
@@ -343,6 +339,50 @@ Class Monkey2Parser Extends CodeParserPlugin
 		
 		
 	End
 	End
 	
 	
+	Method GetNearestScope:CodeItem( docPath:String,docLine:Int,above:Bool )
+	
+		Local items:=ItemsMap[docPath]
+	
+		If Not items Return Null
+	
+		' all classes / structs
+		Local fakeItem:=New CodeItem( "fake" )
+		fakeItem.Children=items
+'		For Local i:=Eachin items
+'			If docLine > i.ScopeStartPos.x And docLine < i.ScopeEndPos.x
+'				result=i
+'				Exit
+'			Endif
+'		Next
+		Local dir:=above ? -1 Else 1
+		Local result:=GetInnerScope( fakeItem,docLine )
+		
+		If result
+			' try to check - are we inside of method/ property / etc
+			Repeat
+				Local i:=GetInnerScope( result,docLine,dir )
+				If i = Null Exit
+				result=i
+			Forever
+	
+		Else
+			' try to find in extension members
+			For Local list:=Eachin ExtraItemsMap.Values
+				For Local i:=Eachin list
+					If i.FilePath<>docPath Continue
+					If docLine > i.ScopeStartPos.x And docLine < i.ScopeEndPos.x
+						result=i
+						Exit
+					Endif
+				Next
+				If result Exit
+			Next
+		End
+	
+		Return result
+	
+	End
+	
 	Method ItemAtScope:CodeItem( ident:String,filePath:String,docLine:Int )
 	Method ItemAtScope:CodeItem( ident:String,filePath:String,docLine:Int )
 		
 		
 		Local opts:=New ParserRequestOptions
 		Local opts:=New ParserRequestOptions
@@ -351,7 +391,10 @@ Class Monkey2Parser Extends CodeParserPlugin
 		opts.filePath=filePath
 		opts.filePath=filePath
 		opts.docLineNum=docLine
 		opts.docLineNum=docLine
 		opts.usingsFilter=_lastUsingsFilter
 		opts.usingsFilter=_lastUsingsFilter
+		opts.intelliIdent=False
+		
 		GetItemsInternal( opts,1 )
 		GetItemsInternal( opts,1 )
+		
 		Return (Not opts.results.Empty) ? opts.results[0] Else Null
 		Return (Not opts.results.Empty) ? opts.results[0] Else Null
 	End
 	End
 	
 	
@@ -363,6 +406,9 @@ Class Monkey2Parser Extends CodeParserPlugin
 		For Local i:=Eachin Items
 		For Local i:=Eachin Items
 			If i.Ident=ident Return i
 			If i.Ident=ident Return i
 		Next
 		Next
+		For Local i:=Eachin _aliases.Values
+			If i.Ident=ident Return i
+		Next
 		Return Null
 		Return Null
 	End
 	End
 	
 	
@@ -371,6 +417,33 @@ Class Monkey2Parser Extends CodeParserPlugin
 		GetItemsInternal( options )
 		GetItemsInternal( options )
 	End
 	End
 	
 	
+	Method GetConstructors( item:CodeItem,target:Stack<CodeItem> )
+		
+		If item.isAlias
+			Local type:=item.Type?.ident
+			item=Self[type]
+			If Not item Return
+		Endif
+		
+		If Not item.IsLikeClass Print "not a class" ; Return
+		
+		If item.Children
+			For Local i:=Eachin item.Children
+		
+				If i.Ident.ToLower()="new"
+					target+=i
+				Endif
+			Next
+		Endif
+		
+'		If _superTypes
+'			For Local i:=Eachin _superTypes
+'		
+'			Next
+'		Endif
+		
+	End
+	
 	
 	
 	Private
 	Private
 	
 	
@@ -395,6 +468,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 		Local docLineStr:=options.docLineStr
 		Local docLineStr:=options.docLineStr
 		Local target:=options.results
 		Local target:=options.results
 		Local usingsFilter:=options.usingsFilter
 		Local usingsFilter:=options.usingsFilter
+		Local intelliIdent:=options.intelliIdent
 		
 		
 		_lastUsingsFilter=usingsFilter
 		_lastUsingsFilter=usingsFilter
 		
 		
@@ -442,7 +516,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 					
 					
 					For Local i:=Eachin items
 					For Local i:=Eachin items
 						'Print "item at scope: "+i.Text
 						'Print "item at scope: "+i.Text
-						If Not CheckIdent( i.Ident,firstIdent,onlyOne )
+						If Not CheckIdent( i.Ident,firstIdent,onlyOne,intelliIdent )
 							'Print "cont1: "+i.Ident
 							'Print "cont1: "+i.Ident
 							Continue
 							Continue
 						Endif
 						Endif
@@ -513,7 +587,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 					Endif
 					Endif
 					
 					
 					'Print "global 1: "+i.Scope
 					'Print "global 1: "+i.Scope
-					If Not CheckIdent( i.Ident,firstIdent,onlyOne )
+					If Not CheckIdent( i.Ident,firstIdent,onlyOne,intelliIdent )
 						'Print "skip 2 "+i.Ident
 						'Print "skip 2 "+i.Ident
 						Continue
 						Continue
 					Endif
 					Endif
@@ -678,7 +752,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 						' skip constructors
 						' skip constructors
 						If Not (isSelf Or isSuper) And i.Kind=CodeItemKind.Method_ And i.Ident="New" Continue
 						If Not (isSelf Or isSuper) And i.Kind=CodeItemKind.Method_ And i.Ident="New" Continue
 						
 						
-						If Not CheckIdent( i.Ident,identPart,last )
+						If Not CheckIdent( i.Ident,identPart,last,intelliIdent )
 							'Print "continue 1: "+i.Ident
 							'Print "continue 1: "+i.Ident
 							Continue
 							Continue
 						Endif
 						Endif
@@ -767,7 +841,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 		Endif
 		Endif
 	End
 	End
 	
 	
-	Method StartParsing:String( pathOnDisk:String,isModule:Bool )
+	Method StartParsing:String( pathOnDisk:String )
 		
 		
 		If Not _enabled Return ""
 		If Not _enabled Return ""
 		
 		
@@ -793,12 +867,12 @@ Class Monkey2Parser Extends CodeParserPlugin
 		Next
 		Next
 		
 		
 		For Local d:=Eachin dirs
 		For Local d:=Eachin dirs
-			If GetFileType( _modsPath+d ) = FileType.Directory
+			If GetFileType( _modsPath+d )=FileType.Directory
 				Local file:=_modsPath + d + "/" + d + ".monkey2"
 				Local file:=_modsPath + d + "/" + d + ".monkey2"
 				'Print "module: "+file
 				'Print "module: "+file
-				If GetFileType( file ) = FileType.File
+				If GetFileType( file )=FileType.File
 					OnParseModule( file )
 					OnParseModule( file )
-					ParseFile( file,file,True )
+					ParseFile( file,file,d )
 				Endif
 				Endif
 			Endif
 			Endif
 		Next
 		Next
@@ -991,15 +1065,44 @@ Class Monkey2Parser Extends CodeParserPlugin
 		Return type
 		Return type
 	End
 	End
 	
 	
-	Method GetInnerScope:CodeItem( parent:CodeItem,docLine:Int )
+	Method GetInnerScope:CodeItem( parent:CodeItem,docLine:Int,dir:Int=0 )
 		
 		
 		Local items:=parent.Children
 		Local items:=parent.Children
-		If items = Null Return Null
+		If items=Null Return Null
+		
+		Local result:CodeItem=Null
+		Local storedPos:=dir>0 ? 999999999 Else -1
 		For Local i:=Eachin items
 		For Local i:=Eachin items
-			If docLine > i.ScopeStartPos.x And docLine < i.ScopeEndPos.x Return i
+			
+			If i.Kind=CodeItemKind.Param_ Continue
+			
+			Local i1:=i.ScopeStartPos.x
+			Local i2:=i.ScopeEndPos.x
+			
+			'inside
+			If docLine>i1 And docLine<=i2
+				result=i
+				Exit
+			Endif
+			
+			If dir=-1 ' above
+				
+				If docLine>i2 And i2>storedPos
+					result=i
+					storedPos=i2
+				Endif
+				
+			Elseif dir=1 ' below
+				
+				If docLine<i1 And i1<storedPos
+					result=i
+					storedPos=i1
+				Endif
+				
+			End
+			
 		Next
 		Next
-		Return Null
-		
+		Return result
 	End
 	End
 	
 	
 	Function CheckUsingsFilter:Bool( nspace:String,usingsFilter:StringStack )
 	Function CheckUsingsFilter:Bool( nspace:String,usingsFilter:StringStack )
@@ -1143,12 +1246,12 @@ Class Monkey2Parser Extends CodeParserPlugin
 		
 		
 	End
 	End
 	
 	
-	Method CheckIdent:Bool( ident1:String,ident2:String,startsOnly:Bool,smartStarts:Bool=True )
+	Method CheckIdent:Bool( ident1:String,ident2:String,startsOnly:Bool,intelliIdent:Bool=True )
 	
 	
-		If ident2 = "" Return True
+		If ident2="" Return True
 		
 		
 		If startsOnly
 		If startsOnly
-			Return smartStarts ? CheckStartsWith( ident1,ident2 ) Else ident1.StartsWith( ident2 )
+			Return intelliIdent ? CheckStartsWith( ident1,ident2 ) Else ident1.StartsWith( ident2 )
 		Else
 		Else
 			Return ident1 = ident2
 			Return ident1 = ident2
 		Endif
 		Endif
@@ -1213,25 +1316,7 @@ Class Monkey2Parser Extends CodeParserPlugin
 	
 	
 	Method IsPosInsideOfQuotes:Bool( text:String,pos:Int )
 	Method IsPosInsideOfQuotes:Bool( text:String,pos:Int )
 	
 	
-		Local i:=0
-		Local n:=text.Length
-		if pos = 0 Return False
-		Local quoteCounter:=0
-		While i < n
-			Local c:=text[i]
-			If i = pos
-				If quoteCounter Mod 2 = 0 'not inside of string
-					Return False
-				Else 'inside
-					Return True
-				Endif 
-			Endif
-			If c = Chars.DOUBLE_QUOTE
-				quoteCounter+=1
-			Endif
-			i+=1
-		Wend
-		Return (quoteCounter Mod 2 <> 0)
+		Return IsPosInsideOfQuotes_Mx2( text,pos )
 	End
 	End
 	
 	
 	Method RemovePrevious( path:String )
 	Method RemovePrevious( path:String )
@@ -1258,6 +1343,7 @@ Struct Chars
 	Const SINGLE_QUOTE:="'"[0] '39
 	Const SINGLE_QUOTE:="'"[0] '39
 	Const DOUBLE_QUOTE:="~q"[0] '34
 	Const DOUBLE_QUOTE:="~q"[0] '34
 	Const COMMA:=","[0] '44
 	Const COMMA:=","[0] '44
+	Const SEMICOLON:=";"[0]
 	Const DOT:="."[0] '46
 	Const DOT:="."[0] '46
 	Const EQUALS:="="[0] '61
 	Const EQUALS:="="[0] '61
 	Const LESS_BRACKET:="<"[0] '60
 	Const LESS_BRACKET:="<"[0] '60

+ 11 - 3
parser/Parser.monkey2

@@ -3,13 +3,15 @@ Namespace ted2go
 
 
 
 
 Interface ICodeParser
 Interface ICodeParser
-
+	
+	Method GetConstructors( item:CodeItem,target:Stack<CodeItem> )
 	Method RefineRawType( item:CodeItem )
 	Method RefineRawType( item:CodeItem )
-	Method ParseFile:String( filePath:String,pathOnDisk:String,isModule:Bool )
+	Method ParseFile:String( filePath:String,pathOnDisk:String,moduleName:String )
 	'Method ParseJson( json:String,filePath:String )
 	'Method ParseJson( json:String,filePath:String )
 	Method IsPosInsideOfQuotes:Bool( text:String,pos:Int )
 	Method IsPosInsideOfQuotes:Bool( text:String,pos:Int )
 	Method CanShowAutocomplete:Bool( line:String,posInLine:Int )
 	Method CanShowAutocomplete:Bool( line:String,posInLine:Int )
 	Method GetScope:CodeItem( docPath:String,docLine:Int )
 	Method GetScope:CodeItem( docPath:String,docLine:Int )
+	Method GetNearestScope:CodeItem( docPath:String,docLine:Int,above:Bool )
 	Method ItemAtScope:CodeItem( ident:String,filePath:String,docLine:Int )
 	Method ItemAtScope:CodeItem( ident:String,filePath:String,docLine:Int )
 	
 	
 	Method GetItemsForAutocomplete( options:ParserRequestOptions )
 	Method GetItemsForAutocomplete( options:ParserRequestOptions )
@@ -73,6 +75,7 @@ Class ParserRequestOptions Final
 	Field usingsFilter:Stack<String>
 	Field usingsFilter:Stack<String>
 	Field docLineStr:String
 	Field docLineStr:String
 	Field docPosInLine:Int
 	Field docPosInLine:Int
+	Field intelliIdent:=True
 	
 	
 End
 End
 
 
@@ -97,7 +100,9 @@ Class FakeParser Implements ICodeParser
 		Return _extraItemsMap
 		Return _extraItemsMap
 	End
 	End
 	
 	
-	Method ParseFile:String( filePath:String,pathOnDisk:String,isModule:Bool )
+	Method GetConstructors( item:CodeItem,target:Stack<CodeItem> )
+	End
+	Method ParseFile:String( filePath:String,pathOnDisk:String,moduleName:String )
 		'do nothing
 		'do nothing
 		Return Null
 		Return Null
 	End
 	End
@@ -110,6 +115,9 @@ Class FakeParser Implements ICodeParser
 	Method GetScope:CodeItem( docPath:String,docLine:Int )
 	Method GetScope:CodeItem( docPath:String,docLine:Int )
 		Return Null
 		Return Null
 	End
 	End
+	Method GetNearestScope:CodeItem( docPath:String,docLine:Int,above:Bool )
+		Return Null
+	End
 	Method ItemAtScope:CodeItem( ident:String,filePath:String,docLine:Int )
 	Method ItemAtScope:CodeItem( ident:String,filePath:String,docLine:Int )
 		Return Null
 		Return Null
 	End
 	End

+ 3 - 1
product/BuildProduct.monkey2

@@ -384,6 +384,8 @@ Class MacosProduct Extends DesktopProduct
 		plist+="<!DOCTYPE plist PUBLIC ~q-//Apple Computer//DTD PLIST 1.0//EN~q ~qhttp://www.apple.com/DTDs/PropertyList-1.0.dtd~q>~n"
 		plist+="<!DOCTYPE plist PUBLIC ~q-//Apple Computer//DTD PLIST 1.0//EN~q ~qhttp://www.apple.com/DTDs/PropertyList-1.0.dtd~q>~n"
 		plist+="<plist version=~q1.0~q>~n"
 		plist+="<plist version=~q1.0~q>~n"
 		plist+="<dict>~n"
 		plist+="<dict>~n"
+		plist+="~t<key>CFBundleName</key>~n"
+		plist+="~t<string>"+AppName+"</string>~n"
 		plist+="~t<key>CFBundleExecutable</key>~n"
 		plist+="~t<key>CFBundleExecutable</key>~n"
 		plist+="~t<string>"+AppName+"</string>~n"
 		plist+="~t<string>"+AppName+"</string>~n"
 		plist+="~t<key>CFBundleIconFile</key>~n"
 		plist+="~t<key>CFBundleIconFile</key>~n"
@@ -476,7 +478,7 @@ Class AndroidProduct Extends BuildProduct
 	Method New( srcPath:String )
 	Method New( srcPath:String )
 		Super.New( srcPath,"android" )
 		Super.New( srcPath,"android" )
 		
 		
-		AddExts( New String[]( ".xml",".java",".gradle" ) )
+		AddExts( New String[]( ".xml",".java",".gradle",".name" ) )
 		
 		
 		AddVar( "Package Name","com.monkey2.monkey2game" )
 		AddVar( "Package Name","com.monkey2.monkey2game" )
 		AddVar( "Activity Name","Monkey2Game" )
 		AddVar( "Activity Name","Monkey2Game" )

+ 50 - 40
product/ModuleManager.monkey2

@@ -5,6 +5,7 @@ Namespace ted2go
 Private
 Private
 
 
 Class Module
 Class Module
+	Field dir:String
 	Field name:String
 	Field name:String
 	Field about:String
 	Field about:String
 	Field author:String
 	Field author:String
@@ -146,7 +147,8 @@ Class ModuleManager Extends Dialog
 		
 		
 		For Local module:=Eachin _procmods
 		For Local module:=Eachin _procmods
 		
 		
-			Local src:="modules/"+module.name
+'			Local src:="modules/"+module.name
+			Local src:=module.dir+module.name
 			Local dst:=backupDir+module.name
 			Local dst:=backupDir+module.name
 			
 			
 			Select GetFileType( src )
 			Select GetFileType( src )
@@ -169,7 +171,8 @@ Class ModuleManager Extends Dialog
 		For Local module:=Eachin _procmods
 		For Local module:=Eachin _procmods
 		
 		
 			Local src:=backupDir+module.name
 			Local src:=backupDir+module.name
-			Local dst:="modules/"+module.name
+'			Local dst:="modules/"+module.name
+			Local dst:=module.dir+module.name
 			
 			
 			Select GetFileType( src )
 			Select GetFileType( src )
 			Case FileType.Directory
 			Case FileType.Directory
@@ -236,12 +239,14 @@ Class ModuleManager Extends Dialog
 			Local zip:=module.name+"-v"+module.new_version+".zip"
 			Local zip:=module.name+"-v"+module.new_version+".zip"
 			Local dst:=downloadDir+zip
 			Local dst:=downloadDir+zip
 			
 			
-			If Not DeleteDir( "modules/"+module.name,True )
+'			If Not DeleteDir( "modules/"+module.name,True )
+			If Not DeleteDir( module.dir+module.name,True )
 				Alert( "Error deleting module directory '"+module.name+"'" )
 				Alert( "Error deleting module directory '"+module.name+"'" )
 				Return False
 				Return False
 			End
 			End
 		
 		
-			If Not ExtractZip( dst,"modules",module.name+"/" )
+'			If Not ExtractZip( dst,"modules",module.name+"/" )
+			If Not ExtractZip( dst,module.dir,module.name+"/" )
 				Alert( "Error extracting zip to '"+dst+"'" )
 				Alert( "Error extracting zip to '"+dst+"'" )
 				Return False
 				Return False
 			Endif
 			Endif
@@ -356,7 +361,7 @@ Class ModuleManager Extends Dialog
 		Endif
 		Endif
 		
 		
 		
 		
-		App.EndModal()		
+		App.EndModal()
 		
 		
 		_progress.Close()
 		_progress.Close()
 		
 		
@@ -483,6 +488,7 @@ Class ModuleManager Extends Dialog
 				Endif
 				Endif
 			Else
 			Else
 				module=New Module
 				module=New Module
+				module.dir=ModuleDirs[0]
 				module.version=version
 				module.version=version
 				module.new_version=version
 				module.new_version=version
 				module.status="Uninstalled"
 				module.status="Uninstalled"
@@ -502,44 +508,48 @@ Class ModuleManager Extends Dialog
 	End
 	End
 	
 	
 	Method EnumLocalModules()
 	Method EnumLocalModules()
-	
-		For Local f:=Eachin LoadDir( "modules" )
 		
 		
-			Local dir:="modules/"+f+"/"
-			If GetFileType( dir )<>FileType.Directory Continue
-			
-			Local str:=LoadString( dir+"module.json" )
-			If Not str Continue
-			
-			Local obj:=JsonObject.Parse( str )
-			If Not obj Continue
-			
-			Local jname:=obj["module"]
-			If Not jname Or Not Cast<JsonString>( jname ) Continue
-			
-			Local jabout:=obj["about"]
-			If Not jabout Or Not Cast<JsonString>( jabout ) Continue
-			
-			Local jauthor:=obj["author"]
-			If Not jauthor Or Not Cast<JsonString>( jauthor ) Continue
-			
-			Local jversion:=obj["version"]
-			If Not jversion Or Not Cast<JsonString>( jversion ) Continue
-			
-			Local name:=jname.ToString()
-			Local about:=jabout.ToString()
-			Local author:=jauthor.ToString()
-			Local version:=jversion.ToString()
+		For Local moddir:=Eachin ModuleDirs
+	
+			For Local f:=Eachin LoadDir( moddir )
 			
 			
-			Local module:=New Module
-			module.name=name
-			module.about=about
-			module.author=author
-			module.version=version
-			module.status="Local"
+				Local dir:=moddir+f+"/"
+				If GetFileType( dir )<>FileType.Directory Continue
+				
+				Local str:=LoadString( dir+"module.json" )
+				If Not str Continue
+				
+				Local obj:=JsonObject.Parse( str )
+				If Not obj Continue
+				
+				Local jname:=obj["module"]
+				If Not jname Or Not Cast<JsonString>( jname ) Continue
+				
+				Local jabout:=obj["about"]
+				If Not jabout Or Not Cast<JsonString>( jabout ) Continue
+				
+				Local jauthor:=obj["author"]
+				If Not jauthor Or Not Cast<JsonString>( jauthor ) Continue
+				
+				Local jversion:=obj["version"]
+				If Not jversion Or Not Cast<JsonString>( jversion ) Continue
+				
+				Local name:=jname.ToString()
+				Local about:=jabout.ToString()
+				Local author:=jauthor.ToString()
+				Local version:=jversion.ToString()
+				
+				Local module:=New Module
+				module.dir=moddir
+				module.name=name
+				module.about=about
+				module.author=author
+				module.version=version
+				module.status="Local"
+				
+				_modules[name]=module
 			
 			
-			_modules[name]=module
-		
+			Next
 		Next
 		Next
 	End
 	End
 
 

+ 14 - 2
product/Mx2ccEnv.monkey2

@@ -1,6 +1,7 @@
 
 
 Namespace ted2go
 Namespace ted2go
 
 
+Global ModuleDirs:String[]
 
 
 Function GetEnv:String( name:String )
 Function GetEnv:String( name:String )
 
 
@@ -51,6 +52,8 @@ Function ReplaceEnv:String( str:String,lineid:Int )
 	Return str
 	Return str
 End
 End
 
 
+Public
+
 Function LoadEnv()
 Function LoadEnv()
 
 
 	Local path:="bin/env_"+HostOS+".txt"
 	Local path:="bin/env_"+HostOS+".txt"
@@ -79,10 +82,19 @@ Function LoadEnv()
 		
 		
 		SetEnv( name,value )
 		SetEnv( name,value )
 	Next
 	Next
+	
+	Local moddirs:=New StringStack
+	moddirs.Add( CurrentDir()+"modules/" )
+	For Local moddir:=Eachin GetEnv( "MX2_MODULE_DIRS" ).Split( ";" )
+		moddir=moddir.Replace( "\","/" )
+		If GetFileType( moddir )<>FileType.Directory Continue
+		moddir=RealPath( moddir )
+		If Not moddir.EndsWith( "/" ) moddir+="/"
+		If Not moddirs.Contains( moddir ) moddirs.Add( moddir )
+	Next
+	ModuleDirs=moddirs.ToArray()
 End
 End
 
 
-Public
-
 Function EnumValidTargets:StringStack( console:ConsoleExt )
 Function EnumValidTargets:StringStack( console:ConsoleExt )
 
 
 	LoadEnv()
 	LoadEnv()

+ 2 - 2
syntax/Monkey2Highlighter.monkey2

@@ -15,7 +15,7 @@ Class Monkey2Highlighter Extends HighlighterPlugin
 	
 	
 	Method New()
 	Method New()
 		Super.New()
 		Super.New()
-		_types=New String[](".monkey2")
+		_types=New String[]( ".monkey2",".json" )
 		_hl=New Highlighter
 		_hl=New Highlighter
 		_hl.Painter=HL
 		_hl.Painter=HL
 	End
 	End
@@ -121,7 +121,7 @@ Class Monkey2Highlighter Extends HighlighterPlugin
 				If preproc And istart=sol
 				If preproc And istart=sol
 				
 				
 					Select id.ToLower()
 					Select id.ToLower()
-					Case "rem"				
+					Case "rem"
 						cnest+=1
 						cnest+=1
 					Case "end"
 					Case "end"
 						cnest=Max( cnest-1,-1 )
 						cnest=Max( cnest-1,-1 )

+ 11 - 0
testing/ParserTests.monkey2

@@ -43,6 +43,17 @@ Interface ITest
 	
 	
 End
 End
 
 
+Class c123 Implements ITest
+	
+	Method abs()
+	End
+End
+
+Class c456 Extends c123
+	
+'	Method abs()' Override
+'	End
+End
 
 
 '0000000000000000000000000000000
 '0000000000000000000000000000000
 '0000000000000000000000000000000
 '0000000000000000000000000000000

+ 86 - 0
testing/pixelPerfect.json

@@ -0,0 +1,86 @@
+{
+	"Object2D":{
+		"Class":"game3d.GameObject",
+		"Components":[{
+			"Animation":"WalkRight",
+			"Class":"game3d.SpriteAnim",
+			"Enabled":true,
+			"Frame":0,
+			"FrameOffset":0,
+			"FrameRate":20,
+			"Name":"SpriteAnim",
+			"animationPath":"asset::blob.json",
+			"border":0,
+			"cellHeight":16,
+			"cellWidth":16,
+			"defaultAnimation":"WalkRight",
+			"flags":0,
+			"padding":0,
+			"path":"asset::blob.png"
+		},{
+			"Class":"game3d.SinePosition",
+			"Enabled":true,
+			"Name":"SinePosition",
+			"period":0.5,
+			"x":16,
+			"y":16,
+			"z":0
+		}],
+		"Name":"Object2D",
+		"Parent":"",
+		"Position":[0,0,0],
+		"Rotation":[-0,-0,0],
+		"Scale":[16,16,1],
+		"Visible":true,
+		"timeOffset":0
+	},
+	"camera":{
+		"Class":"game3d.GameObject",
+		"Components":[{
+			"AmbientLight":[1,1,1,1],
+			"Class":"game3d.CameraComponent",
+			"ClearColor":[0.30000001192092896,0.30000001192092896,0.30000001192092896,1],
+			"Enabled":true,
+			"EnvColor":[0,0,0,1],
+			"FOV":45,
+			"Far":1000,
+			"FogColor":[0,0,0,0],
+			"Name":"CameraComponent",
+			"Near":0.10000000149011612
+		}],
+		"Name":"camera",
+		"Parent":"",
+		"Position":[0,0,-217.27922058105469],
+		"Rotation":[-0,-0,0],
+		"Scale":[1,1,1],
+		"Visible":true,
+		"timeOffset":0
+	},
+	"checkerboard":{
+		"Class":"game3d.GameObject",
+		"Components":[{
+			"Animation":"",
+			"Class":"game3d.SpriteAnim",
+			"Enabled":true,
+			"Frame":0,
+			"FrameOffset":0,
+			"FrameRate":15,
+			"Name":"SpriteAnim",
+			"animationPath":"",
+			"border":0,
+			"cellHeight":180,
+			"cellWidth":320,
+			"defaultAnimation":"",
+			"flags":0,
+			"padding":0,
+			"path":"asset::checkerboard.png"
+		}],
+		"Name":"checkerboard",
+		"Parent":"",
+		"Position":[0,0,217.27922058105469],
+		"Rotation":[-0,-0,0],
+		"Scale":[640,360,1],
+		"Visible":true,
+		"timeOffset":0
+	}
+}

+ 5 - 4
utils/JsonUtils.monkey2

@@ -40,23 +40,24 @@ End
 
 
 Function Json_GetBool:Bool( json:Map<String,JsonValue>,key:String,def:Bool )
 Function Json_GetBool:Bool( json:Map<String,JsonValue>,key:String,def:Bool )
 	
 	
-	Return json[key] ? json[key].ToBool() Else def
+	Return json.Contains( key ) ? json[key].ToBool() Else def
 End
 End
 
 
 Function Json_GetString:String( json:Map<String,JsonValue>,key:String,def:String )
 Function Json_GetString:String( json:Map<String,JsonValue>,key:String,def:String )
 	
 	
-	Return json[key] ? json[key].ToString() Else def
+	Return json.Contains( key ) ? json[key].ToString() Else def
 End
 End
 
 
 Function Json_GetInt:Int( json:Map<String,JsonValue>,key:String,def:Int )
 Function Json_GetInt:Int( json:Map<String,JsonValue>,key:String,def:Int )
 	
 	
-	Return json[key] ? Int(json[key].ToNumber()) Else def
+	Return json.Contains( key ) ? Int(json[key].ToNumber()) Else def
 End
 End
 
 
 
 
+
 Class JsonArray Extension
 Class JsonArray Extension
 	
 	
-	Function Create:JsonArray( values:String[] )
+	Function FromStrings:JsonArray( values:String[] )
 		
 		
 		Local jvals:=New JsonValue[values.Length]
 		Local jvals:=New JsonValue[values.Length]
 		For Local i:=0 Until values.Length
 		For Local i:=0 Until values.Length

+ 117 - 1
utils/Utils.monkey2

@@ -2,13 +2,40 @@
 Namespace ted2go
 Namespace ted2go
 
 
 
 
-Function IsLowercacedFirstChar:Bool(s:String)
+Function SwapCase:String( s:String )
+	
+	Local result:="",ss:String,lower:String
+	For Local i:=0 Until s.Length
+		ss=s.Slice( i,i+1 )
+		lower=ss.ToLower()
+		result+=(ss=lower) ? ss.ToUpper() Else lower
+	Next
+	Return result
+End
+
+Function IsLowercacedFirstChar:Bool( s:String )
 	
 	
 	If Not s Return False
 	If Not s Return False
 	Local s1:=s.Slice( 0,1 )
 	Local s1:=s.Slice( 0,1 )
 	Return s1 = s1.ToLower()
 	Return s1 = s1.ToLower()
 End
 End
 
 
+Function GetCaseSensitivePath:String( path:String )
+
+#If __HOSTOS__="windows"
+	Local dir:=ExtractDir( path )
+	Local items:=LoadDir( dir )
+	If items
+		Local lower:=StripDir( path ).ToLower()
+		For Local i:=Eachin items
+			If i.ToLower()=lower Return dir+i
+		Next
+	Endif
+	Return path
+#Else
+	Return path
+#Endif
+End
 
 
 Class Utils
 Class Utils
 	
 	
@@ -263,6 +290,11 @@ Class Stack<T> Extension
 		Self.Remove( item )
 		Self.Remove( item )
 	End
 	End
 	
 	
+	Operator+=( items:T[] )
+	
+		Self.AddAll( items )
+	End
+	
 End
 End
 
 
 
 
@@ -282,3 +314,87 @@ Struct Recti Extension
 		Self.Size=size
 		Self.Size=size
 	End
 	End
 End
 End
+
+
+Function TypeName<T>:String( obj:T ) Where T Extends Object
+	
+	Return obj ? String.FromCString( obj.typeName() ) Else Null
+End
+
+Function FindViewInHierarchy<T>:T( view:View ) Where T Extends View
+	
+	While view
+		Local r:=Cast<T>( view )
+		If r Return r
+		view=view.Parent
+	Wend
+	Return Null
+End
+
+Function StripEnding:String( text:String,ends:String )
+	
+	Return text.EndsWith( ends ) ? text.Slice( 0,text.Length-ends.Length ) Else text
+End
+
+Function StripStarting:String( text:String,starts:String )
+	
+	Return text.StartsWith( starts ) ? text.Slice( starts.Length ) Else text
+End
+
+#Rem monkeydocs Return ident and position in line where ident starts
+#End
+Function GetIndentBeforePos_Mx2:Tuple2<String,Int>( line:String,pos:Int,withDots:Bool )
+	
+	Local n:=pos-1
+	
+	While n >= 0
+	
+		Local more:=(line[n]=Chars.MORE_BRACKET)
+	
+		If line[n] = Chars.DOT Or more ' . | ?. | ->
+			If Not withDots Exit
+			If more
+				If n>0 And line[n-1]<>"-"[0] Exit
+				n-=1 ' skip '-'
+			Else
+				If n>0 And line[n-1]="?"[0] Then n-=1 ' skip '?'
+			Endif
+		ElseIf Not (IsIdent( line[n] ) Or line[n] = Chars.GRID) ' #
+			Exit
+		Endif
+	
+		n-=1
+	Wend
+	n+=1
+	
+	Local s:=""
+	Local starts:=-1
+	If n < pos
+		starts=n
+		s=line.Slice( n,pos ).Replace( "?.","." ).Replace( "->","." )
+	Endif
+	Return New Tuple2<String,Int>( s,starts )
+End
+
+Function IsPosInsideOfQuotes_Mx2:Bool( text:String,pos:Int )
+
+	Local i:=0
+	Local n:=text.Length
+	If pos=0 Return False
+	Local quoteCounter:=0
+	While i < n
+		Local c:=text[i]
+		If i = pos
+			If quoteCounter Mod 2 = 0 'not inside of string
+				Return False
+			Else 'inside
+				Return True
+			Endif 
+		Endif
+		If c = Chars.DOUBLE_QUOTE
+			quoteCounter+=1
+		Endif
+		i+=1
+	Wend
+	Return (quoteCounter Mod 2 <> 0)
+End

+ 33 - 33
view/AutocompleteView.monkey2

@@ -158,7 +158,7 @@ Class AutocompleteDialog Extends NoTitleDialog
 		' using lowerCase for keywords
 		' using lowerCase for keywords
 		Local lastIdent:=(dotPos > 0) ? ident.Slice( dotPos+1 ) Else ident
 		Local lastIdent:=(dotPos > 0) ? ident.Slice( dotPos+1 ) Else ident
 		Local lastIdentLower:=lastIdent.ToLower()
 		Local lastIdentLower:=lastIdent.ToLower()
-				
+		
 		_view.word=lastIdentLower
 		_view.word=lastIdentLower
 		
 		
 		Local starts:=(_fullIdent And ident.StartsWith( _fullIdent ))
 		Local starts:=(_fullIdent And ident.StartsWith( _fullIdent ))
@@ -175,37 +175,37 @@ Class AutocompleteDialog Extends NoTitleDialog
 		'if typed ident starts with previous
 		'if typed ident starts with previous
 		'need to simple filter items
 		'need to simple filter items
 		
 		
-		If IsOpened And starts And Not ident.EndsWith(".")
-			
-			Local items:=_view.Items
-			For Local i:=Eachin items
-				
-				If parser.CheckStartsWith( i.Text,lastIdentLower )
-					result.Add( i )
-				Endif
-				
-			Next
-			
-			' some "copy/paste" code
-			_fullIdent=ident
-			_lastIdentPart=lastIdentLower
-			If IsOpened Then Hide() 'hide to re-layout on open
-			
-			'nothing to show
-			If result.Empty
-				Return
-			Endif
-			
-			CodeItemsSorter.SortByIdent( result,lastIdent )
-			
-			_view.Reset()'reset selIndex
-			_view.SetItems( result )
-			
-			Super.Show()
-			
-			_disableUsingsFilter=filter
-			Return
-		End
+'		If IsOpened And starts And Not ident.EndsWith(".")
+'			
+'			Local items:=_view.Items
+'			For Local i:=Eachin items
+'				
+'				If parser.CheckStartsWith( i.Text,lastIdentLower )
+'					result.Add( i )
+'				Endif
+'				
+'			Next
+'			
+'			' some "copy/paste" code
+'			_fullIdent=ident
+'			_lastIdentPart=lastIdentLower
+'			If IsOpened Then Hide() 'hide to re-layout on open
+'			
+'			'nothing to show
+'			If result.Empty
+'				Return
+'			Endif
+'			
+'			CodeItemsSorter.SortByIdent( result,lastIdent )
+'			
+'			_view.Reset()'reset selIndex
+'			_view.SetItems( result )
+'			
+'			Super.Show()
+'			
+'			_disableUsingsFilter=filter
+'			Return
+'		End
 		
 		
 		
 		
 		_fullIdent=ident
 		_fullIdent=ident
@@ -514,7 +514,7 @@ Class AutocompleteDialog Extends NoTitleDialog
 		Next
 		Next
 		'preprocessor
 		'preprocessor
 		'need to load it like keywords
 		'need to load it like keywords
-		Local s:="#If ,#Rem,#End,#Endif,#Else,#Else If ,#Import ,monkeydoc,__TARGET__,__MOBILE_TARGET__,__DESKTOP_TARGET__,__HOSTOS__"
+		Local s:="#If ,#Rem,#End,#Endif,#Else,#Else If ,#Import ,monkeydoc,__TARGET__,__MOBILE_TARGET__,__DESKTOP_TARGET__,__HOSTOS__,__ARCH__,#Reflect "
 		Local arr:=s.Split( "," )
 		Local arr:=s.Split( "," )
 		For Local i:=Eachin arr
 		For Local i:=Eachin arr
 			list.Add( New ListViewItem( i ) )
 			list.Add( New ListViewItem( i ) )

+ 131 - 35
view/CodeTextView.monkey2

@@ -12,6 +12,7 @@ Class CodeTextView Extends TextView
 	Field TextChanged:Void()
 	Field TextChanged:Void()
 	
 	
 	Method New()
 	Method New()
+		
 		Super.New()
 		Super.New()
 		
 		
 		CursorBlinkRate=2.5
 		CursorBlinkRate=2.5
@@ -59,6 +60,116 @@ Class CodeTextView Extends TextView
 		UpdateThemeColors()
 		UpdateThemeColors()
 	End
 	End
 	
 	
+	Method DeleteLineAtCursor()
+	
+		Local line:=Document.FindLine( Cursor )
+		Local pos:=Cursor
+		SelectText( Document.StartOfLine( line ),Document.EndOfLine( line )+1 )
+		ReplaceText( "" )
+		pos=Min( pos,Document.EndOfLine( line ) )
+		SelectText( pos,pos )
+	End
+	
+	Method DeleteWordBackward()
+	
+		If CanCopy ' try to delete selected area
+			ReplaceText( "" )
+			Return
+		Endif
+	
+		Local line:=Document.FindLine( Cursor )
+		Local found:Word=Null
+		For Local word:=Eachin WordIterator.ForLine( Self,line )
+			If Cursor>word.index And Cursor<=word.index+word.length
+				found=word
+				Exit
+			Endif
+		Next
+		If found
+			SelectText( found.index,Cursor )
+			ReplaceText( "" )
+		Endif
+	End
+	
+	Method DeleteWordForward()
+	
+		If CanCopy ' try to delete selected area
+			ReplaceText( "" )
+			Return
+		Endif
+	
+		Local line:=Document.FindLine( Cursor )
+		Local found:Word=Null
+		For Local word:=Eachin WordIterator.ForLine( Self,line )
+			If Cursor>=word.index And Cursor<word.index+word.length
+				found=word
+				Exit
+			Endif
+		Next
+		If found
+			SelectText( Cursor,found.index+found.length )
+			ReplaceText( "" )
+		Endif
+	End
+	
+	Method DeleteToEnd()
+	
+		Local i1:=Min( Anchor,Cursor )
+		Local i2:=Max( Anchor,Cursor )
+	
+		SelectText( i1,Document.EndOfLine( Document.FindLine( i2 ) ) )
+		ReplaceText( "" )
+	End
+	
+	Method DeleteToBegin()
+	
+		Local i1:=Min( Anchor,Cursor )
+		Local i2:=Max( Anchor,Cursor )
+	
+		SelectText( Document.StartOfLine( Document.FindLine( i1 ) ),i2 )
+		ReplaceText( "" )
+	End
+	
+	Method LowercaseSelection()
+	
+		Local txt:=SelectedText
+		If txt
+			Local a:=Anchor,c:=Cursor
+			ReplaceText( txt.ToLower() )
+			SelectText( a,c )
+		Endif
+	End
+	
+	Method UppercaseSelection()
+	
+		Local txt:=SelectedText
+		If txt
+			Local a:=Anchor,c:=Cursor
+			ReplaceText( txt.ToUpper() )
+			SelectText( a,c )
+		Endif
+	End
+	
+	Method SwapCaseSelection()
+	
+		Local txt:=SelectedText
+		If txt
+			Local a:=Anchor,c:=Cursor
+			ReplaceText( SwapCase( txt ) )
+			SelectText( a,c )
+		Endif
+	End
+	
+	Property SelectedText:String()
+		
+		If Not CanCopy Return ""
+		
+		Local i1:=Min( Anchor,Cursor )
+		Local i2:=Max( Anchor,Cursor )
+		
+		Return Text.Slice( i1,i2 )
+	End
+	
 	Property IsCursorAtTheEndOfLine:Bool()
 	Property IsCursorAtTheEndOfLine:Bool()
 		
 		
 		Local line:=Document.FindLine( Cursor )
 		Local line:=Document.FindLine( Cursor )
@@ -92,36 +203,8 @@ Class CodeTextView Extends TextView
 	
 	
 	Method IdentBeforeCursor:String( withDots:Bool=True )
 	Method IdentBeforeCursor:String( withDots:Bool=True )
 		
 		
-		Local text:=Text
-		Local cur:=Cursor
-		Local n:=Cursor-1
-		Local start:=Document.StartOfLine( Document.FindLine( Cursor ) )
-		
-		While n >= start
-			
-			Local more:=(text[n]=Chars.MORE_BRACKET)
-			
-			If text[n] = Chars.DOT Or more ' . | ?. | ->
-				If Not withDots Exit
-				If more
-					If n>0 And text[n-1]<>"-"[0] Exit
-					n-=1 ' skip '-'
-				Else
-					If n>0 And text[n-1]="?"[0] Then n-=1 ' skip '?'
-				Endif
-			ElseIf Not (IsIdent( text[n] ) Or text[n] = Chars.GRID) ' #
-				Exit
-			Endif
-			
-			n-=1
-		Wend
-		n+=1
-		
-		Local s:=""
-		If n < cur
-			s=text.Slice( n,cur ).Replace( "?.","." ).Replace( "->","." )
-		Endif
-		Return s
+		Local pair:=GetIndentBeforePos_Mx2( LineTextAtCursor,PosInLineAtCursor,withDots )
+		Return pair.Item1
 	End
 	End
 	
 	
 	Property WordAtCursor:String()
 	Property WordAtCursor:String()
@@ -247,6 +330,10 @@ Class CodeTextView Extends TextView
 		Return Anchor-Document.StartOfLine( LineNumAtAnchor )
 		Return Anchor-Document.StartOfLine( LineNumAtAnchor )
 	End
 	End
 	
 	
+	Property StartOfLineAtCursor:Int()
+		Return Document.StartOfLine( LineNumAtCursor )
+	End
+	
 	Property CursorPos:Vec2i()
 	Property CursorPos:Vec2i()
 		Return New Vec2i( LineNumAtCursor,PosInLineAtCursor )
 		Return New Vec2i( LineNumAtCursor,PosInLineAtCursor )
 	End
 	End
@@ -354,7 +441,18 @@ Class CodeTextView Extends TextView
 						Local cur:=CharAtPoint( event.Location )
 						Local cur:=CharAtPoint( event.Location )
 						SelectText( cur,cur )
 						SelectText( cur,cur )
 					Else
 					Else
-						Local r:=CursorRect | CharRect( Anchor )
+						Local i1:=Min( Cursor,Anchor )
+						Local i2:=Max( Cursor,Anchor )
+						Local l1:=Document.FindLine( i1 )
+						Local l2:=Document.FindLine( i2 )
+						Local r:Recti=Null
+						For Local line:=l1 To l2
+							If r=Null
+								r=LineRect( line )
+							Else
+								r|=LineRect( line )
+							Endif
+						Next
 						If Not r.Contains( event.Location )
 						If Not r.Contains( event.Location )
 							Local cur:=CharAtPoint( event.Location )
 							Local cur:=CharAtPoint( event.Location )
 							SelectText( cur,cur )
 							SelectText( cur,cur )
@@ -413,9 +511,6 @@ Class CodeTextView Extends TextView
 		Return _line
 		Return _line
 	End
 	End
 	
 	
-	
-	Protected
-	
 	Method OnCut( wholeLine:Bool=False )
 	Method OnCut( wholeLine:Bool=False )
 	
 	
 		If wholeLine
 		If wholeLine
@@ -573,11 +668,12 @@ Class CodeTextView Extends TextView
 	Method OnThemeChanged() Override
 	Method OnThemeChanged() Override
 		
 		
 		Super.OnThemeChanged()
 		Super.OnThemeChanged()
+		
 		UpdateThemeColors()
 		UpdateThemeColors()
 	End
 	End
 	
 	
 	Method UpdateThemeColors() Virtual
 	Method UpdateThemeColors() Virtual
-	
+		
 		_whitespacesColor=App.Theme.GetColor( "textview-whitespaces" )
 		_whitespacesColor=App.Theme.GetColor( "textview-whitespaces" )
 		_extraSelColor=App.Theme.GetColor( "textview-extra-selection" )
 		_extraSelColor=App.Theme.GetColor( "textview-extra-selection" )
 	End
 	End

+ 9 - 7
view/CodeTreeView.monkey2

@@ -44,19 +44,20 @@ Class CodeTreeView Extends TreeViewExt
 		If expandIfOnlyOneItem And RootNode.NumChildren=1
 		If expandIfOnlyOneItem And RootNode.NumChildren=1
 			RootNode.Children[0].Expanded=True
 			RootNode.Children[0].Expanded=True
 		Endif
 		Endif
+		
 	End
 	End
 	
 	
 	Method SelectByScope( scope:CodeItem )
 	Method SelectByScope( scope:CodeItem )
-	
+		
 		Local node:=FindNode( RootNode,scope )
 		Local node:=FindNode( RootNode,scope )
 		If Not node Return
 		If Not node Return
 		
 		
-		If scope.IsLikeClass
-			node.Expanded=True
-			NodeExpanded( node )
-			Return
-		Endif
+		node.Expanded=True
+		TreeViewExpander.ExpandParents( node )
 		
 		
+		MeasureLayoutSize()
+		
+		Selected=Null
 		Selected=node
 		Selected=node
 	End
 	End
 	
 	
@@ -173,13 +174,14 @@ End
 Class CodeTreeNode Extends TreeView.Node
 Class CodeTreeNode Extends TreeView.Node
 
 
 	Method New( item:CodeItem,node:TreeView.Node )
 	Method New( item:CodeItem,node:TreeView.Node )
+		
 		Super.New( item.Text,node )
 		Super.New( item.Text,node )
 		_code=item
 		_code=item
 		Icon=CodeItemIcons.GetIcon( item )
 		Icon=CodeItemIcons.GetIcon( item )
-		
 	End
 	End
 	
 	
 	Property CodeItem:CodeItem()
 	Property CodeItem:CodeItem()
+		
 		Return _code
 		Return _code
 	End
 	End
 	
 	

+ 160 - 0
view/DraggableViewListener.monkey2

@@ -0,0 +1,160 @@
+
+Namespace ted2go
+
+
+Interface IDraggableItem<THolder>
+	
+	Property Detachable:Bool()
+	
+	Property PossibleHolders:THolder[]()
+	Setter( value:THolder[] )
+	
+	Property CurrentHolder:THolder()
+	
+End
+
+Interface IDraggableHolder
+	
+	Method Attach( item:Object,eventLocation:Vec2i )
+	Method Detach:View( item:Object )
+	
+	Method OnDragStarted() 	' highlight holder here (if needed)
+	Method OnDragEnded() 	' reset highlighting
+	
+End
+
+#Rem Call order: Detach -> OnDragStarted -> Attach -> OnDragEnded
+
+#End
+Class DraggableViewListener<TItem,THolder>
+	
+	Method GetItem:TItem( eventView:View,eventLocation:Vec2i ) Abstract
+	Method GetHolder:THolder( view:View ) Abstract
+	
+	Method New()
+		
+		_window=Window.AllWindows()[0]
+		
+		App.MouseEventFilter+=OnMouseEvent
+	End
+	
+	Property DragThreshold:Float()
+		Return _threshold
+	Setter( value:Float )
+		_threshold=value
+	End
+	
+	
+	Private
+	
+	Field _threshold:=10.0
+	Field _item:TItem
+	Field _view:View
+	Field _pressedPos:Vec2i
+	Field _detached:Bool
+	Field _window:Window
+	
+	Method OnMouseEvent( event:MouseEvent )
+	
+		Select event.Type
+			
+			Case EventType.MouseDown
+				
+				_item=GetItem( event.View,event.Location )
+				If Not _item Return
+				
+				If Not _item.Detachable
+					_item=Null
+					Return
+				Endif
+				
+				_pressedPos=Mouse.Location
+				
+			
+			Case EventType.MouseMove
+			
+				If Not _item Return
+				
+				If _detached
+					Local r:=_view.Frame
+					Local sz:=r.Size
+					r.TopLeft=Mouse.Location+New Vec2i( 0,-10 )
+					r.BottomRight=r.TopLeft+sz
+					_view.Frame=r
+					App.RequestRender()
+					Return
+				Endif
+				
+				Local dy:Float=Abs(Mouse.Y-_pressedPos.y)
+				
+				If dy>=_threshold*App.Theme.Scale.y
+					Detach()
+				Endif
+				
+			
+			Case EventType.MouseUp
+				
+				If Not _detached 
+					_item=Null
+					Return
+				Endif
+				
+				_window.RemoveChildView( _view )
+				
+				Local holder:=GetHolder( App.ActiveViewAtMouseLocation() )
+				
+				If Not CanAttach( _item,holder ) Then holder=_item.CurrentHolder
+				
+				holder.Attach( _item,event.Location )
+				
+				_item.CurrentHolder.OnDragEnded()
+				If _item.PossibleHolders
+					For Local i:=Eachin _item.PossibleHolders
+						If i=_item.CurrentHolder Continue
+						i.OnDragEnded()
+					Next
+				Endif
+				
+				_item=Null
+				_detached=False
+				
+				event.Eat()
+				
+		End
+	
+	End
+	
+	Method Detach()
+		
+		_detached=True
+		
+		Local holder:=GetHolder( _item.View )
+		_view=holder.Detach( _item )
+		
+		_window.AddChildView( _view )
+		
+		_item.CurrentHolder.OnDragStarted()
+		
+		If Not _item.PossibleHolders Return
+		
+		For Local i:=Eachin _item.PossibleHolders
+			If i=_item.CurrentHolder Continue
+			i.OnDragStarted()
+		Next
+		
+	End
+	
+	Function CanAttach:Bool( item:TItem,holder:THolder )
+		
+		If Not holder Return False
+		If Not item.PossibleHolders Return False
+		
+		For Local i:=Eachin item.PossibleHolders
+			
+			If i=holder Return True
+		Next
+		
+		Return False
+	End
+	
+End

+ 198 - 99
view/HelpTreeView.monkey2

@@ -35,9 +35,9 @@ Class HelpTreeView Extends TreeViewExt
 	Field PageClicked:Void( page:String )
 	Field PageClicked:Void( page:String )
 	
 	
 	Method New( htmlView:HtmlView )
 	Method New( htmlView:HtmlView )
-	
-		htmlView.AnchorClicked=Lambda( url:String )
 		
 		
+		htmlView.AnchorClicked=Lambda( url:String )
+			
 			'dodgy work around for mx2 docs!
 			'dodgy work around for mx2 docs!
 			'
 			'
 			If url.StartsWith( "javascript:void('" ) And url.EndsWith( "')" )
 			If url.StartsWith( "javascript:void('" ) And url.EndsWith( "')" )
@@ -50,7 +50,7 @@ Class HelpTreeView Extends TreeViewExt
 		End
 		End
 		
 		
 		PageClicked+=Lambda( page:String )
 		PageClicked+=Lambda( page:String )
-		
+			
 			Local url:=PageUrl( page )
 			Local url:=PageUrl( page )
 			If Not url Return
 			If Not url Return
 			
 			
@@ -58,15 +58,16 @@ Class HelpTreeView Extends TreeViewExt
 		End
 		End
 		
 		
 		Init()
 		Init()
+		
 	End
 	End
 	
 	
 	Property FindField:TextFieldExt()
 	Property FindField:TextFieldExt()
-	
+		
 		Return _textField
 		Return _textField
 	End
 	End
 	
 	
 	Method QuickHelp( text:String )
 	Method QuickHelp( text:String )
-	
+		
 		If text<>_textField.Text
 		If text<>_textField.Text
 			_textField.Text=text
 			_textField.Text=text
 		Else
 		Else
@@ -76,153 +77,245 @@ Class HelpTreeView Extends TreeViewExt
 	End
 	End
 	
 	
 	Method PageUrl:String( page:String )
 	Method PageUrl:String( page:String )
-
-		'old doc system		
+		
+		'old doc system
 		'Return RealPath( "modules/"+page.Replace( ":","/docs/__PAGES__/" ).Replace( ".","-" )+".html" )
 		'Return RealPath( "modules/"+page.Replace( ":","/docs/__PAGES__/" ).Replace( ".","-" )+".html" )
 		
 		
 		'new doc system
 		'new doc system
 		Return RealPath( "docs/"+page )
 		Return RealPath( "docs/"+page )
 	End
 	End
 	
 	
-	Method Update()
+	Function CreateNodes( obj:JsonObject,parent:Tree.Node,indexer:StringMap<Tree.Node> )
+		
+		Local text:=obj["text"].ToString()
+		Local page:=""
+		
+		If obj.Contains( "data" )
+			Local data:=obj["data"].ToObject()
+			page=data["page"].ToString()
+		Endif
+		
+		Local node:=New Tree.Node( text,parent,page )
+		indexer[page.ToLower()]=node
+		
+		If obj.Contains( "children" )
+			For Local child:=Eachin obj["children"].ToArray()
+				CreateNodes( Cast<JsonObject>( child ),node,indexer )
+			Next
+		Endif
+		
+	End
+	
+	Function FindChild:Node( node:TreeView.Node,text:String )
+		
+		For Local n:=Eachin node.Children
+			If n.Text=text Return Cast<Node>( n )
+		Next
+		Return Null
+	End
 	
 	
-		RootNode.RemoveAllChildren()
-
+	Method InsertNode:Node( node:Tree.Node )
+		
+		Local parent:=RootNode
+		Local items:=node.ParentsHierarchy
+		items.Add( node )
+		
+		Local last:Node
+		Local len:=items.Length
+		For Local i:=1 Until len ' start from 1 to skip root node
+			Local item:=items[i]
+			Local text:=item.Text
+			If i+1<len And items[i+1].Text=text Continue ' skip nested mogo>mojo>... etc
+			last=FindChild( parent,text )
+			If Not last
+				last=New Node( text,parent,item.GetUserData<String>() )
+			Endif
+			parent=last
+		Next
+		Return last
+	End
+	
+	Method Update( applyFilter:Bool=False )
+		
+		_index.Clear()
+		_index2.Clear()
+		_tree.Clear()
+		
 		For Local modname:=Eachin EnumModules()
 		For Local modname:=Eachin EnumModules()
-
-			'old doc system		
+			
+			'old doc system
 			'Local index:="modules/"+modname+"/docs/__PAGES__/index.js"
 			'Local index:="modules/"+modname+"/docs/__PAGES__/index.js"
-
+			
 			'new doc system
 			'new doc system
 			Local index:="docs/modules/"+modname+"/module/index.js"
 			Local index:="docs/modules/"+modname+"/module/index.js"
-		
+			
 			Local obj:=JsonObject.Load( index )
 			Local obj:=JsonObject.Load( index )
 			If Not obj Continue
 			If Not obj Continue
 			
 			
-			New Node( obj,RootNode,Self )
+			CreateNodes( obj,_tree.RootNode,_index )
 		Next
 		Next
 		
 		
-		NodeClicked+=Lambda( tnode:TreeView.Node )
+		FillTree()
 		
 		
-			Local node:=Cast<Node>( tnode )
-			If Not node Or Not node.Page Return
-			
-			PageClicked( node.Page )
-		End
+		If applyFilter Then Update( _textField.Text )
+	End
+	
+	Method RequestFocus()
 		
 		
+		_textField.MakeKeyView()
 	End
 	End
-
+	
+	
 	Private
 	Private
 	
 	
 	Class Node Extends TreeView.Node
 	Class Node Extends TreeView.Node
 	
 	
-		Method New( page:String,parent:TreeView.Node,tree:HelpTreeView )
-			Super.New( page,parent )
-			
-			_page=page
-		End
-	
-		Method New( obj:JsonObject,parent:TreeView.Node,tree:HelpTreeView )
-			Super.New( "",parent )
-		
-			Text=obj["text"].ToString()
+		Method New( text:String,parent:TreeView.Node,page:String )
 			
 			
-			If obj.Contains( "data" )
-
-				Local data:=obj["data"].ToObject()
-
-				Local page:=data["page"].ToString()
-				
-				tree._index[page.ToLower()]=Self
-				
-				_page=page
-			Endif
+			Super.New( text,parent )
 			
 			
-			If obj.Contains( "children" )
-				For Local child:=Eachin obj["children"].ToArray()
-					New Node( Cast<JsonObject>( child ),Self,tree )
-				Next
-			Endif
-
+			_page=page
 		End
 		End
 		
 		
 		Property Page:String()
 		Property Page:String()
 			Return _page
 			Return _page
 		End
 		End
 		
 		
-		Property Url:String()
-			Return _url
-		End
-		
 		Private
 		Private
 		
 		
 		Field _page:String
 		Field _page:String
 		
 		
-		Field _url:String
+	End
+	
+	Method FillTree()
+	
+		RootNode.RemoveAllChildren()
+		
+		FillNode( RootNode,_tree.RootNode.Children )
+		
+		Sort()
+	End
+	
+	Method FillNode( node:TreeView.Node,items:Stack<Tree.Node> )
+		
+		If Not items Return
+		
+		For Local item:=Eachin items
+			
+			Local page:=item.GetUserData<String>()
+			
+			' hack for the-same-nested 
+			If item.NumChildren=1
+				Local child:=item.Children[0]
+				If child.Text=item.Text.Replace( "-","." )
+					item=child
+				Endif
+			Endif
+			
+			Local n:=New Node( item.Text,node,page )
+			_index2[page.ToLower()]=n
+			
+			If item.NumChildren
+				FillNode( n,item.Children )
+			Endif
+		Next
+		
 	End
 	End
 	
 	
 	Method Update( text:String )
 	Method Update( text:String )
-
+		
 		RootNode.CollapseAll()
 		RootNode.CollapseAll()
-			
+		
+		text=StripEnding( text,"." )
+		
 		text=text.ToLower()
 		text=text.ToLower()
-			
+		
+		Local parts:=text.Split( "." )
+		Local text2:=text.Replace( ".","-" )
+		
+		If _tree.RootNode.NumChildren=0
+			New Node( "Click here to rebuild docs!",RootNode,"$$rebuild$$" )
+			Return
+		Endif
+		
 		_matches.Clear()
 		_matches.Clear()
+		
+		For Local it:=Eachin _index2
 			
 			
-		Local selected:=New Map<Node,Bool>
+			'Local node:=it.Value
+			Local n:=it.Value
 			
 			
-		For Local it:=Eachin _index
+			'Local n:=InsertNode( node )
 			
 			
-			If Not it.Key.Contains( text ) Continue
-				
-			Local node:=it.Value
-				
-			_matches.Push( node )
-				
-			node.Selected=True
+			'If Not text Continue
+			
+			If Not text2 Or Not it.Key.Contains( text2 )
+				n.Selected=False
+				Continue
+			Endif
+			
+			n.Selected=GetSelectionState( n,parts )
+			
+			If n.Selected
 				
 				
-			selected[node]=True
+				_matches.Push( n )
 				
 				
-			While node
-				node.Expanded=True
-				node=Cast<Node>( node.Parent )
-			Wend
-
-		Next
-						
-		For Local node:=Eachin _selected.Keys
+				Local n2:=n.Parent
+				While n2
+					n2.Expanded=True
+					n2=n2.Parent
+				Wend
+			Endif
 			
 			
-			If Not selected.Contains( node ) node.Selected=False
-
 		Next
 		Next
-			
-		_selected=selected
-			
+		
 		RootNode.Expanded=True
 		RootNode.Expanded=True
-			
+		
+		MainWindow.UpdateWindow( False )
+		
 		_matchid=0
 		_matchid=0
-			
+		
 		If _matches.Length
 		If _matches.Length
 			
 			
 			PageClicked( _matches[0].Page )
 			PageClicked( _matches[0].Page )
-			
+			Selected=_matches[0]
 		Endif
 		Endif
+		
+	End
 	
 	
+	Method GetSelectionState:Bool( node:TreeView.Node,parts:String[] )
+		
+		Local last:=parts.Length-1
+		Local i:=last
+		Repeat
+			Local part:=parts[i]
+			Local txt:=node.Text.ToLower()
+			If txt.Contains( part )
+				i-=1
+				If i<0 Exit 'true
+			Else
+				If i=last Return False
+			Endif
+			node=node.Parent
+			If Not node Return False
+		Forever
+		
+		Return True
 	End
 	End
 	
 	
 	Method NextHelp()
 	Method NextHelp()
-	
-		If Not _matches Return
-	
-		_matchid+=1
-		If _matchid>=_matches.Length _matchid=0
 		
 		
-		If _matchid<_matches.Length PageClicked( _matches[_matchid].Page )
+		If _matches.Empty Return
+		
+		_matchid=(_matchid+1) Mod _matches.Length
+		
+		PageClicked( _matches[_matchid].Page )
+		Selected=_matches[_matchid]
 	End
 	End
 	
 	
 	Method Init()
 	Method Init()
-
-		_textField=New TextFieldExt
+		
+		_textField=New TextFieldExt( "" )
 		_textField.Style=GetStyle( "HelpTextField" )
 		_textField.Style=GetStyle( "HelpTextField" )
 		
 		
 		_textField.Entered=Lambda()
 		_textField.Entered=Lambda()
@@ -245,22 +338,28 @@ Class HelpTreeView Extends TreeViewExt
 		RootNodeVisible=False
 		RootNodeVisible=False
 		RootNode.Expanded=True
 		RootNode.Expanded=True
 		
 		
-		_textField.Activated+=_textField.MakeKeyView
+		NodeClicked+=Lambda( tnode:TreeView.Node )
 		
 		
-		Activated+=MainWindow.ShowHelpView
+			Local node:=Cast<Node>( tnode )
+			Local page:=node?.Page
+			If Not page Return
+			
+			If page="$$rebuild$$"
+				MainWindow.RebuildDocs()
+				Return
+			Endif
+			
+			PageClicked( page )
+		End
 		
 		
 		Update()
 		Update()
-				
 	End
 	End
 	
 	
 	Field _textField:TextFieldExt
 	Field _textField:TextFieldExt
-	
 	Field _matchid:Int
 	Field _matchid:Int
-		
 	Field _matches:=New Stack<Node>
 	Field _matches:=New Stack<Node>
-	
-	Field _selected:=New Map<Node,Bool>
-	
-	Field _index:=New Map<String,Node>
+	Field _index:=New Map<String,Tree.Node>
+	Field _index2:=New Map<String,Node>
+	Field _tree:=New Tree
 	
 	
 End
 End

+ 12 - 2
view/ListViewExt.monkey2

@@ -216,9 +216,10 @@ Class ListViewExt Extends ScrollableView
 			Local d:=(firstVisLine-_selIndex)*_lineH
 			Local d:=(firstVisLine-_selIndex)*_lineH
 			Scroll-=New Vec2i( 0,d )
 			Scroll-=New Vec2i( 0,d )
 		Elseif _selIndex >= lastVisLine
 		Elseif _selIndex >= lastVisLine
-			Local d:=(lastVisLine-_selIndex)*_lineH
+			Local d:=(lastVisLine-_selIndex)*_lineH - _dh
 			Scroll-=New Vec2i( 0,d )
 			Scroll-=New Vec2i( 0,d )
 		Endif
 		Endif
+		
 	End
 	End
 
 
 	Method OnRender( canvas:Canvas ) Override
 	Method OnRender( canvas:Canvas ) Override
@@ -258,6 +259,14 @@ Class ListViewExt Extends ScrollableView
 		_width=w
 		_width=w
 		
 		
 		Local h:=_items.Length*_lineH
 		Local h:=_items.Length*_lineH
+		
+		_dh=0
+		Local maxH:=Min( _visibleCount*_lineH,MaxSize.y )
+		If h>maxH 'has scroll
+			_dh=20*App.Theme.Scale.y '+20 for scrollbar
+			h+=_dh
+		Endif
+		
 		_height=h
 		_height=h
 		
 		
 		Return New Vec2i( w,h )
 		Return New Vec2i( w,h )
@@ -276,7 +285,7 @@ Class ListViewExt Extends ScrollableView
 		Endif
 		Endif
 		If sx Then h+=_lineH
 		If sx Then h+=_lineH
 		
 		
-		Return New Vec2i( w,h ) '+20 for scrollbar
+		Return New Vec2i( w,h )
 	End
 	End
 	
 	
 	Method OnContentMouseEvent( event:MouseEvent ) Override
 	Method OnContentMouseEvent( event:MouseEvent ) Override
@@ -326,5 +335,6 @@ Class ListViewExt Extends ScrollableView
 	Field _selColor:Color,_hoverColor:Color
 	Field _selColor:Color,_hoverColor:Color
 	Field _width:Int,_height:Int
 	Field _width:Int,_height:Int
 	Field _moveCyclic:Bool
 	Field _moveCyclic:Bool
+	Field _dh:Float
 	
 	
 End
 End

+ 256 - 27
view/ProjectBrowserView.monkey2

@@ -2,7 +2,7 @@
 Namespace ted2go
 Namespace ted2go
 
 
 
 
-Class ProjectBrowserView Extends TreeViewExt
+Class ProjectBrowserView Extends TreeViewExt Implements IDraggableHolder
 	
 	
 	Field RequestedDelete:Void( node:Node )
 	Field RequestedDelete:Void( node:Node )
 	Field FileClicked:Void( node:Node )
 	Field FileClicked:Void( node:Node )
@@ -15,7 +15,7 @@ Class ProjectBrowserView Extends TreeViewExt
 		
 		
 		Style=GetStyle( "FileBrowser" )
 		Style=GetStyle( "FileBrowser" )
 		
 		
-		_rootNode=New Node( Null )
+		_rootNode=NewNode( Null )
 		RootNode=_rootNode
 		RootNode=_rootNode
 		RootNode.Expanded=True
 		RootNode.Expanded=True
 		RootNodeVisible=False
 		RootNodeVisible=False
@@ -34,11 +34,141 @@ Class ProjectBrowserView Extends TreeViewExt
 		
 		
 		UpdateFileTypeIcons()
 		UpdateFileTypeIcons()
 		
 		
+		If Not _listener Then _listener=New DraggableProjTreeListener
+	End
+	
+	Method Attach( item:Object,eventLocation:Vec2i )
+		
+		New Fiber( Lambda()
+			
+			Local node:=Cast<Node>( item )
+			Local node2:=FindNodeAtPoint( eventLocation )
+			If Not node2 Return
+			
+			Local destNode:=Cast<Node>( node2 )
+			
+			Local srcIsFolder:=GetFileType( node.Path )=FileType.Directory
+			Local destIsFolder:=GetFileType( destNode.Path )=FileType.Directory
+			
+			If Not destIsFolder
+				node2=node2.Parent ' grab destination folder
+				destNode=Cast<Node>( node2 )
+				destIsFolder=True
+			Endif
+			
+			If srcIsFolder
+				If node2=node Or node.Parent=node2 Return
+				' deny to move into child folder
+				Local n:=node2.Parent
+				While n
+					If n=node Return
+					n=n.Parent
+				Wend
+			Else
+				If node.Parent=node2 Return
+			Endif
+			
+			Local src:=node.Path
+			Local dest:=destNode.Path
+			
+			If Not dest.EndsWith( "/" ) Then dest+="/"
+			Local name:=StripDir( src )
+			dest+=name
+			
+			If Not CheckOverwritingConfirm( dest,name,srcIsFolder ) Return
+			
+			Local ok:=False
+			Local move:=(Keyboard.Modifiers & Modifier.Control)=0
+			
+			If srcIsFolder
+				ok=CopyDir( src,dest )
+				If ok And move Then DeleteDir( src,True )
+			Else
+				ok=CopyFile( src,dest )
+				If ok And move Then DeleteFile( src )
+			Endif
+			If ok
+				If move Then node.Remove()
+				
+				OnDraggedInto( destNode,name )
+			Else
+				Alert( "Can't move into "+ExtractDir( dest ) )
+			Endif
+			
+		End )
+		
+	End
+	
+	Method Detach:View( item:Object )
+		
+		' don't remove
+		Local node:=Cast<Node>( item )
+		
+		_draggingText=node.Text
+		If Not _draggableView
+			_draggableView=New Button( "",node.Icon )
+			_draggableView.Layout="float"
+		Else
+			_draggableView.Icon=node.Icon
+		Endif
+		
+		MakeKeyView() 'wonna catch Ctrl-key
+		
+		Return _draggableView
+	End
+	
+	Method OnDragStarted()
+		
+		_draggingState=True
+	End
+	
+	Method OnDragEnded()
+		
+		_draggingState=False
+	End
+	
+	Method OnFileDropped:Bool( path:String )
+		
+		Local point:=TransformWindowPointToView( Mouse.Location )
+		Local node:=Cast<Node>( FindNodeAtPoint( point ) )
+		If Not node Return False
+		
+		If GetFileType( node.Path )=FileType.File
+			node=Cast<Node>( node.Parent )
+		Endif
+		
+		Local dest:=node.Path
+		If Not dest.EndsWith( "/" ) Then dest+="/"
+		Local name:=StripDir( path )
+		dest+=name
+		
+		Local isFolder:=GetFileType( path )=FileType.Directory
+		
+		If Not CheckOverwritingConfirm( dest,name,isFolder ) Return True ' don't copied but return true
+		
+		Local ok:=False
+		If isFolder
+			ok=CopyDir( path,dest )
+		Else
+			ok=CopyFile( path,dest )
+		Endif
+		If ok
+			OnDraggedInto( node,name )
+		Else
+			Alert( "Can't copy into "+ExtractDir( dest ) )
+		Endif
+		
+		Return True
+	End
+	
+	Method NewNode:Node( parent:Node )
+		
+		Return New Node( parent,Self )
 	End
 	End
 	
 	
 	Method AddProject( dir:String )
 	Method AddProject( dir:String )
 		
 		
-		Local node:=New Node( _rootNode )
+		Local node:=NewNode( _rootNode )
 		Local s:=StripDir( dir )+" ("+dir+")"
 		Local s:=StripDir( dir )+" ("+dir+")"
 		node.Text=s
 		node.Text=s
 		node._path=dir
 		node._path=dir
@@ -85,30 +215,62 @@ Class ProjectBrowserView Extends TreeViewExt
 	Method Refresh( node:Node )
 	Method Refresh( node:Node )
 	
 	
 		UpdateNode( node,True )
 		UpdateNode( node,True )
+		ApplyFilter( node )
+		Selected=node
 	End
 	End
 	
 	
 	Method Refresh( tnode:TreeView.Node )
 	Method Refresh( tnode:TreeView.Node )
 		
 		
 		Local node:=Cast<Node>( tnode )
 		Local node:=Cast<Node>( tnode )
-		If node then UpdateNode( node,True )
+		If node Then Refresh( node )
 	End
 	End
 	
 	
 	
 	
 	Protected
 	Protected
 	
 	
-	Class Node Extends TreeView.Node
+	Class Node Extends TreeView.Node Implements IDraggableItem<ProjectBrowserView>
 	
 	
-		Method New( parent:Node )
+		Method New( parent:Node,view:ProjectBrowserView )
+			
 			Super.New( "",parent )
 			Super.New( "",parent )
+			_view=view
+			_curHolder=view
 		End
 		End
 	
 	
 		Property Path:String()
 		Property Path:String()
 			Return _path
 			Return _path
 		End
 		End
 		
 		
+		Property Detachable:Bool()
+			Return GetNodeDeepLevel( Self )>1
+		End
+		
+		Property PossibleHolders:ProjectBrowserView[]()
+			Return _holders
+		Setter( value:ProjectBrowserView[] )
+			_holders=value
+		End
+		
+		Property CurrentHolder:ProjectBrowserView()
+			Return _curHolder
+		End
+		
+		Property View:View()
+		
+			Return _view
+		
+		Setter( view:View )
+		
+			_view=view
+		End
+		
 		Private
 		Private
 	
 	
 		Field _path:String
 		Field _path:String
+		Field _holders:ProjectBrowserView[]
+		Field _curHolder:ProjectBrowserView
+		Field _view:View
+		
 	End
 	End
 	
 	
 	Method GetFileTypeIcon:Image( path:String ) Virtual
 	Method GetFileTypeIcon:Image( path:String ) Virtual
@@ -144,6 +306,15 @@ Class ProjectBrowserView Extends TreeViewExt
 		Endif
 		Endif
 		
 		
 		Super.OnKeyEvent( event )
 		Super.OnKeyEvent( event )
+		
+		UpdateDraggingState()
+	End
+	
+	Method OnContentMouseEvent( event:MouseEvent ) Override
+		
+		Super.OnContentMouseEvent( event )
+		
+		UpdateDraggingState()
 	End
 	End
 	
 	
 	
 	
@@ -158,6 +329,48 @@ Class ProjectBrowserView Extends TreeViewExt
 	Field _dirIcon:Image
 	Field _dirIcon:Image
 	Field _fileIcon:Image
 	Field _fileIcon:Image
 	
 	
+	Field _draggableView:Button
+	Field _draggingState:Bool
+	Field _draggingText:String
+	
+	Global _listener:DraggableProjTreeListener
+	
+	Method CheckOverwritingConfirm:Bool( destPath:String,name:String,isFolder:Bool )
+		
+		' confirm overwriting
+		Local confirm:=""
+		If isFolder And DirectoryExists( destPath )
+			confirm="Destination folder already contains '"+name+"' subfolder.~nDo you want to merge files replacing with moved ones?"
+		Elseif FileExists( destPath )
+			confirm="Destination folder already contains '"+name+"'.~nDo you want to replace existing file with moved one?"
+		Endif
+		
+		If confirm
+			Return RequestOkay( confirm,"" )
+		Endif
+		
+		Return True
+	End
+	
+	Method OnDraggedInto( node:Node,name:String )
+		
+		Local path:=node.Text+"\"+name
+		
+		node.Expanded=True
+		_expander.Store( node )
+		Local par:=IsProjectNode( node ) ? node Else node.Parent
+		OnNodeExpanded( par ) 'update parent folder
+		
+		SelectByPathEnds( path )
+		
+	End
+	
+	Method UpdateDraggingState()
+		
+		If _draggingState
+			_draggableView.Text=(Keyboard.Modifiers & Modifier.Control = 0) ? _draggingText Else _draggingText+" (copy)"
+		Endif
+	End
 	
 	
 	Method FindProjectNode:Node( node:TreeView.Node )
 	Method FindProjectNode:Node( node:TreeView.Node )
 		
 		
@@ -248,14 +461,14 @@ Class ProjectBrowserView Extends TreeViewExt
 		'Print "update node: "+path
 		'Print "update node: "+path
 		If Not path.EndsWith( "/" ) path+="/"
 		If Not path.EndsWith( "/" ) path+="/"
 		Local dir:=filesystem.LoadDir( path )
 		Local dir:=filesystem.LoadDir( path )
-	
+		
 		Local dirs:=New Stack<String>
 		Local dirs:=New Stack<String>
 		Local files:=New Stack<String>
 		Local files:=New Stack<String>
-	
+		
 		For Local f:=Eachin dir
 		For Local f:=Eachin dir
-	
+			
 			Local fpath:=path+f
 			Local fpath:=path+f
-	
+			
 			Select GetFileType( fpath )
 			Select GetFileType( fpath )
 			Case FileType.Directory
 			Case FileType.Directory
 				dirs.Add( f )
 				dirs.Add( f )
@@ -263,42 +476,42 @@ Class ProjectBrowserView Extends TreeViewExt
 				files.Add( f )
 				files.Add( f )
 			End
 			End
 		Next
 		Next
-	
+		
 		dirs.Sort()
 		dirs.Sort()
 		files.Sort()
 		files.Sort()
-	
+		
 		Local i:=0,children:=node.Children
 		Local i:=0,children:=node.Children
-	
+		
 		While i<dir.Length
 		While i<dir.Length
-	
+			
 			Local f:=""
 			Local f:=""
 			If i<dirs.Length f=dirs[i] Else f=files[i-dirs.Length]
 			If i<dirs.Length f=dirs[i] Else f=files[i-dirs.Length]
-	
+			
 			Local child:Node
 			Local child:Node
-	
+			
 			If i<children.Length
 			If i<children.Length
 				child=Cast<Node>( children[i] )
 				child=Cast<Node>( children[i] )
 				child.RemoveAllChildren()
 				child.RemoveAllChildren()
 			Else
 			Else
-				child=New Node( node )
+				child=NewNode( node )
 			Endif
 			Endif
-	
+			
 			Local fpath:=path+f
 			Local fpath:=path+f
-	
+			
 			child.Text=f
 			child.Text=f
 			child._path=fpath
 			child._path=fpath
-	
+			
 			Local icon:Image
 			Local icon:Image
 			If Prefs.MainProjectIcons 'Only load icon if settings say so
 			If Prefs.MainProjectIcons 'Only load icon if settings say so
 				icon=GetFileTypeIcon( fpath )
 				icon=GetFileTypeIcon( fpath )
 			Endif
 			Endif
-	
+			
 			If i<dirs.Length
 			If i<dirs.Length
 				If Not icon And Prefs.MainProjectIcons Then icon=_dirIcon
 				If Not icon And Prefs.MainProjectIcons Then icon=_dirIcon
 				child.Icon=icon
 				child.Icon=icon
-	
+				
 				_expander.Restore( child )
 				_expander.Restore( child )
-	
+				
 				If child.Expanded Or recurse
 				If child.Expanded Or recurse
 					UpdateNode( child,child.Expanded )
 					UpdateNode( child,child.Expanded )
 				Endif
 				Endif
@@ -307,12 +520,12 @@ Class ProjectBrowserView Extends TreeViewExt
 				child.Icon=icon
 				child.Icon=icon
 				child.RemoveAllChildren()
 				child.RemoveAllChildren()
 			Endif
 			Endif
-	
+			
 			i+=1
 			i+=1
 		Wend
 		Wend
-	
+		
 		node.RemoveChildren( i )
 		node.RemoveChildren( i )
-	
+		
 	End
 	End
 	
 	
 	Method OnNodeClicked( tnode:TreeView.Node )
 	Method OnNodeClicked( tnode:TreeView.Node )
@@ -324,7 +537,7 @@ Class ProjectBrowserView Extends TreeViewExt
 	End
 	End
 	
 	
 	Method OnNodeRightClicked( tnode:TreeView.Node )
 	Method OnNodeRightClicked( tnode:TreeView.Node )
-	
+		
 		Local node:=Cast<Node>( tnode )
 		Local node:=Cast<Node>( tnode )
 		If Not node Return
 		If Not node Return
 		
 		
@@ -445,3 +658,19 @@ Class TextFilter
 	Field _type:=CheckType.Equals
 	Field _type:=CheckType.Equals
 	
 	
 End
 End
+
+Class DraggableProjTreeListener Extends DraggableViewListener<ProjectBrowserView.Node,ProjectBrowserView>
+	
+	Method GetItem:ProjectBrowserView.Node( eventView:View,eventLocation:Vec2i ) Override
+		
+		Local projTree:=FindViewInHierarchy<ProjectBrowserView>( eventView )
+		
+		Return Cast<ProjectBrowserView.Node>( projTree?.FindNodeAtPoint( eventLocation ) )
+	End
+	
+	Method GetHolder:ProjectBrowserView( view:View ) Override
+	
+		Return Cast<ProjectBrowserView>( view )
+	End
+	
+End

+ 179 - 70
view/ProjectView.monkey2

@@ -56,6 +56,19 @@ Class ProjectView Extends ScrollView
 		Return ""
 		Return ""
 	End
 	End
 	
 	
+	Method OnFileDropped:Bool( path:String )
+		
+		Local ok:=_projBrowser.OnFileDropped( path )
+		If Not ok
+			Local isFolder:=GetFileType( path )=FileType.Directory
+			If isFolder
+				ok=True
+				OpenProject( path )
+			Endif
+		Endif
+		Return ok
+	End
+	
 	Method OpenProject:Bool( dir:String )
 	Method OpenProject:Bool( dir:String )
 	
 	
 		dir=StripSlashes( dir )
 		dir=StripSlashes( dir )
@@ -145,6 +158,64 @@ Class ProjectView Extends ScrollView
 	Field _builder:IModuleBuilder
 	Field _builder:IModuleBuilder
 	Field _projBrowser:ProjectBrowserView
 	Field _projBrowser:ProjectBrowserView
 	
 	
+	Field _cutPath:String,_copyPath:String
+	
+	Method OnCut( path:String )
+		
+		_copyPath=""
+		_cutPath=path
+	End
+	
+	Method OnCopy( path:String )
+		
+		_cutPath=""
+		_copyPath=path
+	End
+	
+	Method OnPaste:Bool( path:String )
+		
+		Local ok:=True
+		
+		If Not path.EndsWith( "/" ) Then path+="/"
+		
+		Local cut:=(_cutPath<>"")
+		Local srcPath:=cut ? _cutPath Else _copyPath
+		
+		Local isFolder:=(GetFileType( srcPath )=FileType.Directory)
+		
+		If isFolder And path.StartsWith( srcPath )
+			
+			Alert( "Can't paste into the same or nested folder!","Paste element" )
+			Return False
+		Endif
+		
+		Local name:=StripDir( srcPath )
+		
+		Local dest:=path+name
+		Local exists:=(GetFileType( dest )<>FileType.None)
+		
+		If exists
+			Local s:=RequestString( "New name:","Element already exists",name )
+			If Not s Or s=name Return False
+			name=s
+			dest=path+name
+		Endif
+		
+		If isFolder
+			ok=CopyDir( srcPath,dest )
+			If ok And cut Then DeleteDir( srcPath,True )
+		Else
+			ok=CopyFile( srcPath,dest )
+			If ok And cut Then DeleteFile( srcPath )
+		Endif
+		
+		If Not ok Then Alert( "Can't copy~n"+srcPath+"~ninto~n"+dest,"Paste element" )
+		
+		_cutPath=""
+		
+		Return ok
+	End
+	
 	Method DeleteItem( browser:ProjectBrowserView,path:String,node:TreeView.Node )
 	Method DeleteItem( browser:ProjectBrowserView,path:String,node:TreeView.Node )
 		
 		
 		Local nodeToRefresh:=Cast<ProjectBrowserView.Node>( node.Parent )
 		Local nodeToRefresh:=Cast<ProjectBrowserView.Node>( node.Parent )
@@ -285,187 +356,225 @@ Class ProjectView Extends ScrollView
 		
 		
 			Local menu:=New MenuExt
 			Local menu:=New MenuExt
 			Local path:=node.Path
 			Local path:=node.Path
-		
+			Local pasteAction:Action
+			Local isFolder:=False
+			
 			Select GetFileType( path )
 			Select GetFileType( path )
 			Case FileType.Directory
 			Case FileType.Directory
-		
+				
+				isFolder=True
+				
 				menu.AddAction( "Find..." ).Triggered=Lambda()
 				menu.AddAction( "Find..." ).Triggered=Lambda()
-		
+					
 					RequestedFindInFolder( path )
 					RequestedFindInFolder( path )
 				End
 				End
-		
+				
 				menu.AddSeparator()
 				menu.AddSeparator()
-		
+				
 				menu.AddAction( "New class..." ).Triggered=Lambda()
 				menu.AddAction( "New class..." ).Triggered=Lambda()
-		
+					
 					Local d:=New GenerateClassDialog( path )
 					Local d:=New GenerateClassDialog( path )
 					d.Generated+=Lambda( filePath:String,fileContent:String )
 					d.Generated+=Lambda( filePath:String,fileContent:String )
-		
+						
 						If CreateFileInternal( filePath,fileContent )
 						If CreateFileInternal( filePath,fileContent )
-		
+							
 							MainWindow.OpenDocument( filePath )
 							MainWindow.OpenDocument( filePath )
 							browser.Refresh( node )
 							browser.Refresh( node )
 						Endif
 						Endif
 					End
 					End
 					d.ShowModal()
 					d.ShowModal()
 				End
 				End
-		
+				
 				menu.AddSeparator()
 				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
-		
+					
 					Local tpath:=path+"/"+file
 					Local tpath:=path+"/"+file
-		
+					
 					CreateFileInternal( tpath )
 					CreateFileInternal( tpath )
-		
+					
 					browser.Refresh( node )
 					browser.Refresh( node )
 				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:" )
 					If Not dir Return
 					If Not dir Return
-		
+					
 					Local tpath:=path+"/"+dir
 					Local tpath:=path+"/"+dir
-		
+					
 					If GetFileType( tpath )<>FileType.None
 					If GetFileType( tpath )<>FileType.None
 						Alert( "A file or directory already exists at '"+tpath+"'" )
 						Alert( "A file or directory already exists at '"+tpath+"'" )
 						Return
 						Return
 					End
 					End
-		
+					
 					If Not CreateDir( tpath )
 					If Not CreateDir( tpath )
 						Alert( "Failed to create folder '"+dir+"'" )
 						Alert( "Failed to create folder '"+dir+"'" )
 						Return
 						Return
 					Endif
 					Endif
-		
+					
 					browser.Refresh( node )
 					browser.Refresh( node )
 				End
 				End
-		
+				
 				menu.AddAction( "Delete" ).Triggered=Lambda()
 				menu.AddAction( "Delete" ).Triggered=Lambda()
-		
+					
 					DeleteItem( browser,path,node )
 					DeleteItem( browser,path,node )
 				End
 				End
-		
+				
 				menu.AddSeparator()
 				menu.AddSeparator()
-		
+				
 				If browser.IsProjectNode( node ) ' root node
 				If browser.IsProjectNode( node ) ' root node
-		
+					
 					menu.AddAction( "Close project" ).Triggered=Lambda()
 					menu.AddAction( "Close project" ).Triggered=Lambda()
-		
+						
 						CloseProject( path )
 						CloseProject( path )
 					End
 					End
-		
+					
 					menu.AddAction( "Clean (delete .buildv)" ).Triggered=Lambda()
 					menu.AddAction( "Clean (delete .buildv)" ).Triggered=Lambda()
-		
+						
 						If Not RequestOkay( "Really delete all '.buildv' folders?" ) Return
 						If Not RequestOkay( "Really delete all '.buildv' folders?" ) Return
-		
+						
 						Local changes:=CleanProject( path )
 						Local changes:=CleanProject( path )
 						If changes Then browser.Refresh( node )
 						If changes Then browser.Refresh( node )
 					End
 					End
 				Else
 				Else
-		
+					
 					menu.AddAction( "Open as a project" ).Triggered=Lambda()
 					menu.AddAction( "Open as a project" ).Triggered=Lambda()
-		
+					
 						OpenProject( path )
 						OpenProject( path )
 					End
 					End
 				Endif
 				Endif
-		
+				
 				' update / rebuild module
 				' update / rebuild module
 				path=path.Replace( "\","/" )
 				path=path.Replace( "\","/" )
 				Local name := path.Slice( path.FindLast( "/")+1 )
 				Local name := path.Slice( path.FindLast( "/")+1 )
 				Local file:=path+"/module.json"
 				Local file:=path+"/module.json"
-		
+				
 				If path.Contains( "/modules/") And GetFileType( file )=FileType.File
 				If path.Contains( "/modules/") And GetFileType( file )=FileType.File
-		
+					
 					menu.AddSeparator()
 					menu.AddSeparator()
-		
+					
 					menu.AddAction( "Update / Rebuild "+name ).Triggered=Lambda()
 					menu.AddAction( "Update / Rebuild "+name ).Triggered=Lambda()
-		
-						_builder.BuildModules( True,name )
+						
+						_builder.BuildModules( name )
 					End
 					End
-		
+					
 				Endif
 				Endif
-		
+				
 				' update all modules
 				' update all modules
 				Local path2:=MainWindow.ModsPath
 				Local path2:=MainWindow.ModsPath
 				If path2.EndsWith( "/" ) Then path2=path2.Slice( 0,path2.Length-1 )
 				If path2.EndsWith( "/" ) Then path2=path2.Slice( 0,path2.Length-1 )
-		
+				
 				If path = path2
 				If path = path2
-		
+					
 					menu.AddSeparator()
 					menu.AddSeparator()
-		
+					
 					menu.AddAction( "Update / Rebuild modules" ).Triggered=Lambda()
 					menu.AddAction( "Update / Rebuild modules" ).Triggered=Lambda()
-		
-						_builder.BuildModules( False )
+						
+						_builder.BuildModules()
 					End
 					End
-		
+					
 				Endif
 				Endif
-		
+				
 				' bananas showcase
 				' bananas showcase
 				If IsBananasShowcaseAvailable()
 				If IsBananasShowcaseAvailable()
 					path2=Prefs.MonkeyRootPath+"bananas"
 					path2=Prefs.MonkeyRootPath+"bananas"
 					If path = path2
 					If path = path2
-		
+						
 						menu.AddSeparator()
 						menu.AddSeparator()
-		
+						
 						menu.AddAction( "Open bananas showcase" ).Triggered=Lambda()
 						menu.AddAction( "Open bananas showcase" ).Triggered=Lambda()
-		
+							
 							MainWindow.ShowBananasShowcase()
 							MainWindow.ShowBananasShowcase()
 						End
 						End
-		
+						
 					Endif
 					Endif
 				Endif
 				Endif
-		
+				
 				menu.AddSeparator()
 				menu.AddSeparator()
-		
+				
 				menu.AddAction( "Open on Desktop" ).Triggered=Lambda()
 				menu.AddAction( "Open on Desktop" ).Triggered=Lambda()
-		
+					
 					requesters.OpenUrl( path )
 					requesters.OpenUrl( path )
 				End
 				End
-		
-		
+			
+			
 			Case FileType.File
 			Case FileType.File
-		
+				
 				menu.AddAction( "Open on Desktop" ).Triggered=Lambda()
 				menu.AddAction( "Open on Desktop" ).Triggered=Lambda()
-		
+					
 					requesters.OpenUrl( path )
 					requesters.OpenUrl( path )
 				End
 				End
-		
+				
 				menu.AddSeparator()
 				menu.AddSeparator()
-		
+				
 				menu.AddAction( "Rename" ).Triggered=Lambda()
 				menu.AddAction( "Rename" ).Triggered=Lambda()
-		
+					
 					Local oldName:=StripDir( path )
 					Local oldName:=StripDir( path )
 					Local name:=RequestString( "Enter new name:","Ranaming '"+oldName+"'",oldName )
 					Local name:=RequestString( "Enter new name:","Ranaming '"+oldName+"'",oldName )
 					If Not name Or name=oldName Return
 					If Not name Or name=oldName Return
-		
+					
 					Local newPath:=ExtractDir( path )+name
 					Local newPath:=ExtractDir( path )+name
+					
+					If FileExists( newPath )
+						Alert( "File already exists! Path: '"+newPath+"'" )
+						Return
+					Endif
+					
 					If CopyFile( path,newPath )
 					If CopyFile( path,newPath )
-		
+						
 						DeleteFile( path )
 						DeleteFile( path )
-		
+						
 						browser.Refresh( node.Parent )
 						browser.Refresh( node.Parent )
 						Return
 						Return
 					Endif
 					Endif
-		
+					
 					Alert( "Failed to rename file: '"+path+"'" )
 					Alert( "Failed to rename file: '"+path+"'" )
 				End
 				End
-		
+				
 				menu.AddSeparator()
 				menu.AddSeparator()
-		
+				
 				menu.AddAction( "Delete" ).Triggered=Lambda()
 				menu.AddAction( "Delete" ).Triggered=Lambda()
-		
+					
 					DeleteItem( browser,path,node )
 					DeleteItem( browser,path,node )
 				End
 				End
-		
+			
 			Default
 			Default
-		
+				
 				Return
 				Return
 			End
 			End
-		
+			
+			' cut / copy / paste
+			menu.AddSeparator()
+			
+			menu.AddAction( "Cut" ).Triggered=Lambda()
+			
+				OnCut( path )
+			End
+			
+			menu.AddAction( "Copy" ).Triggered=Lambda()
+			
+				OnCopy( path )
+			End
+			
+			pasteAction=menu.AddAction( "Paste" )
+			pasteAction.Triggered=Lambda()
+				
+				New Fiber( Lambda()
+					
+					Local ok:=OnPaste( path )
+					If ok
+						Local n:=browser.IsProjectNode( node ) ? node Else node.Parent
+						browser.Refresh( n )
+					Endif
+				End )
+				
+			End
+			pasteAction.Enabled=(_cutPath Or _copyPath) And isFolder
+			
 			menu.Open()
 			menu.Open()
 		End
 		End
 		
 		

+ 83 - 179
view/TabViewExt.monkey2

@@ -20,7 +20,8 @@ Class ScrollViewTabs Extends ScrollView
 		
 		
 			Scroll-=delta
 			Scroll-=delta
 		
 		
-			If scroll<>Scroll event.Eat()
+			'If scroll<>Scroll event.Eat()
+			event.Eat()
 			Return
 			Return
 		End
 		End
 		
 		
@@ -34,7 +35,7 @@ End
 ' full copy of mojox.TabView
 ' full copy of mojox.TabView
 ' can't extend it, all I need is private there
 ' can't extend it, all I need is private there
 '
 '
-Class TabViewExt Extends DockingView
+Class TabViewExt Extends DockingView Implements IDraggableHolder
 
 
 	#rem monkeydoc Invoked when the current tab changes.
 	#rem monkeydoc Invoked when the current tab changes.
 	#end
 	#end
@@ -107,10 +108,60 @@ Class TabViewExt Extends DockingView
 	Function CreateDraggableTab:TabButtonExt( text:String,view:View,possibleParents:TabViewExt[],icon:Image=Null,closable:Bool=False )
 	Function CreateDraggableTab:TabButtonExt( text:String,view:View,possibleParents:TabViewExt[],icon:Image=Null,closable:Bool=False )
 		
 		
 		Local tab:=New TabButtonExt( text,icon,view,closable,Null )
 		Local tab:=New TabButtonExt( text,icon,view,closable,Null )
-		tab.PossibleParentDocks=possibleParents
+		tab.PossibleHolders=possibleParents
 		Return tab
 		Return tab
 	End
 	End
 	
 	
+	Method Attach( item:Object,eventLocation:Vec2i )
+		
+		Local tab:=Cast<TabButtonExt>( item )
+		AddTab( tab )
+		MakeCurrent( tab,True )
+		
+		_vis=True
+		_curIndex=CurrentIndex-1 '-1 for [+] tab
+	End
+	
+	Method Detach:View( item:Object )
+		
+		Local tab:=Cast<TabButtonExt>( item )
+		RemoveTab( tab )
+		tab.Selected=True
+		Return tab
+	End
+	
+	Method OnDragStarted()
+		
+		_dragDropMode=True
+		_curIndex=CurrentIndex
+		_vis=Visible
+		Visible=True
+		If Not _placeHolderTab
+			Local v:=New Label ("[Drop tab here]")
+			v.Style=GetStyle( "TabsDropArea","Label" )
+			v.Layout="fill"
+			v.Gravity=New Vec2f( .5,.5 )
+			_placeHolderTab=AddTab( "[+]",v,True )
+			_placeHolderContent=v
+		Else
+			AddTab( _placeHolderTab,True )
+		Endif
+	End
+	
+	Method OnDragEnded()
+		
+		If Not _dragDropMode Return
+		
+		_dragDropMode=False
+		
+		RemoveTab( _placeHolderTab )
+		_placeHolderTab=Null
+'		
+		Visible=(_vis And NumTabs>0)
+		
+		If _curIndex>=0 Then CurrentIndex=_curIndex
+	End
+	
 	#rem monkeydoc Tab view flags.
 	#rem monkeydoc Tab view flags.
 	#end
 	#end
 	Property Flags:TabViewFlags()
 	Property Flags:TabViewFlags()
@@ -347,8 +398,9 @@ Class TabViewExt Extends DockingView
 	End
 	End
 	
 	
 	Method SetTabText( view:View,text:String )
 	Method SetTabText( view:View,text:String )
-	
-		SetTabText( TabIndex( view ),text )
+		
+		Local index:=TabIndex( view )
+		If index>=0 Then SetTabText( index,text )
 	End
 	End
 	
 	
 	#rem monkeydoc Sets a tab's icon.
 	#rem monkeydoc Sets a tab's icon.
@@ -378,38 +430,6 @@ Class TabViewExt Extends DockingView
 		Next
 		Next
 	End
 	End
 	
 	
-	Method ShowDragPlaceHolder()
-		
-		_dragDropMode=True
-		_curIndex=CurrentIndex
-		_vis=Visible
-		Visible=True
-		If Not _placeHolderTab
-			Local v:=New Label ("[Drop tab here]")
-			v.Style=GetStyle( "TabsDropArea","Label" )
-			v.Layout="fill"
-			v.Gravity=New Vec2f( .5,.5 )
-			_placeHolderTab=AddTab( "[+]",v,True )
-			_placeHolderContent=v
-		Else
-			AddTab( _placeHolderTab,True )
-		Endif
-	End
-	
-	Method HideDragPlaceHolder()
-		
-		If Not _dragDropMode Return
-		
-		_dragDropMode=False
-		
-		RemoveTab( _placeHolderTab )
-		_placeHolderTab=Null
-'		
-		Visible=(_vis And NumTabs>0)
-		
-		If _curIndex>=0 Then CurrentIndex=_curIndex
-	End
-	
 	
 	
 	Protected
 	Protected
 	
 	
@@ -516,7 +536,7 @@ Class TabViewExt Extends DockingView
 End
 End
 
 
 
 
-Class TabButtonExt Extends TabButton
+Class TabButtonExt Extends TabButton Implements IDraggableItem<TabViewExt>
 	
 	
 	Field ActiveChanged:Void()
 	Field ActiveChanged:Void()
 	
 	
@@ -524,17 +544,18 @@ Class TabButtonExt Extends TabButton
 		
 		
 		Super.New( text,icon,view,closable )
 		Super.New( text,icon,view,closable )
 		_parentDock=parentDock
 		_parentDock=parentDock
+		_closable=closable
 	End
 	End
 	
 	
 	Property Detachable:Bool()
 	Property Detachable:Bool()
-		Return PossibleParentDocks<>Null
+		Return PossibleHolders<>Null
 	End
 	End
 	
 	
-	Property ParentDock:TabViewExt()
+	Property CurrentHolder:TabViewExt()
 		Return _parentDock
 		Return _parentDock
 	End
 	End
 	
 	
-	Property PossibleParentDocks:TabViewExt[]()
+	Property PossibleHolders:TabViewExt[]()
 		Return _possibleParentDocks
 		Return _possibleParentDocks
 	Setter( value:TabViewExt[] )
 	Setter( value:TabViewExt[] )
 		_possibleParentDocks=value
 		_possibleParentDocks=value
@@ -542,22 +563,7 @@ Class TabButtonExt Extends TabButton
 	
 	
 	Method Activate()
 	Method Activate()
 		
 		
-		Local dock:=ParentDock
-		If dock Then dock.MakeCurrent( Text )
-	End
-	
-	Method TryDropTo( tabDock:TabViewExt )
-		
-		If Not CanDropTo( tabDock )
-			tabDock=_parentDock
-		Endif
-		
-		_parentDock.Visible=(_parentDock.NumTabs>0)
-		_parentDock=tabDock
-		tabDock.AddTab( Self )
-		tabDock.Visible=True
-		
-		Activate()
+		CurrentHolder?.MakeCurrent( Text )
 	End
 	End
 	
 	
 	Property IsActive:Bool()
 	Property IsActive:Bool()
@@ -581,25 +587,26 @@ Class TabButtonExt Extends TabButton
 		Style=GetStyle( _locked ? "TabButtonLocked" Else "TabButton" )
 		Style=GetStyle( _locked ? "TabButtonLocked" Else "TabButton" )
 	End
 	End
 	
 	
+	Method OnMouseEvent( event:MouseEvent ) Override
+		
+		If _closable And 
+			event.Type=EventType.MouseUp And 
+			event.Button=MouseButton.Middle
+			
+			CloseClicked()
+			event.Eat()
+			Return
+		Endif
+		
+		Super.OnMouseEvent( event )
+	End
+	
 	
 	
 	Private
 	Private
 	
 	
 	Field _possibleParentDocks:TabViewExt[]
 	Field _possibleParentDocks:TabViewExt[]
 	Field _locked:Bool
 	Field _locked:Bool
-	
-	Method CanDropTo:Bool( tabDock:TabViewExt )
-	
-		If Not tabDock Print "if 1" ; Return False
-		If Not _possibleParentDocks Print "if 1" ; Return False
-	
-		For Local d:=Eachin _possibleParentDocks
-	
-			If d=tabDock Return True
-		Next
-		Print "false"
-		Return False
-	End
-	
+	Field _closable:Bool
 End
 End
 
 
 
 
@@ -623,119 +630,16 @@ Class TabButtonExt_Bridge Extends TabButtonExt Abstract
 End
 End
 
 
 
 
-Class DraggableTabsListener
+Class DraggableTabsListener Extends DraggableViewListener<TabButtonExt,TabViewExt>
 	
 	
-	Method New()
+	Method GetItem:TabButtonExt( eventView:View,eventLocation:Vec2i ) Override
 		
 		
-		App.MouseEventFilter+=OnMouseEvent
+		Return Cast<TabButtonExt>( eventView )
 	End
 	End
 	
 	
-	Private
-	
-	Global _label:Label
-	Global _tab:TabButtonExt
-	Global _pressedPos:Vec2i
-	Global _detached:Bool
-	
-	Function OnMouseEvent( event:MouseEvent )
-	
-		Select event.Type
-			
-			Case EventType.MouseDown
-				
-				_tab=Cast<TabButtonExt>( event.View )
-				If Not _tab Return
-				
-				If Not _tab.Detachable
-					_tab=Null
-					Return
-				Endif
-				
-				_pressedPos=Mouse.Location
-				
-			
-			Case EventType.MouseMove
-			
-				If Not _tab Return
-				
-				If _detached
-					Local r:=_tab.Frame
-					Local sz:=r.Size
-					r.TopLeft=Mouse.Location+New Vec2i( 0,-10 )
-					r.BottomRight=r.TopLeft+sz
-					_tab.Frame=r
-					App.RequestRender()
-					Return
-				Endif
-				
-				Local dy:Float=Abs(Mouse.Y-_pressedPos.y)
-				If dy>10.0*App.Theme.Scale.y
-					Detach()
-				Endif
-				
-				
-			Case EventType.MouseUp
-				
-				If Not _detached 
-					_tab=Null
-					Return
-				Endif
-				
-				MainWindow.RemoveChildView( _tab )
-				
-				Local dock:TabViewExt=Null
-				Local v:=App.ActiveViewAtMouseLocation()
-				While v
-					Local d:=Cast<TabViewExt>( v )
-					If d
-						dock=d
-						Exit
-					Endif
-					v=v.Parent
-				Wend
-				
-				If _tab.PossibleParentDocks
-					For Local d:=Eachin _tab.PossibleParentDocks
-						d.HideDragPlaceHolder()
-					Next
-				Endif
-				
-				_tab.TryDropTo( dock )
-				
-				_tab=Null
-				_detached=False
-			
-		End
-	
-	End
-	
-	Function Detach()
-		
-		_detached=True
-		
-'		If Not _label
-'			_label=New Label
-'			_label.Layout="float"
-'			_label.MaxSize=New Vec2i( 40,100 )
-'			MainWindow.AddChildView( _label )
-'		Endif
-'		_label.Text=_tab.Text
-'		_label.Visible=True
-		'Local size:=_label.MeasureLayoutSize()
-		'_label.Frame=New Recti( Mouse.Location,Mouse.Location+size)
-		
-		_tab.ParentDock.RemoveTab( _tab )
-		MainWindow.AddChildView( _tab )
-		_tab.Selected=True
-		
-		If Not _tab.PossibleParentDocks Return
-		
-		For Local d:=Eachin _tab.PossibleParentDocks
-			d.ShowDragPlaceHolder()
-		Next
+	Method GetHolder:TabViewExt( view:View ) Override
 		
 		
+		Return FindViewInHierarchy<TabViewExt>( view )
 	End
 	End
 	
 	
-	
 End
 End
-	

+ 31 - 7
view/Ted2CodeTextView.monkey2

@@ -3,15 +3,31 @@ Namespace ted2go
 
 
 
 
 Class Ted2CodeTextView Extends CodeTextView
 Class Ted2CodeTextView Extends CodeTextView
-
+	
+	Method New( doc:Ted2Document )
+		
+		_document=doc
+		
+		AdjustFileType()
+		
+		_document.Renamed+=Lambda( newPath:String,oldPath:String )
+			
+			AdjustFileType()
+		End
+	End
+	
 	Property FileType:String() 'where else we can store this type?
 	Property FileType:String() 'where else we can store this type?
-		return _type
+		
+		Return _type
+		
 	Setter( value:String )
 	Setter( value:String )
+		
+		If value=_type Return
 		_type=value
 		_type=value
-		Keywords = KeywordsManager.Get(_type)
-		Highlighter = HighlightersManager.Get(_type)
-		Formatter = FormattersManager.Get(_type)
-		Document.TextHighlighter = Highlighter.Painter
+		Keywords=KeywordsManager.Get(_type)
+		Highlighter=HighlightersManager.Get(_type)
+		Formatter=FormattersManager.Get(_type)
+		Document.TextHighlighter=Highlighter.Painter
 	End
 	End
 	
 	
 	Property FilePath:String()
 	Property FilePath:String()
@@ -31,6 +47,14 @@ Class Ted2CodeTextView Extends CodeTextView
 	
 	
 	Protected
 	Protected
 	
 	
+	Field _document:Ted2Document
+	
+	Method AdjustFileType()
+		
+		FileType=_document.FileExtension
+		FilePath=_document.Path
+	End
+	
 	Method OnKeyEvent( event:KeyEvent ) Override
 	Method OnKeyEvent( event:KeyEvent ) Override
 	
 	
 		TextViewKeyEventFilter.FilterKeyEvent( event,Self,FileType )
 		TextViewKeyEventFilter.FilterKeyEvent( event,Self,FileType )
@@ -40,7 +64,7 @@ Class Ted2CodeTextView Extends CodeTextView
 		Endif
 		Endif
 		
 		
 	End
 	End
-
+	
 	Private
 	Private
 	
 	
 	Field _type:String
 	Field _type:String

+ 1 - 1
view/ToolBarViewExt.monkey2

@@ -21,7 +21,7 @@ Class ToolBarExt Extends ToolBar
 	End
 	End
 	
 	
 	Method AddIconicButton:MultiIconToolButton( icons:Image[],trigger:Void(),hint:String=Null )
 	Method AddIconicButton:MultiIconToolButton( icons:Image[],trigger:Void(),hint:String=Null )
-	
+		
 		Local act:=New Action( Null )
 		Local act:=New Action( Null )
 		act.Triggered=trigger
 		act.Triggered=trigger
 		Local b:=New MultiIconToolButton( act,icons,hint )
 		Local b:=New MultiIconToolButton( act,icons,hint )

+ 113 - 10
view/TreeViewExt.monkey2

@@ -15,7 +15,7 @@ Class TreeViewExt Extends TreeView
 		
 		
 		Super.New()
 		Super.New()
 		
 		
-		Super.NodeClicked+=Lambda( node:Node )
+		NodeClicked2+=Lambda( node:Node )
 			
 			
 			If _singleClickExpanding
 			If _singleClickExpanding
 				If TrySwitchExpandingState( node ) Return
 				If TrySwitchExpandingState( node ) Return
@@ -41,6 +41,8 @@ Class TreeViewExt Extends TreeView
 		
 		
 		Super.NodeExpanded+=Lambda( node:Node )
 		Super.NodeExpanded+=Lambda( node:Node )
 			
 			
+			_expandStateChanged=True
+			
 			_expander.Store( node )
 			_expander.Store( node )
 			OnSelect( node )
 			OnSelect( node )
 			NodeExpanded( node )
 			NodeExpanded( node )
@@ -48,6 +50,8 @@ Class TreeViewExt Extends TreeView
 		
 		
 		Super.NodeCollapsed+=Lambda( node:Node )
 		Super.NodeCollapsed+=Lambda( node:Node )
 			
 			
+			_expandStateChanged=True
+			
 			_expander.Store( node )
 			_expander.Store( node )
 			OnSelect( node )
 			OnSelect( node )
 			NodeCollapsed( node )
 			NodeCollapsed( node )
@@ -62,9 +66,10 @@ Class TreeViewExt Extends TreeView
 		
 		
 	Setter( value:TreeView.Node )
 	Setter( value:TreeView.Node )
 		
 		
-		If _sel=value Return
-		_sel=value
-		SelectedChanged( _sel )
+		If _sel<>value
+			_sel=value
+			SelectedChanged( _sel )
+		Endif
 		
 		
 		EnsureVisible( _sel )
 		EnsureVisible( _sel )
 		
 		
@@ -91,6 +96,15 @@ Class TreeViewExt Extends TreeView
 		_expander.LoadState( jobj,jkey )
 		_expander.LoadState( jobj,jkey )
 	End
 	End
 	
 	
+	Method FindByText:TreeView.Node( text:String,recursive:Bool=False )
+	
+		Return FindSubNode( RootNode,
+						recursive,
+						Lambda:Bool( n:TreeView.Node )
+							Return n.Text=text
+						End )
+	End
+	
 	Method FindSubNode:TreeView.Node( text:String,whereNode:TreeView.Node,recursive:Bool=False )
 	Method FindSubNode:TreeView.Node( text:String,whereNode:TreeView.Node,recursive:Bool=False )
 		
 		
 		Return FindSubNode( whereNode,
 		Return FindSubNode( whereNode,
@@ -132,6 +146,22 @@ Class TreeViewExt Extends TreeView
 		If n Then Selected=n
 		If n Then Selected=n
 	End
 	End
 	
 	
+	Method SelectByPathEnds( pathEnding:String )
+	
+		Local n:=FindSubNode( RootNode,
+						True,
+						Lambda:Bool( n:TreeView.Node )
+							Return GetNodePath( n ).EndsWith( pathEnding )
+						End )
+	
+		If n Then Selected=n
+	End
+	
+	Method Sort()
+	
+		SortNode( RootNode )
+	End
+	
 	
 	
 	Protected
 	Protected
 	
 	
@@ -165,19 +195,39 @@ Class TreeViewExt Extends TreeView
 				' make scroll little faster
 				' make scroll little faster
 				Scroll-=New Vec2i( 0,RenderStyle.Font.Height*event.Wheel.Y*2 )
 				Scroll-=New Vec2i( 0,RenderStyle.Font.Height*event.Wheel.Y*2 )
 				Return
 				Return
-		
+			
+			Case EventType.MouseClick
+				
+				_expandStateChanged=False
+				
+				
+			Case EventType.MouseUp
+				
+				If event.Button=MouseButton.Left
+					
+					Local p:=TransformWindowPointToView( Mouse.Location )
+					Local node:=FindNodeAtPoint( p )
+					If node And Not _expandStateChanged Then NodeClicked2( node )
+				Endif
 		End
 		End
 		
 		
 		Super.OnContentMouseEvent( event )
 		Super.OnContentMouseEvent( event )
 		
 		
 	End
 	End
 	
 	
+'	Method PrintExpanded()
+'		
+'		_expander.PrintExpanded()
+'	End
 	
 	
 	Private
 	Private
 	
 	
 	Field _sel:TreeView.Node
 	Field _sel:TreeView.Node
 	Field _selColor:Color
 	Field _selColor:Color
 	Field _singleClickExpanding:Bool
 	Field _singleClickExpanding:Bool
+	Field _expandStateChanged:Bool
+	
+	Field NodeClicked2:Void( node:Node )
 	
 	
 	Method TrySwitchExpandingState:Bool( node:TreeView.Node )
 	Method TrySwitchExpandingState:Bool( node:TreeView.Node )
 		
 		
@@ -202,15 +252,15 @@ Class TreeViewExt Extends TreeView
 	End
 	End
 	
 	
 	Method EnsureVisible( node:TreeView.Node )
 	Method EnsureVisible( node:TreeView.Node )
-		
+	
 		If Not node Return
 		If Not node Return
-		
+	
 		Local n:=node.Parent
 		Local n:=node.Parent
 		While n
 		While n
 			n.Expanded=True
 			n.Expanded=True
 			n=n.Parent
 			n=n.Parent
 		Wend
 		Wend
-		
+	
 		' scroll Y only 
 		' scroll Y only 
 		Local sx:=Scroll.x
 		Local sx:=Scroll.x
 		Local scroll:=Scroll
 		Local scroll:=Scroll
@@ -219,17 +269,53 @@ Class TreeViewExt Extends TreeView
 		Scroll=scroll
 		Scroll=scroll
 	End
 	End
 	
 	
+	Method SortNode( node:TreeView.Node )
+		
+		If node.Children.Length=0 Return
+		
+		Local children:=New Stack<TreeView.Node>
+		children+=node.Children
+		
+		children.Sort( Lambda:Int( lhs:TreeView.Node,rhs:TreeView.Node )
+			
+			Return lhs.Text<=>rhs.Text
+		End )
+		
+		node.RemoveAllChildren()
+		
+		For Local n:=Eachin children
+			node.AddChild( n )
+			
+			SortNode( n )
+		Next
+	End
+	
 End
 End
 
 
 
 
 Class TreeViewExpander
 Class TreeViewExpander
 	
 	
+	Function ExpandParents( node:TreeView.Node )
+		
+		Local p:=node.Parent
+		While p<>Null
+			p.Expanded=True
+			p=p.Parent
+		Wend
+	End
+	
 	Method Store( node:TreeView.Node,recurse:Bool=False )
 	Method Store( node:TreeView.Node,recurse:Bool=False )
 	
 	
 		Local key:=GetNodePath( node )
 		Local key:=GetNodePath( node )
 	
 	
 		If node.Expanded
 		If node.Expanded
 			_expands[key]=True
 			_expands[key]=True
+			' grab all parents states
+			Local p:=node.Parent
+			While p<>Null
+				If p.Expanded Then _expands[GetNodePath( p )]=True
+				p=p.Parent
+			Wend
 		Else
 		Else
 			_expands.Remove( key )
 			_expands.Remove( key )
 		Endif
 		Endif
@@ -245,7 +331,7 @@ Class TreeViewExpander
 	
 	
 		Local key:=GetNodePath( node )
 		Local key:=GetNodePath( node )
 		
 		
-		node.Expanded = _expands.Contains( key ) ? True Else False
+		node.Expanded=_expands.Contains( key )
 		
 		
 		If Not recurse Return
 		If Not recurse Return
 		
 		
@@ -277,7 +363,14 @@ Class TreeViewExpander
 		Next
 		Next
 	End
 	End
 	
 	
-	Private
+	Method PrintExpanded()
+		
+		For Local key:=Eachin _expands.Keys
+			If _expands[key] Print "expanded: "+key
+		Next
+	End
+	
+	Protected
 	
 	
 	Field _expands:=New StringMap<Bool>
 	Field _expands:=New StringMap<Bool>
 	
 	
@@ -319,3 +412,13 @@ Function GetNodePath:String( node:TreeView.Node )
 	Wend
 	Wend
 	Return s
 	Return s
 End
 End
+
+Function GetNodeDeepLevel:Int( node:TreeView.Node )
+	
+	Local level:=-1
+	While node
+		level+=1
+		node=node.Parent
+	Wend
+	Return level
+End