2019-08-23 11:56:54 -07:00
using System ;
2020-04-29 06:40:03 -07:00
using System.Collections ;
2019-08-23 11:56:54 -07:00
using System.Text ;
using Beefy.widgets ;
using Beefy.gfx ;
using Beefy.theme ;
using Beefy.events ;
using Beefy.theme.dark ;
using System.Threading ;
using System.IO ;
using Beefy.utils ;
using Beefy ;
using IDE.Compiler ;
using System.Diagnostics ;
using IDE.Util ;
namespace IDE.ui
{
public class ProjectListViewItem : DarkListViewItem
{
public float mLabelOffset ;
public Object mRefObject ;
public bool mSortDirty ;
public bool mWantsRehup ;
2020-03-28 14:26:59 -07:00
public override void RehupScale ( float oldScale , float newScale )
{
base . RehupScale ( oldScale , newScale ) ;
2020-03-29 10:17:28 -07:00
if ( mLabelOffset ! = 0 )
mLabelOffset = GS ! ( - 16 ) ;
2020-03-28 14:26:59 -07:00
}
2019-08-23 11:56:54 -07:00
protected override float GetLabelOffset ( )
{
return mLabelOffset ;
}
public override float ResizeComponents ( float xOffset )
{
return base . ResizeComponents ( xOffset ) ;
}
public override void DrawSelect ( Graphics g )
{
let projectPanel = ( ( ProjectListView ) mListView ) . mProjectPanel ;
using ( g . PushColor ( ( mListView . mParent . mHasFocus | | ( projectPanel . mMenuWidget ! = null ) ) ? 0xFFFFFFFF : 0x80FFFFFF ) )
base . DrawSelect ( g ) ;
}
public override void Draw ( Graphics g )
{
2020-08-05 05:37:05 -07:00
uint32 color = DarkTheme . COLOR_TEXT ;
2019-08-23 11:56:54 -07:00
let projectPanel = ( ( ProjectListView ) mListView ) . mProjectPanel ;
ProjectItem projectItem ;
projectPanel . mListViewToProjectMap . TryGetValue ( this , out projectItem ) ;
if ( ( projectItem ! = null ) & & ( projectItem . mParentFolder ! = null ) )
{
if ( projectItem . mIncludeKind = = . Manual )
2020-10-05 14:25:55 -07:00
color = Color . Mult ( color , gApp . mSettings . mUISettings . mColors . mWorkspaceManualIncludeText ) ;
2019-08-23 11:56:54 -07:00
else if ( projectItem . mIncludeKind = = . Ignore )
2020-10-05 14:25:55 -07:00
color = Color . Mult ( color , gApp . mSettings . mUISettings . mColors . mWorkspaceIgnoredText ) ;
2020-01-15 08:33:16 -08:00
if ( let projectSource = projectItem as ProjectSource )
{
if ( projectSource . mLoadFailed )
2020-10-05 14:25:55 -07:00
color = Color . Mult ( color , gApp . mSettings . mUISettings . mColors . mWorkspaceFailedText ) ;
2020-01-15 08:33:16 -08:00
}
2019-08-23 11:56:54 -07:00
mTextColor = color ;
}
base . Draw ( g ) ;
if ( mRefObject ! = null )
{
float changeX = g . mFont . GetWidth ( mLabel ) + mLabelOffset + LabelX + GS ! ( 1 ) ;
bool hasChanged = false ;
var workspace = mRefObject as Workspace ;
if ( workspace ! = null )
hasChanged = workspace . mHasChanged ;
var project = mRefObject as Project ;
if ( project ! = null )
{
hasChanged = project . mHasChanged ;
if ( project . mLocked )
{
g . Draw ( DarkTheme . sDarkTheme . GetImage ( . LockIcon ) , g . mFont . GetWidth ( mLabel ) + mLabelOffset + LabelX + GS ! ( - 3 ) , 0 ) ;
changeX + = GS ! ( 12 ) ;
}
}
if ( hasChanged )
g . DrawString ( "*" , changeX , 0 ) ;
}
}
public override void DrawAll ( Graphics g )
{
base . DrawAll ( g ) ;
}
}
public class ProjectListView : IDEListView
{
public ProjectPanel mProjectPanel ;
protected override ListViewItem CreateListViewItem ( )
{
ProjectListViewItem anItem = new ProjectListViewItem ( ) ;
return anItem ;
}
}
public class ProjectPanel : Panel
{
public ProjectListView mListView ;
bool mImportFileDeferred ;
bool mImportFolderDeferred ;
bool mImportProjectDeferred ;
bool mImportInstalledDeferred ;
public Dictionary < ListViewItem , ProjectItem > mListViewToProjectMap = new . ( ) ~ delete _ ;
public Dictionary < ProjectItem , ProjectListViewItem > mProjectToListViewMap = new . ( ) ~ delete _ ;
public DarkListViewItem mSelectedParentItem ;
public MenuWidget mMenuWidget ;
public bool mRefreshVisibleViewsDeferred ;
public bool mShowIgnored = true ;
public bool mSortDirty ;
public bool mWantsRehup ;
public this ( )
{
mListView = new ProjectListView ( ) ;
mListView . mProjectPanel = this ;
mListView . mOnEditDone . Add ( new = > HandleEditDone ) ;
mListView . SetShowHeader ( false ) ;
mListView . InitScrollbars ( true , true ) ;
mListView . mHorzScrollbar . mPageSize = GS ! ( 100 ) ;
mListView . mHorzScrollbar . mContentSize = GS ! ( 500 ) ;
mListView . mVertScrollbar . mPageSize = GS ! ( 100 ) ;
mListView . mVertScrollbar . mContentSize = GS ! ( 500 ) ;
mListView . UpdateScrollbars ( ) ;
mListView . mOnFocusChanged . Add ( new = > FocusChangedHandler ) ;
2021-01-03 11:51:53 -08:00
mListView . mOnDragEnd . Add ( new = > HandleDragEnd ) ;
mListView . mOnDragUpdate . Add ( new = > HandleDragUpdate ) ;
2019-08-23 11:56:54 -07:00
AddWidget ( mListView ) ;
mListView . mOnMouseClick . Add ( new = > ListViewClicked ) ;
mListView . mOnMouseDown . Add ( new = > ListViewMouseDown ) ;
mListView . AddColumn ( GS ! ( 100 ) , "Name" ) ;
SetScaleData ( ) ;
RebuildUI ( ) ;
}
void SetScaleData ( )
{
mListView . mColumns [ 0 ] . mMinWidth = GS ! ( 40 ) ;
mListView . mIconX = GS ! ( 20 ) ;
mListView . mOpenButtonX = GS ! ( 4 ) ;
mListView . mLabelX = GS ! ( 44 ) ;
mListView . mChildIndent = GS ! ( 16 ) ;
mListView . mHiliteOffset = GS ! ( - 2 ) ;
}
public override void RehupScale ( float oldScale , float newScale )
{
2020-03-28 14:26:59 -07:00
mListView . mOpenButtonX = GS ! ( 4 ) ;
2019-08-23 11:56:54 -07:00
base . RehupScale ( oldScale , newScale ) ;
SetScaleData ( ) ;
}
public override void FocusForKeyboard ( )
{
base . FocusForKeyboard ( ) ;
SetFocus ( ) ;
if ( mListView . GetRoot ( ) . FindFocusedItem ( ) = = null )
{
mListView . GetRoot ( ) . GetChildAtIndex ( 0 ) . Focused = true ;
}
}
void FocusChangedHandler ( ListViewItem listViewItem )
{
if ( listViewItem . Focused )
{
ProjectItem aProjectItem ;
mListViewToProjectMap . TryGetValue ( listViewItem , out aProjectItem ) ;
if ( aProjectItem ! = null )
{
IDEApp . sApp . ShowProjectItem ( aProjectItem , true , false ) ;
}
}
}
public override void Serialize ( StructuredData data )
{
base . Serialize ( data ) ;
data . Add ( "Type" , "ProjectPanel" ) ;
}
public override bool Deserialize ( StructuredData data )
{
return base . Deserialize ( data ) ;
}
void HandleDragUpdate ( DragEvent theEvent )
{
DarkListViewItem source = ( DarkListViewItem ) theEvent . mSender ;
DarkListViewItem target = ( DarkListViewItem ) theEvent . mDragTarget ;
2021-01-03 11:51:53 -08:00
theEvent . mDragKind = . None ;
int validCount = 0 ;
int invalidCount = 0 ;
2019-08-23 11:56:54 -07:00
if ( source . mListView = = target . mListView )
{
2021-01-03 11:51:53 -08:00
if ( mListViewToProjectMap . GetValue ( target ) case . Ok ( var targetProjectItem ) )
{
mListView . GetRoot ( ) . WithSelectedItems ( scope [ & ] ( selectedItem ) = >
{
if ( mListViewToProjectMap . GetValue ( selectedItem ) case . Ok ( var sourceProjectItem ) )
{
if ( ( sourceProjectItem . mParentFolder ! = null ) & & ( sourceProjectItem . mProject = = targetProjectItem . mProject ) )
validCount + + ;
else
invalidCount + + ;
}
} ) ;
}
}
if ( ( validCount > 0 ) & & ( invalidCount = = 0 ) )
theEvent . mDragKind = . Inside ;
2019-08-23 11:56:54 -07:00
}
void HandleDragEnd ( DragEvent theEvent )
{
2021-01-03 11:51:53 -08:00
if ( theEvent . mDragKind = = . None )
2019-08-23 11:56:54 -07:00
return ;
2021-01-03 11:51:53 -08:00
if ( theEvent . mDragTarget is ProjectListViewItem )
2019-08-23 11:56:54 -07:00
{
2021-01-03 11:51:53 -08:00
ProjectListViewItem source = ( ProjectListViewItem ) theEvent . mSender ;
ProjectListViewItem target = ( ProjectListViewItem ) theEvent . mDragTarget ;
theEvent . mDragKind = . None ;
if ( source . mListView = = target . mListView )
{
if ( mListViewToProjectMap . GetValue ( target ) case . Ok ( var targetProjectItem ) )
{
if ( targetProjectItem = = null )
return ;
if ( source = = target )
return ;
var targetProjectFolder = targetProjectItem as ProjectFolder ;
if ( targetProjectFolder = = null )
targetProjectFolder = targetProjectItem . mParentFolder ;
var targetListItem = mProjectToListViewMap [ targetProjectFolder ] ;
int moveCount = 0 ;
int selectCount = 0 ;
mListView . GetRoot ( ) . WithSelectedItems ( scope [ & ] ( selectedItem ) = >
{
if ( mListViewToProjectMap . GetValue ( selectedItem ) case . Ok ( var sourceProjectItem ) )
{
if ( sourceProjectItem . mParentFolder ! = targetProjectFolder )
moveCount + + ;
}
selectCount + + ;
} ) ;
if ( moveCount = = 0 )
return ;
var targetDisplayName = targetProjectFolder . GetFullDisplayName ( . . scope . ( ) ) ;
if ( targetDisplayName . IsEmpty )
targetDisplayName = "src" ;
Dialog dialog ;
if ( selectCount = = 1 )
{
dialog = ThemeFactory . mDefault . CreateDialog ( "Move file to a new location?" ,
scope $"Are you sure you want to move this file to '{targetDisplayName}'?" ) ;
}
else
{
dialog = ThemeFactory . mDefault . CreateDialog ( "Move files to a new location?" ,
scope $"Are you sure you want to move these files to '{targetDisplayName}'?" ) ;
}
dialog . AddButton ( "Yes" , new ( evt ) = >
{
List < String > fileErrors = scope . ( ) ;
List < ListViewItem > selectedItems = scope . ( ) ;
mListView . GetRoot ( ) . WithSelectedItems ( scope [ & ] ( selectedItem ) = >
{
selectedItems . Add ( selectedItem ) ;
} ) ;
for ( var selectedItem in selectedItems )
{
if ( mListViewToProjectMap . GetValue ( selectedItem ) case . Ok ( var sourceProjectItem ) )
{
var sourceProjectFileItem = sourceProjectItem as ProjectFileItem ;
if ( sourceProjectFileItem = = null )
return ;
var sourcePath = sourceProjectFileItem . GetFullImportPath ( . . scope . ( ) ) ;
var destPath = targetProjectFolder . GetFullImportPath ( . . scope . ( ) ) ;
destPath . AppendF ( $"{Path.DirectorySeparatorChar}{sourceProjectFileItem.mName}" ) ;
if ( File . Move ( sourcePath , destPath ) case . Ok )
{
gApp . FileRenamed ( sourceProjectFileItem , sourcePath , destPath ) ;
}
else
fileErrors . Add ( scope : : . ( destPath ) ) ;
if ( targetProjectFolder ! = sourceProjectItem . mParentFolder )
{
source . mParentItem . RemoveChildItem ( source , false ) ;
sourceProjectItem . mParentFolder . RemoveChild ( sourceProjectItem ) ;
targetListItem . AddChildAtIndex ( 0 , source ) ;
targetListItem . mOpenButton . Open ( true , false ) ;
targetProjectFolder . AddChildAtIndex ( 0 , sourceProjectItem ) ;
}
}
}
QueueSortItem ( targetListItem ) ;
DoSortItem ( targetListItem ) ;
if ( ! fileErrors . IsEmpty )
{
var errorStr = scope String ( ) ;
if ( fileErrors . Count = = 1 )
errorStr . AppendF ( "Failed to move file to: {0}" , fileErrors [ 0 ] ) ;
else
{
errorStr . AppendF ( "Failed to move {0} files:" , fileErrors . Count ) ;
for ( var file in fileErrors )
errorStr . Append ( "\n {}" , file ) ;
}
gApp . Fail ( errorStr ) ;
}
} ) ;
dialog . AddButton ( "No" , new ( evt ) = >
{
} ) ;
dialog . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
//RehupFolder(targetProjectFolder.mProject.mRootFolder, .FullTraversal);
/ * if ( theEvent . mDragTargetDir = = - 1 ) // Before
{
target . mParentItem . InsertChild ( source , target ) ;
targetProjectItem . mParentFolder . InsertChild ( sourceProjectItem , targetProjectItem ) ;
}
else if ( theEvent . mDragTargetDir = = 0 ) // Inside
{
target . AddChildAtIndex ( 0 , source ) ;
target . mOpenButton . Open ( true , false ) ;
( ( ProjectFolder ) targetProjectItem ) . AddChildAtIndex ( 0 , sourceProjectItem ) ;
}
else if ( theEvent . mDragTargetDir = = 1 ) // After
{
target . mParentItem . AddChild ( source , target ) ;
targetProjectItem . mParentFolder . AddChild ( sourceProjectItem , targetProjectItem ) ;
} * /
}
}
/ * DarkListViewItem source = ( DarkListViewItem ) theEvent . mSender ;
2019-08-23 11:56:54 -07:00
DarkListViewItem target = ( DarkListViewItem ) theEvent . mDragTarget ;
if ( source . mListView = = target . mListView )
{
ProjectItem targetProjectItem = mListViewToProjectMap [ target ] ;
ProjectItem sourceProjectItem = mListViewToProjectMap [ source ] ;
2021-01-03 11:51:53 -08:00
} * /
2019-08-23 11:56:54 -07:00
}
}
public void InitProject ( Project project )
{
var projectListViewItem = InitProjectItem ( project . mRootFolder ) ;
projectListViewItem . mRefObject = project ;
}
public void RebuildUI ( )
{
mListView . GetRoot ( ) . Clear ( ) ;
/ * if ( gApp . mWorkspace . mDebugSession ! = null )
{
var debugSessionItem = ( ProjectListViewItem ) mListView . GetRoot ( ) . CreateChildItem ( ) ;
debugSessionItem . Label = "Debug Session" ;
debugSessionItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . Workspace ) ;
debugSessionItem . mLabelOffset = GS ! ( - 16 ) ;
debugSessionItem . mRefObject = IDEApp . sApp . mWorkspace ;
SetupItem ( debugSessionItem , true ) ;
} * /
if ( ! gApp . mWorkspace . IsInitialized )
{
mListViewToProjectMap . Clear ( ) ;
mProjectToListViewMap . Clear ( ) ;
return ;
}
if ( ! gApp . mWorkspace . IsDebugSession )
{
var workspaceItem = ( ProjectListViewItem ) mListView . GetRoot ( ) . CreateChildItem ( ) ;
workspaceItem . Label = "Workspace" ;
workspaceItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . Workspace ) ;
workspaceItem . mLabelOffset = GS ! ( - 16 ) ;
workspaceItem . mRefObject = IDEApp . sApp . mWorkspace ;
SetupItem ( workspaceItem , true ) ;
}
mListViewToProjectMap . Clear ( ) ;
mProjectToListViewMap . Clear ( ) ;
for ( var project in IDEApp . sApp . mWorkspace . mProjects )
InitProject ( project ) ;
RehupProjects ( ) ;
}
ProjectListViewItem InitProjectItem ( ProjectItem item )
{
var listViewItem = AddProjectItem ( item ) ;
if ( item is ProjectFolder )
{
ProjectFolder aFolder = ( ProjectFolder ) item ;
for ( ProjectItem anItem in aFolder . mChildItems )
InitProjectItem ( anItem ) ;
}
return listViewItem ;
}
void AssociateViews ( ProjectListViewItem listViewItem , ProjectItem projectItem )
{
mListViewToProjectMap [ listViewItem ] = projectItem ;
mProjectToListViewMap [ projectItem ] = listViewItem ;
}
void SetupItem ( ListViewItem item , bool selectable )
{
if ( selectable )
item . mOnMouseDown . Add ( new = > ItemClicked ) ;
item . mOnMouseClick . Add ( new = > ListViewItemClicked ) ;
UpdateColors ( ) ;
DarkListViewItem listViewItem = ( DarkListViewItem ) item ;
2021-01-03 11:51:53 -08:00
listViewItem . AllowDragging = true ;
2020-10-05 14:25:55 -07:00
listViewItem . mFocusColor = gApp . mSettings . mUISettings . mColors . mWorkspaceDisabledText ;
listViewItem . mSelectColor = gApp . mSettings . mUISettings . mColors . mWorkspaceDisabledText ;
2019-08-23 11:56:54 -07:00
}
void UpdateColors ( )
{
}
public ProjectListViewItem AddProjectItem ( ProjectItem projectItem , ProjectListViewItem existingListViewItem = null )
{
var projectSource = projectItem as ProjectSource ;
2020-06-04 17:19:57 -07:00
2019-08-23 11:56:54 -07:00
ProjectListViewItem listViewItem = null ;
if ( ( projectSource ! = null ) & & ( gApp . IsProjectSourceEnabled ( projectSource ) ) )
{
var resolveCompiler = gApp . GetProjectCompilerForFile ( projectSource . mName ) ;
if ( resolveCompiler ! = null )
{
2020-04-14 11:37:27 -07:00
resolveCompiler . QueueProjectSource ( projectSource , . None , false ) ;
2019-08-23 11:56:54 -07:00
resolveCompiler . QueueDeferredResolveAll ( ) ;
}
projectSource . mHasChangedSinceLastCompile = true ;
mRefreshVisibleViewsDeferred = true ;
CheckProjectSource ( projectSource ) ;
}
if ( existingListViewItem ! = null )
return existingListViewItem ;
if ( projectItem . mParentFolder ! = null )
{
let listViewParent = mProjectToListViewMap [ projectItem . mParentFolder ] ;
listViewItem = ( ProjectListViewItem ) listViewParent . CreateChildItem ( ) ;
if ( projectItem is ProjectFolder )
listViewItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . ProjectFolder ) ;
else
listViewItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . Document ) ;
listViewItem . Label = projectItem . mName ;
if ( projectItem is ProjectFolder )
listViewItem . MakeParent ( ) ;
SetupItem ( listViewItem , true ) ;
AssociateViews ( listViewItem , projectItem ) ;
QueueSortItem ( listViewParent ) ;
}
else
{
var project = projectItem . mProject ;
let listViewParent = ( ProjectListViewItem ) mListView . GetRoot ( ) ;
listViewItem = ( ProjectListViewItem ) listViewParent . CreateChildItem ( ) ;
listViewItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . Project ) ;
listViewItem . Label = project . mProjectName ;
listViewItem . MakeParent ( ) ;
listViewItem . mIsBold = project = = IDEApp . sApp . mWorkspace . mStartupProject ;
// It's the root
SetupItem ( listViewItem , true ) ;
AssociateViews ( listViewItem , projectItem ) ;
QueueSortItem ( listViewParent ) ;
}
return listViewItem ;
}
bool HasNonAutoItems ( ProjectFolder projectFolder )
{
for ( let child in projectFolder . mChildItems )
{
if ( var childFolder = child as ProjectFolder )
{
if ( HasNonAutoItems ( childFolder ) )
return true ;
}
if ( child . mIncludeKind ! = . Auto )
{
return true ;
}
}
return false ;
}
public enum RehupFlags
{
None = 0 ,
ApplyAutoToChildren = 1 ,
2019-09-05 08:18:24 -07:00
ClearAutoItems = 2 ,
FullTraversal = 4 ,
2019-08-23 11:56:54 -07:00
}
public void RehupFolder ( ProjectFolder projectFolder , RehupFlags rehupFlags = . None )
{
scope AutoBeefPerf ( "ProjectPanel.RehupFolder" ) ;
if ( mProjectToListViewMap . TryGetValue ( projectFolder , var lvItem ) )
{
lvItem . mWantsRehup = false ;
}
var dirPath = scope String ( ) ;
projectFolder . GetFullImportPath ( dirPath ) ;
2019-09-05 08:18:24 -07:00
bool clearAutoItems = ( ! rehupFlags . HasFlag ( . ApplyAutoToChildren ) ) & & ( projectFolder . mAutoInclude ) ; // && (rehupFlags.HasFlag(.ClearAutoItems));
2019-08-23 11:56:54 -07:00
HashSet < ProjectItem > foundAutoItems = scope . ( ) ;
for ( let fileEntry in Directory . EnumerateFiles ( dirPath ) )
{
String fileName = scope String ( ) ;
fileEntry . GetFileName ( fileName ) ;
ProjectItem projectItem ;
if ( projectFolder . mChildMap . TryGetValue ( fileName , out projectItem ) )
{
if ( ( rehupFlags . HasFlag ( . ApplyAutoToChildren ) ) & & ( projectItem . mIncludeKind = = . Manual ) )
projectItem . mIncludeKind = . Auto ;
if ( ( clearAutoItems ) & & ( projectItem . mIncludeKind = = . Auto ) )
foundAutoItems . Add ( projectItem ) ;
continue ;
}
2019-09-30 12:23:27 -07:00
if ( ! projectFolder . mAutoInclude )
continue ;
2019-08-23 11:56:54 -07:00
let ext = scope String ( ) ;
Path . GetExtension ( fileName , ext ) ;
let projectSource = new ProjectSource ( ) ;
projectSource . mProject = projectFolder . mProject ;
projectSource . mName . Set ( fileName ) ;
2020-06-04 17:19:57 -07:00
//if (projectFolder.mPath != null)
{
projectSource . mPath = new String ( ) ;
projectSource . mPath . Append ( projectFolder . mPath ) ;
projectSource . mPath . Append ( "/" ) ;
projectSource . mPath . Append ( fileName ) ;
}
projectSource . mIncludeKind = . Auto ;
2019-08-23 11:56:54 -07:00
projectFolder . AddChild ( projectSource ) ;
AddProjectItem ( projectSource ) ;
if ( ( clearAutoItems ) & & ( projectSource . mIncludeKind = = . Auto ) )
foundAutoItems . Add ( projectSource ) ;
if ( projectSource . mIncludeKind ! = . Auto )
projectSource . mProject . SetChanged ( ) ;
}
for ( let fileEntry in Directory . EnumerateDirectories ( dirPath ) )
{
String dirName = scope String ( ) ;
fileEntry . GetFileName ( dirName ) ;
ProjectItem projectItem ;
if ( projectFolder . mChildMap . TryGetValue ( dirName , out projectItem ) )
{
if ( var childProjectFolder = projectItem as ProjectFolder )
{
if ( ( rehupFlags . HasFlag ( . ApplyAutoToChildren ) ) & & ( projectItem . mIncludeKind = = . Manual ) )
projectItem . mIncludeKind = . Auto ;
if ( projectItem . mIncludeKind = = . Auto )
RehupFolder ( childProjectFolder , rehupFlags ) ;
2019-09-05 08:18:24 -07:00
if ( ( clearAutoItems ) & & ( projectItem . mIncludeKind = = . Auto ) )
foundAutoItems . Add ( projectItem ) ;
2019-08-23 11:56:54 -07:00
}
continue ;
}
let newRelDir = scope String ( projectFolder . mPath ) ;
if ( ! newRelDir . IsEmpty )
newRelDir . Append ( "/" ) ;
newRelDir . Append ( dirName ) ;
let childProjectFolder = new ProjectFolder ( ) ;
childProjectFolder . mProject = projectFolder . mProject ;
childProjectFolder . mName . Set ( dirName ) ;
childProjectFolder . mPath = new String ( projectFolder . mPath ) ;
childProjectFolder . mPath . Append ( "/" ) ;
childProjectFolder . mPath . Append ( dirName ) ;
childProjectFolder . mAutoInclude = true ;
2020-06-04 17:19:57 -07:00
childProjectFolder . mIncludeKind = . Auto ;
2019-08-23 11:56:54 -07:00
projectFolder . AddChild ( childProjectFolder ) ;
2019-09-05 08:18:24 -07:00
if ( clearAutoItems )
{
foundAutoItems . Add ( childProjectFolder ) ;
}
2019-08-23 11:56:54 -07:00
AddProjectItem ( childProjectFolder ) ;
RehupFolder ( childProjectFolder , rehupFlags ) ;
}
if ( ( rehupFlags . HasFlag ( . ApplyAutoToChildren ) ) | | ( clearAutoItems ) )
{
// Any items that were specified as 'manual' but don't actually exist in the file system, remove those now
//List<ProjectItem> removeList = scope List<ProjectItem>();
//for (var child in projectFolder.mChildItems)
for ( int childIdx = projectFolder . mChildItems . Count - 1 ; childIdx > = 0 ; childIdx - - )
{
var child = projectFolder . mChildItems [ childIdx ] ;
2019-09-05 08:18:24 -07:00
2019-08-23 11:56:54 -07:00
if ( ( ( rehupFlags . HasFlag ( . ApplyAutoToChildren ) ) & & ( child . mIncludeKind = = . Manual ) ) | |
( ( clearAutoItems ) & & ( child . mIncludeKind = = . Auto ) & & ( ! foundAutoItems . Contains ( child ) ) ) )
{
var listItem = mProjectToListViewMap [ child ] ;
2020-06-04 17:19:57 -07:00
DoDeleteItem ( listItem , null , . ForceRemove ) ;
2019-09-05 08:18:24 -07:00
continue ;
}
if ( ( rehupFlags . HasFlag ( . FullTraversal ) ) & & ( child . mIncludeKind = = . Manual ) & & ( var childProjectFolder = child as ProjectFolder ) )
{
RehupFolder ( childProjectFolder , rehupFlags ) ;
2019-08-23 11:56:54 -07:00
}
}
}
}
public void QueueRehupFolder ( ProjectFolder projectFolder )
{
bool hadValue = mProjectToListViewMap . TryGetValue ( projectFolder , var lvItem ) ;
if ( ! hadValue )
{
RehupFolder ( projectFolder ) ;
return ;
}
mWantsRehup = true ;
lvItem . mWantsRehup = true ;
}
void Unignore ( ProjectItem projectItem )
{
var listViewItem = ( ProjectListViewItem ) mProjectToListViewMap [ projectItem ] ;
if ( projectItem . mIncludeKind = = . Ignore )
projectItem . mIncludeKind = . Auto ;
if ( let projectFolder = projectItem as ProjectFolder )
{
for ( let childItem in projectFolder . mChildItems )
{
if ( childItem . mIncludeKind ! = . Ignore )
Unignore ( childItem ) ;
}
}
AddProjectItem ( projectItem , listViewItem ) ;
projectItem . mProject . SetChanged ( ) ;
}
public void NewFolder ( ProjectFolder folder )
{
ProjectFolder projectFolder = new ProjectFolder ( ) ;
2020-05-07 05:39:53 -07:00
int checkIdx = 0 ;
while ( true )
{
projectFolder . mName . Set ( "New folder" ) ;
if ( checkIdx > 0 )
projectFolder . mName . AppendF ( "{}" , checkIdx + 1 ) ;
if ( ! folder . mChildMap . ContainsKey ( projectFolder . mName ) )
break ;
checkIdx + + ;
}
2019-08-23 11:56:54 -07:00
projectFolder . mProject = folder . mProject ;
projectFolder . mPath = new String ( ) ;
2020-08-09 07:19:26 -07:00
String dirSepStr = scope String ( ) . . Append ( Path . DirectorySeparatorChar ) ;
2019-08-23 11:56:54 -07:00
if ( folder . mParentFolder = = null )
2020-08-09 07:19:26 -07:00
projectFolder . mPath . Append ( "src" , dirSepStr , projectFolder . mName ) ;
2019-08-23 11:56:54 -07:00
else
2020-08-09 07:19:26 -07:00
projectFolder . mPath . Append ( folder . mPath , dirSepStr , projectFolder . mName ) ;
2019-08-23 11:56:54 -07:00
projectFolder . mIncludeKind = folder . mIncludeKind ;
projectFolder . mAutoInclude = folder . IsAutoInclude ( ) ;
folder . AddChild ( projectFolder ) ;
2020-01-25 06:22:26 -08:00
let projectItem = AddProjectItem ( projectFolder ) ;
if ( projectItem ! = null )
{
2020-09-19 05:15:30 -07:00
projectItem . Open ( true ) ;
Sort ( ) ;
mListView . UpdateAll ( ) ;
2020-01-25 06:22:26 -08:00
mListView . GetRoot ( ) . SelectItemExclusively ( projectItem ) ;
mListView . EnsureItemVisible ( projectItem , false ) ;
2020-09-19 05:15:30 -07:00
RenameItem ( projectFolder ) ;
2020-01-25 06:22:26 -08:00
}
2019-08-23 11:56:54 -07:00
if ( projectFolder . mIncludeKind ! = . Auto )
projectFolder . mProject . SetChanged ( ) ;
2020-05-07 05:39:53 -07:00
String fullPath = scope String ( ) ;
projectFolder . GetFullImportPath ( fullPath ) ;
if ( Directory . CreateDirectory ( fullPath ) case . Err ( let err ) )
{
if ( err ! = . AlreadyExists )
gApp . Fail ( scope String ( ) . . AppendF ( "Failed to create directory '{]'" , fullPath ) ) ;
}
2019-08-23 11:56:54 -07:00
}
public void NewClass ( ProjectFolder folder )
{
DarkDialog dialog = ( DarkDialog ) ThemeFactory . mDefault . CreateDialog ( "New Class" , "Class Name" ) ;
dialog . mMinWidth = GS ! ( 300 ) ;
dialog . mDefaultButton = dialog . AddButton ( "OK" , new ( evt ) = > DoNewClass ( folder , evt ) ) ;
dialog . mEscButton = dialog . AddButton ( "Cancel" ) ;
dialog . AddEdit ( "Unnamed" ) ;
2019-09-05 08:18:24 -07:00
dialog . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
}
void DoNewClass ( ProjectFolder folder , DialogEvent evt )
{
Dialog dlg = ( Dialog ) evt . mSender ;
var className = scope String ( ) ;
dlg . mDialogEditWidget . GetText ( className ) ;
className . Trim ( ) ;
if ( className . Length = = 0 )
return ;
let project = folder . mProject ;
2019-09-05 08:18:24 -07:00
if ( project . mNeedsCreate )
project . FinishCreate ( ) ;
2019-08-23 11:56:54 -07:00
String relFileName = scope String ( className , ".bf" ) ;
String fullFilePath = scope String ( ) ;
String relPath = scope String ( ) ;
folder . GetRelDir ( relPath ) ;
if ( relPath . Length > 0 )
relPath . Append ( "/" ) ;
relPath . Append ( relFileName ) ;
folder . mProject . GetProjectFullPath ( relPath , fullFilePath ) ;
String dirName = scope String ( ) ;
Path . GetDirectoryPath ( fullFilePath , dirName ) ;
Directory . CreateDirectory ( dirName ) . IgnoreError ( ) ;
String fileText = scope String ( ) ;
fileText . Append ( "namespace " ) ;
String namespaceName = scope String ( ) ;
2020-08-09 07:19:26 -07:00
folder . GetRelDir ( namespaceName ) ; namespaceName . Replace ( '/' , '.' ) ; namespaceName . Replace ( '\\' , '.' ) ; namespaceName . Replace ( " " , "" ) ;
2019-08-23 11:56:54 -07:00
if ( namespaceName . StartsWith ( "src." ) )
{
namespaceName . Remove ( 0 , 4 ) ;
if ( ! project . mBeefGlobalOptions . mDefaultNamespace . IsWhiteSpace )
{
namespaceName . Insert ( 0 , "." ) ;
namespaceName . Insert ( 0 , project . mBeefGlobalOptions . mDefaultNamespace ) ;
}
}
else if ( folder . mParentFolder = = null )
{
namespaceName . Clear ( ) ;
namespaceName . Append ( project . mBeefGlobalOptions . mDefaultNamespace ) ;
}
else
namespaceName . Clear ( ) ;
fileText . Append ( namespaceName , Environment . NewLine ) ;
fileText . Append ( "{" , Environment . NewLine ) ;
fileText . Append ( "\tclass " , className , Environment . NewLine ) ;
fileText . Append ( "\t{" , Environment . NewLine ) ;
fileText . Append ( "\t}" , Environment . NewLine ) ;
fileText . Append ( "}" , Environment . NewLine ) ;
if ( File . Exists ( fullFilePath ) )
{
var error = scope String ( ) ;
error . AppendF ( "File '{0}' already exists" , fullFilePath ) ;
IDEApp . sApp . Fail ( error ) ;
return ;
}
if ( File . WriteAllText ( fullFilePath , fileText ) case . Err )
{
var error = scope String ( ) ;
error . AppendF ( "Failed to create file '{0}'" , fullFilePath ) ;
gApp . Fail ( error ) ;
return ;
}
ProjectSource projectSource = new ProjectSource ( ) ;
projectSource . mIncludeKind = ( folder . mIncludeKind = = . Auto ) ? . Auto : . Manual ;
projectSource . mName . Set ( relFileName ) ;
projectSource . mPath = new String ( ) ;
folder . mProject . GetProjectRelPath ( fullFilePath , projectSource . mPath ) ;
projectSource . mProject = folder . mProject ;
projectSource . mParentFolder = folder ;
folder . AddChild ( projectSource ) ;
2020-01-25 06:22:26 -08:00
let projectItem = AddProjectItem ( projectSource ) ;
if ( projectItem ! = null )
{
mListView . GetRoot ( ) . SelectItemExclusively ( projectItem ) ;
mListView . EnsureItemVisible ( projectItem , false ) ;
}
2019-08-23 11:56:54 -07:00
Sort ( ) ;
if ( folder . mIncludeKind ! = . Auto )
folder . mProject . SetChanged ( ) ;
2019-12-25 12:43:45 -08:00
gApp . RecordHistoryLocation ( true ) ;
2019-08-23 11:56:54 -07:00
gApp . ShowProjectItem ( projectSource ) ;
2019-12-25 12:43:45 -08:00
gApp . RecordHistoryLocation ( true ) ;
2019-08-23 11:56:54 -07:00
}
int CompareListViewItem ( ListViewItem left , ListViewItem right )
{
ProjectItem leftProjectItem ;
mListViewToProjectMap . TryGetValue ( left , out leftProjectItem ) ;
ProjectItem rightProjectItem ;
mListViewToProjectMap . TryGetValue ( right , out rightProjectItem ) ;
if ( leftProjectItem = = null )
return - 1 ;
if ( rightProjectItem = = null )
return 1 ;
2019-09-05 08:18:24 -07:00
if ( ( leftProjectItem . mParentFolder = = null ) & & ( rightProjectItem . mParentFolder = = null ) )
{
return String . Compare ( leftProjectItem . mProject . mProjectName , rightProjectItem . mProject . mProjectName , true ) ;
}
2019-08-23 11:56:54 -07:00
return ProjectItem . Compare ( leftProjectItem , rightProjectItem ) ;
}
void DoSortItem ( ProjectListViewItem listViewItem )
{
if ( listViewItem . mChildItems = = null )
return ;
if ( listViewItem . mSortDirty )
{
if ( listViewItem . mChildItems . Count > 1 )
listViewItem . mChildItems . Sort ( scope = > CompareListViewItem ) ;
listViewItem . mSortDirty = false ;
}
for ( var child in listViewItem . mChildItems )
{
var childItem = ( ProjectListViewItem ) child ;
DoSortItem ( childItem ) ;
}
mListView . mListSizeDirty = true ;
}
public void SortItem ( ProjectListViewItem listViewItem )
{
listViewItem . mSortDirty = true ;
DoSortItem ( listViewItem ) ;
}
public void QueueSortItem ( ProjectListViewItem listViewItem )
{
mSortDirty = true ;
listViewItem . mSortDirty = true ;
}
public void Sort ( )
{
/ * for ( var project in IDEApp . sApp . mWorkspace . mProjects )
project . mRootFolder . SortItems ( ) ; * /
DoSortItem ( ( ProjectListViewItem ) mListView . GetRoot ( ) ) ;
mListView . Resized ( ) ;
}
public bool AlreadyHasPath ( ProjectFolder folder , String relPath )
{
for ( var childItem in folder . mChildItems )
{
ProjectSource projectSource = childItem as ProjectSource ;
if ( projectSource ! = null )
{
if ( projectSource . mPath = = relPath )
return true ;
}
ProjectFolder childFolder = childItem as ProjectFolder ;
if ( childFolder ! = null )
if ( AlreadyHasPath ( childFolder , relPath ) )
return true ;
}
return false ;
}
public bool AlreadyHasPath ( Project project , String relPath )
{
if ( AlreadyHasPath ( project . mRootFolder , relPath ) )
return true ;
return false ;
}
void ShowAlreadyHadFileError ( List < String > alreadyHadFileList , int totalFileCount )
{
if ( alreadyHadFileList . Count > 0 )
{
String errorStr ;
if ( alreadyHadFileList . Count = = 1 )
errorStr = StackStringFormat ! ( "Project already contained file: {0}" , alreadyHadFileList [ 0 ] ) ;
else
errorStr = StackStringFormat ! ( "Project already contained {0} of the {1} files specified" , alreadyHadFileList . Count , totalFileCount ) ;
IDEApp . sApp . Fail ( errorStr ) ;
}
}
void CheckProjectSource ( ProjectSource projectSource )
{
var fullPath = scope String ( ) ;
projectSource . GetFullImportPath ( fullPath ) ;
IDEApp . sApp . WithTabs ( scope ( tab ) = >
{
var sourceViewPanel = tab . mContent as SourceViewPanel ;
if ( ( sourceViewPanel ! = null ) & &
( sourceViewPanel . mProjectSource = = null ) & &
( sourceViewPanel . mFilePath ! = null ) & &
( Path . Equals ( sourceViewPanel . mFilePath , fullPath ) ) )
{
sourceViewPanel . AttachToProjectSource ( projectSource ) ;
}
} ) ;
}
2019-11-28 09:12:49 -08:00
bool CheckProjectModify ( Project project )
{
if ( ! project . mLocked )
return true ;
let dialog = gApp . Fail (
"" "
This project is locked because it may be a shared library , and editing shared libraries may have unwanted effects on other programs that use it .
If you are sure you want to edit this project then you can unlock it by right clicking on the project and deselecting ' Lock Project '
"" ",
null , mWidgetWindow ) ;
dialog . mWindowFlags | = . Modal ;
return false ;
}
2020-07-19 05:50:08 -07:00
public void ImportFiles ( ProjectFolder folder , String [ ] fileList )
{
String fullDir = scope String ( ) ;
folder . GetFullImportPath ( fullDir ) ;
if ( mProjectToListViewMap . TryGetValue ( folder , var value ) )
value . mOpenButton . Open ( true , false ) ;
/ * if ( mSelectedParentItem . mOpenButton ! = null )
mSelectedParentItem . mOpenButton . Open ( true , false ) ; * /
String dir = scope String ( fullDir ) ;
List < String > alreadyHadFileList = scope List < String > ( ) ;
defer ClearAndDeleteItems ( alreadyHadFileList ) ;
for ( String fileNameIn in fileList )
{
String fileName = scope String ( fileNameIn ) ;
String relFilePath = scope String ( ) ;
folder . mProject . GetProjectRelPath ( fileName , relFilePath ) ;
if ( AlreadyHasPath ( folder . mProject , relFilePath ) )
{
alreadyHadFileList . Add ( new String ( fileName ) ) ;
continue ;
}
ProjectSource projectSource = new ProjectSource ( ) ;
int32 lastSlashIdx = ( int32 ) fileName . LastIndexOf ( IDEUtils . cNativeSlash ) ;
if ( lastSlashIdx ! = - 1 )
{
projectSource . mName . Clear ( ) ;
projectSource . mName . Append ( fileName , lastSlashIdx + 1 ) ;
dir . Clear ( ) ;
dir . Append ( fileName , 0 , lastSlashIdx ) ;
}
else
projectSource . mName . Set ( fileName ) ;
projectSource . mIncludeKind = . Manual ;
projectSource . mProject = folder . mProject ;
projectSource . mPath = new String ( relFilePath ) ;
folder . AddChild ( projectSource ) ;
AddProjectItem ( projectSource ) ;
if ( projectSource . mIncludeKind ! = . Auto )
folder . mProject . SetChanged ( ) ;
}
ShowAlreadyHadFileError ( alreadyHadFileList , fileList . Count ) ;
folder . mProject . GetProjectRelPath ( scope String ( dir ) , dir ) ;
//folder.mLastImportDir.Set(dir);
//folder.mProject.mLastImportDir.Set(dir);
Sort ( ) ;
}
2019-08-23 11:56:54 -07:00
public void ImportFile ( ProjectFolder folder )
{
#if ! CLI
/ * String fullDir = scope String ( ) ;
var checkFolder = folder ;
while ( checkFolder ! = null )
{
if ( fullDir . Length > 0 )
fullDir . Append ( Path . DirectorySeparatorChar ) ;
fullDir . Append ( checkFolder . mName ) ;
checkFolder = checkFolder . mParentFolder ;
}
fullDir = scope String ( folder . mProject . mProjectDir ) ;
fullDir . Append ( Path . DirectorySeparatorChar ) ;
fullDir . Append ( fullDir ) ;
String oldStr = fullDir ;
fullDir = scope String ( ) ;
folder . mProject . GetProjectFullPath ( oldStr , fullDir ) ; * /
2019-11-28 09:12:49 -08:00
if ( ! CheckProjectModify ( folder . mProject ) )
return ;
2019-08-23 11:56:54 -07:00
String fullDir = scope String ( ) ;
folder . GetFullImportPath ( fullDir ) ;
//fullDir.Replace('/', '\\');
//TODO:
var fileDialog = scope OpenFileDialog ( ) ;
fileDialog . ShowReadOnly = false ;
fileDialog . Title = "Import File" ;
fileDialog . Multiselect = true ;
fileDialog . InitialDirectory = fullDir ;
fileDialog . ValidateNames = true ;
2019-09-05 08:18:24 -07:00
gApp . GetActiveWindow ( ) . PreModalChild ( ) ;
2019-08-23 11:56:54 -07:00
if ( fileDialog . ShowDialog ( gApp . GetActiveWindow ( ) ) . GetValueOrDefault ( ) = = . OK )
{
2020-07-19 05:50:08 -07:00
ImportFiles ( folder , fileDialog . FileNames ) ;
2019-08-23 11:56:54 -07:00
}
#endif
}
public int32 AddFolder ( ProjectFolder folder , String folderFileName , List < String > alreadyHadFileList , bool autoInclude )
{
int32 totalFileCount = 0 ;
#if ! CLI
folder . mProject . SetChanged ( ) ;
String folderName = scope String ( ) ;
Path . GetFileName ( folderFileName , folderName ) ;
ProjectFolder newFolder = new ProjectFolder ( ) ;
newFolder . mIncludeKind = . Manual ;
newFolder . mName . Set ( folderName ) ;
newFolder . mProject = folder . mProject ;
newFolder . mPath = new String ( ) ;
folder . mProject . GetProjectRelPath ( folderFileName , newFolder . mPath ) ;
folder . AddChild ( newFolder ) ;
AddProjectItem ( newFolder ) ;
if ( autoInclude )
{
newFolder . mAutoInclude = true ;
RehupFolder ( newFolder ) ;
}
else
{
for ( var fileEntry in Directory . EnumerateFiles ( folderFileName ) )
{
var fileName = scope String ( ) ;
fileEntry . GetFileName ( fileName ) ;
totalFileCount + + ;
//String fileName = fileNameIn.Replace('\\', '/');
IDEUtils . FixFilePath ( fileName ) ;
String relFilePath = scope String ( ) ;
folder . mProject . GetProjectRelPath ( fileName , relFilePath ) ;
if ( AlreadyHasPath ( folder . mProject , relFilePath ) )
{
alreadyHadFileList . Add ( relFilePath ) ;
continue ;
}
ProjectSource projectSource = new ProjectSource ( ) ;
projectSource . mProject = folder . mProject ;
projectSource . mIncludeKind = . Manual ;
int32 lastSlashIdx = ( int32 ) fileName . LastIndexOf ( IDEUtils . cNativeSlash ) ;
if ( lastSlashIdx ! = - 1 )
fileName . Remove ( 0 , lastSlashIdx + 1 ) ;
projectSource . mName . Set ( fileName ) ;
projectSource . mPath = new String ( relFilePath ) ;
newFolder . AddChild ( projectSource ) ;
AddProjectItem ( projectSource ) ;
}
for ( var fileEntry in Directory . EnumerateDirectories ( folderFileName ) )
{
var dirName = scope String ( ) ;
fileEntry . GetFileName ( dirName ) ;
totalFileCount + = AddFolder ( newFolder , dirName , alreadyHadFileList , autoInclude ) ;
}
}
#endif
return totalFileCount ;
}
public void ImportFolder ( ProjectFolder folder )
{
#if ! CLI
2019-11-28 09:12:49 -08:00
if ( ! CheckProjectModify ( folder . mProject ) )
return ;
2019-08-23 11:56:54 -07:00
//ThrowUnimplemented();
String relDir = scope String ( "" ) ;
var checkFolder = folder ;
while ( checkFolder ! = null )
{
if ( relDir ! = "" )
relDir . Insert ( 0 , "/" ) ;
relDir . Insert ( 0 , checkFolder . mName ) ;
checkFolder = checkFolder . mParentFolder ;
}
relDir . Insert ( 0 , "/" ) ;
relDir . Insert ( 0 , folder . mProject . mProjectDir ) ;
String fullDir = scope String ( ) ;
folder . mProject . GetProjectFullPath ( relDir , fullDir ) ;
//fullDir.Replace('/', '\\');
var folderDialog = scope FolderBrowserDialog ( ) ;
folderDialog . SelectedPath = fullDir ;
mWidgetWindow . PreModalChild ( ) ;
if ( folderDialog . ShowDialog ( gApp . GetActiveWindow ( ) ) . GetValueOrDefault ( ) = = . OK )
{
List < String > alreadyHadFileList = scope List < String > ( ) ;
if ( mSelectedParentItem . mOpenButton ! = null )
mSelectedParentItem . mOpenButton . Open ( true , false ) ;
String dir = scope String ( folderDialog . SelectedPath ) ;
int32 totalFileCount = AddFolder ( folder , dir , alreadyHadFileList , true ) ;
/ * int32 totalFileCount = 1 ;
if ( AlreadyHasPath ( folder , dir ) )
{
alreadyHadFileList . Add ( dir ) ;
} * /
ShowAlreadyHadFileError ( alreadyHadFileList , totalFileCount ) ;
relDir . Clear ( ) ;
folder . mProject . GetProjectRelPath ( dir , relDir ) ;
//folder.mLastImportDir.Set(relDir);
//folder.mProject.mLastImportDir.Set(relDir);
if ( folder . mIncludeKind ! = . Auto )
folder . mProject . SetChanged ( ) ;
Sort ( ) ;
}
#endif
}
ListViewItem GetSelectedParentItem ( )
{
ListViewItem selectedItem = mListView . GetRoot ( ) . FindFirstSelectedItem ( ) ;
if ( selectedItem ! = null )
{
if ( selectedItem . IsParent )
return selectedItem ;
return selectedItem . mParentItem ;
}
return mListView . GetRoot ( ) ;
}
ListViewItem GetSelectedItem ( )
{
return mListView . GetRoot ( ) . FindFirstSelectedItem ( ) ;
}
ProjectItem GetSelectedProjectItem ( )
{
let listViewItem = GetSelectedItem ( ) ;
if ( listViewItem = = null )
return null ;
ProjectItem projectItem ;
mListViewToProjectMap . TryGetValue ( listViewItem , out projectItem ) ;
return projectItem ;
}
2020-01-19 07:35:17 -08:00
ProjectFolder GetSelectedProjectFolder ( )
{
let projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem = = null )
return null ;
if ( let projectFolder = projectItem as ProjectFolder )
return projectFolder ;
return projectItem . mParentFolder ;
}
2019-08-23 11:56:54 -07:00
public void SelectItem ( ListViewItem item , bool checkKeyStates = false )
{
if ( item . Focused )
{
2021-01-03 11:51:53 -08:00
if ( mListView . GetRoot ( ) . GetSelectedItemCount ( ) < = 1 )
{
// Just rehup focus handler - handles case of closing file then clicking on it again
// even though it's already selected. We want that to re-open it.
FocusChangedHandler ( item ) ;
return ;
}
2019-08-23 11:56:54 -07:00
}
mListView . GetRoot ( ) . SelectItem ( item , checkKeyStates ) ;
if ( item = = null )
return ;
SetFocus ( ) ;
}
public override void LostFocus ( )
{
base . LostFocus ( ) ;
//SelectItem(null);
}
void RemoveProject ( Project project )
{
var app = IDEApp . sApp ;
//var workspace = IDEApp.sApp.mWorkspace;
app . RemoveProject ( project ) ;
}
2020-01-23 07:43:44 -08:00
void ProjectItemUnregister ( ProjectItem projectItem , bool isRemovingProjectSource )
2019-08-23 11:56:54 -07:00
{
var projectSource = projectItem as ProjectSource ;
if ( projectSource ! = null )
{
2020-06-04 17:19:57 -07:00
bool isProjectSourceEnabled = gApp . IsProjectSourceEnabled ( projectSource ) ;
2019-08-23 11:56:54 -07:00
String fullPath = scope String ( ) ;
projectSource . GetFullImportPath ( fullPath ) ;
gApp . mWorkspace . mForceNextCompile = true ;
2020-06-04 17:19:57 -07:00
if ( ( IDEApp . IsBeefFile ( fullPath ) ) & & ( isProjectSourceEnabled ) )
2019-08-23 11:56:54 -07:00
{
var compilers = scope List < BfCompiler > ( ) ;
IDEApp . sApp . GetBfCompilers ( compilers ) ;
for ( var bfCompiler in compilers )
{
bfCompiler . QueueProjectSourceRemoved ( projectSource ) ;
}
gApp . mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
}
#if IDE_C_SUPPORT
else if ( IDEApp . IsClangSourceFile ( fullPath ) )
{
IDEApp . sApp . mDepClang . QueueProjectSourceRemoved ( projectSource ) ;
}
#endif
gApp . WithTabs ( scope ( tab ) = >
{
var sourceViewPanel = tab . mContent as SourceViewPanel ;
if ( ( sourceViewPanel ! = null ) & & ( sourceViewPanel . mProjectSource = = projectSource ) )
{
2020-01-23 07:43:44 -08:00
if ( isRemovingProjectSource )
2020-05-20 06:43:41 -07:00
sourceViewPanel . DetachFromProjectItem ( true ) ;
2020-01-20 17:12:07 -08:00
else
sourceViewPanel . QueueFullRefresh ( true ) ;
2019-08-23 11:56:54 -07:00
}
} ) ;
2020-06-04 17:19:57 -07:00
if ( isProjectSourceEnabled )
2019-08-23 11:56:54 -07:00
{
2020-01-23 07:43:44 -08:00
if ( isRemovingProjectSource )
2020-01-20 17:12:07 -08:00
{
gApp . mBfResolveHelper . ProjectSourceRemoved ( projectSource ) ;
gApp . mWorkspace . ProjectSourceRemoved ( projectSource ) ;
}
2019-08-23 11:56:54 -07:00
gApp . RefreshVisibleViews ( ) ;
}
}
}
void ProjectItemRegister ( Project projectItem )
{
}
2020-06-04 17:19:57 -07:00
enum DeleteItemKind
{
Normal ,
ForceRemove ,
Ignore
}
public void DoDeleteItem ( ListViewItem listItem , delegate bool ( String path ) deletePathFunc , DeleteItemKind deleteKind = . Normal )
2019-08-23 11:56:54 -07:00
{
var projectItemRoot = mListViewToProjectMap [ listItem ] ;
var projectItem = projectItemRoot ;
if ( ( projectItem ! = null ) & & ( projectItem . mParentFolder = = null ) )
{
// Removing full project
mProjectToListViewMap . Remove ( projectItem ) ;
mListViewToProjectMap . Remove ( listItem ) ;
listItem . mParentItem . RemoveChildItem ( listItem ) ;
Project project = projectItem . mProject ;
gApp . WithTabs ( scope ( tab ) = >
{
var sourceViewPanel = tab . mContent as SourceViewPanel ;
2019-12-01 14:40:17 -08:00
//if (sourceViewPanel?.mProjectSource?.mProject == project)
if ( ( sourceViewPanel ! = null ) & &
( sourceViewPanel . mProjectSource ! = null ) & &
( sourceViewPanel . mProjectSource . mProject = = project ) )
2019-08-23 11:56:54 -07:00
{
2020-05-20 06:43:41 -07:00
sourceViewPanel . DetachFromProjectItem ( true ) ;
2019-08-23 11:56:54 -07:00
}
} ) ;
2020-06-05 14:17:06 -07:00
project . mRootFolder . Dispose ( ) ;
2019-08-23 11:56:54 -07:00
RemoveProject ( project ) ;
return ;
}
if ( listItem . mChildItems ! = null )
{
for ( int childIdx = listItem . mChildItems . Count - 1 ; childIdx > = 0 ; childIdx - - )
2020-06-04 17:19:57 -07:00
{
var childDeleteKind = deleteKind ;
if ( childDeleteKind = = . Normal )
childDeleteKind = . ForceRemove ;
DoDeleteItem ( listItem . mChildItems [ childIdx ] , deletePathFunc , childDeleteKind ) ;
}
2019-08-23 11:56:54 -07:00
}
if ( projectItem = = null )
return ;
bool doReleaseRef = false ;
bool didRemove = false ;
2020-06-04 17:19:57 -07:00
if ( ( deleteKind = = . ForceRemove ) | | ( projectItem . mParentFolder = = null ) | | ( projectItem . mParentFolder . mIncludeKind = = . Manual ) | | ( projectItem . mIncludeKind = = . Manual ) | | ( deletePathFunc ! = null ) )
2019-08-23 11:56:54 -07:00
{
bool doRemove = true ;
if ( deletePathFunc ! = null )
{
if ( let projectFileItem = projectItem as ProjectFileItem )
{
var path = scope String ( ) ;
projectFileItem . GetFullImportPath ( path ) ;
doRemove = deletePathFunc ( path ) ;
}
}
if ( doRemove )
{
if ( projectItem . mParentFolder ! = null )
projectItem . mParentFolder . RemoveChild ( projectItem ) ;
mProjectToListViewMap . Remove ( projectItem ) ;
mListViewToProjectMap . Remove ( listItem ) ;
if ( projectItem . mIncludeKind ! = . Auto )
projectItem . mProject . SetChanged ( ) ;
doReleaseRef = true ;
didRemove = true ;
}
}
else
{
2020-01-20 17:12:07 -08:00
if ( let projectSource = projectItem as ProjectSource )
{
String path = scope . ( ) ;
projectSource . GetFullImportPath ( path ) ;
gApp . mErrorsPanel . ClearParserErrors ( path ) ;
}
2019-08-23 11:56:54 -07:00
}
2020-01-23 07:43:44 -08:00
ProjectItemUnregister ( projectItem , didRemove ) ;
2019-08-23 11:56:54 -07:00
if ( ( didRemove ) | | ( ! mShowIgnored ) )
2020-01-20 17:12:07 -08:00
{
listItem . mParentItem . RemoveChildItem ( listItem ) ;
using ( gApp . mMonitor . Enter ( ) )
projectItem . Dispose ( ) ;
}
2019-08-23 11:56:54 -07:00
if ( doReleaseRef )
projectItem . ReleaseRef ( ) ;
//TODO: Defer this, projectItem is needed for a backgrounded QueueProjectSourceRemoved
//delete projectItem;
}
void RemoveSelectedItems ( bool deleteFiles )
{
List < ListViewItem > selectedItems = scope List < ListViewItem > ( ) ;
//selectedItems.AddRange(mListView.GetRoot().FindSelectedItems(true));
mListView . GetRoot ( ) . WithSelectedItems ( scope ( listViewItem ) = >
{
selectedItems . Add ( listViewItem ) ;
} , true ) ;
int fileErrorCount = 0 ;
String fileErrors = scope String ( ) ;
bool hadOverflow = false ;
for ( var selectedItem in selectedItems )
{
//var projectItem = mListViewToProjectMap[selectedItem];
if ( ! deleteFiles )
{
2020-09-19 07:30:20 -07:00
mListViewToProjectMap . TryGetValue ( selectedItem , var projectItem ) ;
if ( ( projectItem ! = null ) & & ( projectItem . mIncludeKind = = . Auto ) )
{
DoDeleteItem ( selectedItem , null , . Ignore ) ;
projectItem . mIncludeKind = . Ignore ;
projectItem . mProject . SetChanged ( ) ;
}
else
DoDeleteItem ( selectedItem , null ) ;
2019-08-23 11:56:54 -07:00
}
else
{
DoDeleteItem ( selectedItem , scope [ & ] ( filePath ) = >
{
if ( File . Delete ( filePath ) case . Ok )
return true ;
2020-05-07 05:39:53 -07:00
if ( Directory . Delete ( filePath ) case . Ok )
return true ;
2019-08-23 11:56:54 -07:00
fileErrorCount + + ;
const int maxErrorLen = 4096 ;
if ( ( fileErrors . Length < maxErrorLen ) & & ( ! hadOverflow ) )
{
if ( ! fileErrors . IsEmpty )
fileErrors . Append ( ", " ) ;
if ( fileErrors . Length + filePath . Length < maxErrorLen )
fileErrors . Append ( filePath ) ;
else
{
fileErrors . Append ( "..." ) ;
hadOverflow = true ;
}
}
return false ;
} ) ;
}
/ * if ( projectItem . mIncludeKind = = . Auto )
{
projectItem . mIncludeKind = . Ignore ;
projectItem . mProject . SetChanged ( ) ;
} * /
}
if ( ! fileErrors . IsEmpty )
{
var errorStr = scope String ( ) ;
if ( fileErrorCount = = 1 )
errorStr . AppendF ( "Failed to delete file: {0}" , fileErrors ) ;
else
errorStr . AppendF ( "Failed to delete {0} files: {1}" , fileErrorCount , fileErrors ) ;
gApp . Fail ( errorStr ) ;
}
}
void RemoveSelectedItems ( )
{
int32 projectCount = 0 ;
int32 fileCount = 0 ;
int32 folderCount = 0 ;
bool hadProjectItemsSelected = false ;
HashSet < Project > projectsReferenced = scope HashSet < Project > ( ) ;
ProjectItem selectedProjectItem = null ;
mListView . GetRoot ( ) . WithSelectedItems ( scope [ & ] ( selectedItem ) = >
{
mListViewToProjectMap . TryGetValue ( selectedItem , out selectedProjectItem ) ;
if ( selectedProjectItem ! = null )
{
if ( selectedProjectItem . mParentFolder = = null )
{
projectCount + + ;
hadProjectItemsSelected = selectedItem . FindLastSelectedItem ( ) ! = selectedItem ;
}
else if ( selectedProjectItem is ProjectFolder )
{
projectsReferenced . Add ( selectedProjectItem . mProject ) ;
folderCount + + ;
}
2019-10-04 10:39:25 -07:00
else
2019-08-23 11:56:54 -07:00
{
projectsReferenced . Add ( selectedProjectItem . mProject ) ;
fileCount + + ;
}
}
} , true ) ;
if ( selectedProjectItem ! = null )
{
if ( projectCount > 0 )
{
if ( ! hadProjectItemsSelected )
{
Dialog aDialog ;
if ( projectCount = = 1 )
{
aDialog = ThemeFactory . mDefault . CreateDialog ( "Remove Project" , StackStringFormat ! ( "Remove project '{0}' from the workspace?" , selectedProjectItem . mProject . mProjectName ) ) ;
}
else
{
aDialog = ThemeFactory . mDefault . CreateDialog ( "Remove Projects" , "Remove the selected projects from the workspace?" ) ;
}
aDialog . mDefaultButton = aDialog . AddButton ( "Yes" , new ( evt ) = > RemoveSelectedItems ( false ) ) ;
aDialog . mEscButton = aDialog . AddButton ( "No" ) ;
2019-09-05 08:18:24 -07:00
aDialog . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
}
}
else if ( ( fileCount > 0 ) | | ( folderCount > 0 ) )
{
Dialog aDialog ;
if ( fileCount + folderCount = = 1 )
{
aDialog = ThemeFactory . mDefault . CreateDialog ( ( fileCount > 0 ) ? "Delete File" : "Delete Folder" ,
StackStringFormat ! ( "Choose Remove to remove '{0}' from '{1}'.\n\nChoose Delete to permanently delete '{0}'." , selectedProjectItem . mName , selectedProjectItem . mProject . mProjectName ) ) ;
}
else
{
String typeDeleting = null ; //TODO: Why do we need this assignment?
String title = null ;
if ( folderCount = = 0 )
{
title = "Delete Files" ;
typeDeleting = "files" ;
}
else if ( fileCount = = 0 )
{
title = "Delete Folders" ;
typeDeleting = "folders" ;
}
else
{
title = "Delete Items" ;
typeDeleting = "items" ;
}
if ( projectsReferenced . Count = = 1 )
{
aDialog = ThemeFactory . mDefault . CreateDialog ( title ,
StackStringFormat ! ( "Choose Remove to remove the selected {0} from '{1}'.\n\nChoose Delete to permanently delete the selected items." , typeDeleting , selectedProjectItem . mProject . mProjectName ) ) ;
}
else
{
aDialog = ThemeFactory . mDefault . CreateDialog ( title ,
StackStringFormat ! ( "Choose Remove to removed the selected {0}.\n\nChoose Delete to permanently delete the selected items." , typeDeleting ) ) ;
}
}
aDialog . mDefaultButton = aDialog . AddButton ( "Remove" , new ( evt ) = >
{
aDialog . Close ( ) ;
RemoveSelectedItems ( false ) ;
} ) ;
aDialog . AddButton ( "Delete" , new ( evt ) = >
{
aDialog . Close ( ) ;
RemoveSelectedItems ( true ) ;
} ) ;
aDialog . mEscButton = aDialog . AddButton ( "Cancel" ) ;
2019-09-05 08:18:24 -07:00
aDialog . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
}
}
}
public override void KeyDown ( KeyCode keyCode , bool isRepeat )
{
mListView . KeyDown ( keyCode , isRepeat ) ;
if ( keyCode = = . Apps )
{
ShowRightClickMenu ( mListView ) ;
return ;
}
base . KeyDown ( keyCode , isRepeat ) ;
if ( keyCode = = KeyCode . Delete )
RemoveSelectedItems ( ) ;
}
void ItemClicked ( MouseEvent theEvent )
{
SetFocus ( ) ;
ListViewItem prevSelectedItem = ( ListViewItem ) mListView . GetRoot ( ) . FindFirstSelectedItem ( ) ;
DarkListViewItem clickedItem = ( DarkListViewItem ) theEvent . mSender ;
if ( clickedItem . mColumnIdx ! = 0 )
{
if ( ( clickedItem . mColumnIdx = = 1 ) & & ( prevSelectedItem = = clickedItem . GetSubItem ( 0 ) ) )
{
EditListViewItem ( clickedItem ) ;
return ;
}
clickedItem = ( DarkListViewItem ) clickedItem . GetSubItem ( 0 ) ;
}
2019-09-28 12:15:36 -07:00
if ( theEvent . mBtn ! = 0 )
{
if ( clickedItem . Selected )
return ;
}
2019-08-23 11:56:54 -07:00
SelectItem ( clickedItem , true ) ;
if ( ( ! clickedItem . IsParent ) & & ( theEvent . mBtnCount > 1 ) )
{
ProjectItem aProjectItem ;
mListViewToProjectMap . TryGetValue ( clickedItem , out aProjectItem ) ;
if ( aProjectItem ! = null )
{
IDEApp . sApp . ShowProjectItem ( aProjectItem , false , true ) ;
}
}
}
void DeselectFolder ( BFWindow window )
{
ListViewItem selectedItem = mListView . GetRoot ( ) . FindFirstSelectedItem ( ) ;
if ( ( selectedItem ! = null ) & & ( selectedItem . IsParent ) )
selectedItem . Selected = false ;
}
void FinishRenameFolder ( String newValue , bool doMove )
{
bool failed = false ;
var projectFolder = GetSelectedProjectItem ( ) as ProjectFolder ;
if ( projectFolder = = null )
return ;
if ( doMove )
{
String fileName = scope String ( ) ;
Path . GetFileName ( projectFolder . mPath , fileName ) ;
if ( fileName = = projectFolder . mName )
{
String importDir = scope String ( ) ;
Path . GetDirectoryPath ( projectFolder . mPath , importDir ) ;
importDir . Append ( "/" , newValue ) ;
String oldFullName = scope String ( ) ;
projectFolder . mProject . GetProjectFullPath ( projectFolder . mPath , oldFullName ) ;
String newFullName = scope String ( ) ;
projectFolder . mProject . GetProjectFullPath ( importDir , newFullName ) ;
if ( Directory . Exists ( oldFullName ) )
{
if ( Directory . Move ( oldFullName , newFullName ) case . Err )
failed = true ;
}
//if (!failed)
//String.NewOrSet!(projectFolder.mPath, importDir);
}
}
else
{
//projectFolder.mName.Set(newValue);
}
if ( failed )
{
//IDEApp.sApp.Fail(ex.Message.Replace("\r", ""));
IDEApp . sApp . Fail ( "Failed to rename item" ) ;
IDEApp . Beep ( IDEApp . MessageBeepType . Error ) ;
return ;
}
// Item renamed
/ * listViewItem . Label = newValue ;
if ( projectFolder . mIncludeKind ! = . Auto )
projectFolder . mProject . SetChanged ( ) ;
Sort ( ) ; * /
}
void HandleEditDone ( EditWidget editWidget , bool cancelled )
{
String newValue = scope String ( ) ;
editWidget . GetText ( newValue ) ;
newValue . Trim ( ) ;
if ( newValue . IsEmpty )
return ;
/ * editWidget . RemoveSelf ( ) ;
gApp . DeferDelete ( editWidget ) ; * /
ListViewItem listViewItem = mListView . mEditingItem ;
int32 column = listViewItem . mColumnIdx ;
ProjectItem projectItem = mListViewToProjectMap [ listViewItem . GetMainItem ( ) ] ;
if ( projectItem = = null )
return ;
bool didRename = true ;
if ( ( ! mListView . mCancelingEdit ) & & ( listViewItem . mLabel ! = newValue ) )
{
if ( column = = 0 )
{
bool failed = false ;
RenameBlock : do
{
var projectFolder = projectItem as ProjectFolder ;
if ( ( projectFolder ! = null ) & & ( projectFolder . mParentFolder = = null ) )
{
gApp . RenameProject ( projectFolder . mProject , newValue ) ;
break ;
}
var projectSource = projectItem as ProjectSource ;
if ( projectSource ! = null )
{
var prevPath = scope String ( ) ;
projectSource . mProject . GetProjectFullPath ( projectSource . mPath , prevPath ) ;
projectSource . mHasChangedSinceLastCompile = true ;
var nameParts = scope List < StringView > ( projectSource . mPath . Split ( IDEUtils . cNativeSlash , IDEUtils . cOtherSlash ) ) ;
nameParts [ nameParts . Count - 1 ] = StringView ( newValue ) ;
String newRelPath = scope String ( ) ;
newRelPath . Join ( "/" , nameParts . GetEnumerator ( ) ) ;
var newPath = scope String ( ) ;
projectSource . mProject . GetProjectFullPath ( newRelPath , newPath ) ;
/ * if ( ( IDEApp . IsBeefFile ( prevPath ) ! = IDEApp . IsBeefFile ( newPath ) ) | |
( IDEApp . IsClangSourceFile ( prevPath ) ! = IDEApp . IsClangSourceFile ( newPath ) ) )
{
IDEApp . sApp . Fail ( StackStringFormat ! ( "Invalid file extension change, cannot rename '{0}' to '{1}'" , prevPath , newPath ) ) ;
return ;
} * /
if ( File . Exists ( prevPath ) )
{
if ( File . Move ( prevPath , newPath ) case . Err )
{
failed = true ;
break ;
}
}
if ( IDEApp . IsBeefFile ( prevPath ) )
{
var bfSystems = scope List < BfSystem > ( ) ;
IDEApp . sApp . GetBfSystems ( bfSystems ) ;
for ( var system in bfSystems )
system . FileRenamed ( projectSource , prevPath , newPath ) ;
}
projectSource . Rename ( newValue ) ;
//projectSource.mName.Set(newValue);
//projectSource.mPath.Set(newRelPath);
//Sort();
#if IDE_C_SUPPORT
if ( IDEApp . IsClangSourceFile ( prevPath ) )
{
var buildClang = IDEApp . sApp . mDepClang ;
buildClang . QueueFileRemoved ( prevPath ) ;
buildClang . QueueProjectSource ( projectSource ) ;
}
#endif
IDEApp . sApp . FileRenamed ( projectSource , prevPath , newPath ) ;
}
if ( projectFolder ! = null )
{
if ( projectFolder . mIncludeKind = = . Auto )
{
FinishRenameFolder ( newValue , true ) ;
}
else
{
if ( projectFolder . HasAlias ( ) )
{
FinishRenameFolder ( newValue , false ) ;
}
else
{
Dialog dialog = ThemeFactory . mDefault . CreateDialog ( "Rename Folder" ,
"Choose Alias to change the folder name in just the project.\n\nChoose Move to rename the actual system directory." ) ;
var oldValue = new String ( projectItem . mName ) ;
var newName = new String ( newValue ) ;
dialog . mDefaultButton = dialog . AddButton ( "Alias" ,
new ( evt ) = >
{
//FinishRenameFolder(newName, false);
projectFolder . Rename ( newName , false ) ;
Sort ( ) ;
}
~ delete newName ) ;
dialog . AddButton ( "Move" , new ( evt ) = >
{
FinishRenameFolder ( newName , true ) ;
projectFolder . Rename ( newName , true ) ;
Sort ( ) ;
} ) ;
dialog . mEscButton = dialog . AddButton ( "Cancel" , new ( evt ) = >
{
// Item renamed
listViewItem . Label = oldValue ;
if ( projectItem . mIncludeKind ! = . Auto )
projectItem . mProject . SetChanged ( ) ;
Sort ( ) ;
}
~ delete oldValue ) ;
2019-09-05 08:18:24 -07:00
dialog . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
didRename = false ;
}
}
//projectFolder.mName.Set(newValue);
//IDEApp.sApp.Fail("Cannot rename a folder");
}
if ( ( ! failed ) & & ( didRename ) )
{
if ( var projectFileItem = projectItem as ProjectFileItem )
{
projectFileItem . Rename ( newValue ) ;
}
else if ( projectItem ! = null )
{
projectItem . mName . Set ( newValue ) ;
}
}
}
if ( failed )
{
//IDEApp.sApp.Fail(ex.Message.Replace("\r", ""));
IDEApp . sApp . Fail ( "Failed to rename item" ) ;
IDEApp . Beep ( IDEApp . MessageBeepType . Error ) ;
return ;
}
}
else if ( column = = 1 )
{
}
// Item renamed
listViewItem . Label = newValue ;
if ( projectItem . mIncludeKind ! = . Auto )
projectItem . mProject . SetChanged ( ) ;
var parentLvItem = ( ProjectListViewItem ) listViewItem . mParentItem ;
QueueSortItem ( parentLvItem ) ;
Sort ( ) ;
}
SetFocus ( ) ;
}
void EditListViewItem ( ListViewItem listViewItem )
{
mListView . EditListViewItem ( listViewItem ) ;
2020-08-13 07:01:33 -07:00
if ( mListView . mEditWidget ! = null )
{
String str = scope . ( ) ;
mListView . mEditWidget . GetText ( str ) ;
int lastDot = str . LastIndexOf ( '.' ) ;
if ( lastDot ! = - 1 )
{
mListView . mEditWidget . mEditWidgetContent . mSelection = . ( 0 , lastDot ) ;
mListView . mEditWidget . mEditWidgetContent . CursorTextPos = lastDot ;
}
}
2019-08-23 11:56:54 -07:00
}
void RenameItem ( ProjectItem projectItem )
{
DarkListViewItem editItem = ( DarkListViewItem ) mProjectToListViewMap [ projectItem ] ;
EditListViewItem ( editItem ) ;
}
public void TryRenameItem ( )
{
ListViewItem selectedListViewItem = mListView . GetRoot ( ) . FindFocusedItem ( ) ;
if ( selectedListViewItem ! = null )
{
ProjectItem projectItem ;
mListViewToProjectMap . TryGetValue ( selectedListViewItem , out projectItem ) ;
2020-09-25 09:32:42 -07:00
if ( projectItem ! = null )
RenameItem ( projectItem ) ;
2019-08-23 11:56:54 -07:00
}
}
public Project ImportProject ( String filePath , VerSpecRecord verSpec = null )
{
if ( ! File . Exists ( filePath ) )
{
gApp . Fail ( StackStringFormat ! ( "Project file not found: {0}" , filePath ) ) ;
return null ;
}
2019-09-18 08:18:20 -07:00
if ( ! gApp . mWorkspace . IsInitialized )
{
String projPath = scope . ( ) ;
Path . GetDirectoryPath ( filePath , projPath ) ;
projPath . Concat ( Path . DirectorySeparatorChar , "BeefSpace.toml" ) ;
gApp . OpenWorkspace ( projPath ) ;
for ( let project in gApp . mWorkspace . mProjects )
{
if ( Path . Equals ( project . mProjectPath , filePath ) )
return project ;
}
return null ;
}
2020-09-06 06:14:39 -07:00
bool failed = false ;
2019-08-23 11:56:54 -07:00
String projName = scope String ( ) ;
Path . GetFileNameWithoutExtension ( filePath , projName ) ;
if ( gApp . mWorkspace . FindProject ( projName ) ! = null )
{
gApp . Fail ( StackStringFormat ! ( "A project named '{0}' name already exists in the workspace." , projName ) ) ;
return null ;
}
2020-08-31 11:32:33 -07:00
gApp . CheckLoadConfig ( ) ;
2019-08-23 11:56:54 -07:00
//TODO: Protect against importing an existing project
Project proj = new Project ( ) ;
String projFilePath = scope String ( filePath ) ;
IDEUtils . FixFilePath ( projFilePath ) ;
proj . mProjectPath . Set ( projFilePath ) ;
proj . Load ( projFilePath ) ;
2020-09-06 06:14:39 -07:00
gApp . AddNewProjectToWorkspace ( proj , verSpec ) ;
gApp . mWorkspace . FixOptions ( ) ;
gApp . [ Friend ] FlushDeferredLoadProjects ( true ) ;
2019-08-23 11:56:54 -07:00
InitProject ( proj ) ;
if ( failed )
{
gApp . Fail ( StackStringFormat ! ( "Failed to load project: {0}" , filePath ) ) ;
return proj ;
}
return proj ;
}
void ImportProject ( )
{
#if ! CLI
2019-10-04 10:39:25 -07:00
gApp . mBeefConfig . Refresh ( ) ;
2019-08-23 11:56:54 -07:00
var fileDialog = scope OpenFileDialog ( ) ;
fileDialog . ShowReadOnly = false ;
fileDialog . Title = "Import Project" ;
fileDialog . Multiselect = false ;
2019-09-18 08:18:20 -07:00
var initialDir = scope String ( ) ;
if ( gApp . mWorkspace . mDir ! = null )
initialDir . Append ( gApp . mWorkspace . mDir ) ;
else
{
if ( gApp . mInstallDir . Length > 0 )
Path . GetDirectoryPath ( . ( gApp . mInstallDir , 0 , gApp . mInstallDir . Length - 1 ) , initialDir ) ;
initialDir . Concat ( Path . DirectorySeparatorChar , "Samples" ) ;
}
2019-08-23 11:56:54 -07:00
fileDialog . InitialDirectory = initialDir ;
fileDialog . ValidateNames = true ;
fileDialog . DefaultExt = ".toml" ;
fileDialog . SetFilter ( "Beef projects (BeefProj.toml)|BeefProj.toml|All files (*.*)|*.*" ) ;
2019-09-05 08:18:24 -07:00
gApp . GetActiveWindow ( ) . PreModalChild ( ) ;
2019-08-23 11:56:54 -07:00
if ( fileDialog . ShowDialog ( gApp . GetActiveWindow ( ) ) . GetValueOrDefault ( ) = = . OK )
{
for ( String origProjFilePath in fileDialog . FileNames )
{
ImportProject ( origProjFilePath ) ;
}
}
#endif
}
void ImportInstalledProject ( )
{
#if ! CLI
InstalledProjectDialog dialog = new . ( ) ;
dialog . PopupWindow ( gApp . mMainWindow ) ;
#endif
}
public void ShowProjectProperties ( Project project )
{
var projectProperties = new ProjectProperties ( project ) ;
2019-09-05 08:18:24 -07:00
projectProperties . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
}
public void ShowWorkspaceProperties ( )
{
var workspaceProperties = new WorkspaceProperties ( ) ;
2019-09-05 08:18:24 -07:00
workspaceProperties . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
}
public void RehupProjects ( )
{
for ( var checkProject in IDEApp . sApp . mWorkspace . mProjects )
{
var listViewItem = ( DarkListViewItem ) mProjectToListViewMap [ checkProject . mRootFolder ] ;
listViewItem . mIsBold = checkProject = = IDEApp . sApp . mWorkspace . mStartupProject ;
var projectOptions = IDEApp . sApp . GetCurProjectOptions ( checkProject ) ;
2020-10-05 14:25:55 -07:00
listViewItem . mTextColor = Color . Mult ( DarkTheme . COLOR_TEXT , ( projectOptions ! = null ) ? gApp . mSettings . mUISettings . mColors . mText : gApp . mSettings . mUISettings . mColors . mWorkspaceDisabledText ) ;
2019-08-23 11:56:54 -07:00
if ( checkProject . mFailed )
2020-10-05 14:25:55 -07:00
listViewItem . mTextColor = Color . Mult ( DarkTheme . COLOR_TEXT , gApp . mSettings . mUISettings . mColors . mWorkspaceFailedText ) ;
2019-08-23 11:56:54 -07:00
}
}
void SetAsStartupProject ( Project project )
{
IDEApp . sApp . mWorkspace . mStartupProject = project ;
IDEApp . sApp . mWorkspace . SetChanged ( ) ;
RehupProjects ( ) ;
}
void AddNewProject ( )
{
var newProjectDialog = new NewProjectDialog ( ) ;
newProjectDialog . Init ( ) ;
2019-09-05 08:18:24 -07:00
newProjectDialog . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
}
protected override void ShowRightClickMenu ( Widget relWidget , float x , float y )
{
ProjectItem projectItem = null ;
mSelectedParentItem = ( DarkListViewItem ) GetSelectedParentItem ( ) ;
var focusedItem = mListView . GetRoot ( ) . FindFocusedItem ( ) ;
if ( focusedItem ! = null )
mListViewToProjectMap . TryGetValue ( focusedItem , out projectItem ) ;
Menu menu = new Menu ( ) ;
bool handled = false ;
2020-04-26 05:54:19 -07:00
void AddOpenContainingFolder ( )
{
var item = menu . AddItem ( "Open Containing Folder" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
let projectItem = GetSelectedProjectItem ( ) ;
String path = scope String ( ) ;
if ( projectItem = = null )
{
path . Set ( gApp . mWorkspace . mDir ) ;
}
else if ( let projectFolder = projectItem as ProjectFolder )
{
if ( projectFolder . mParentFolder = = null )
{
path . Set ( projectFolder . mProject . mProjectDir ) ;
}
else
projectFolder . GetFullImportPath ( path ) ;
}
else
projectItem . mParentFolder . GetFullImportPath ( path ) ;
if ( ! path . IsWhiteSpace )
{
ProcessStartInfo psi = scope ProcessStartInfo ( ) ;
psi . SetFileName ( path ) ;
psi . UseShellExecute = true ;
psi . SetVerb ( "Open" ) ;
var process = scope SpawnedProcess ( ) ;
process . Start ( psi ) . IgnoreError ( ) ;
}
} ) ;
}
2019-08-23 11:56:54 -07:00
if ( projectItem = = null )
{
Menu anItem ;
if ( gApp . mWorkspace . IsInitialized )
{
2020-04-26 05:54:19 -07:00
AddOpenContainingFolder ( ) ;
menu . AddItem ( ) ;
2019-08-23 11:56:54 -07:00
anItem = menu . AddItem ( "Add New Project..." ) ;
anItem . mOnMenuItemSelected . Add ( new ( item ) = > { AddNewProject ( ) ; } ) ;
anItem = menu . AddItem ( "Add Existing Project..." ) ;
anItem . mOnMenuItemSelected . Add ( new ( item ) = > { mImportProjectDeferred = true ; } ) ;
anItem = menu . AddItem ( "Add From Installed..." ) ;
anItem . mOnMenuItemSelected . Add ( new ( item ) = > { mImportInstalledDeferred = true ; } ) ;
2020-04-26 05:54:19 -07:00
menu . AddItem ( ) ;
2019-08-23 11:56:54 -07:00
anItem = menu . AddItem ( "Properties..." ) ;
anItem . mOnMenuItemSelected . Add ( new ( item ) = > { ShowWorkspaceProperties ( ) ; } ) ;
handled = true ;
}
}
bool isProject = false ;
2020-11-16 17:44:04 -08:00
bool isFailedLoad = false ;
2019-08-23 11:56:54 -07:00
if ( ( projectItem ! = null ) & & ( ! handled ) )
{
if ( projectItem is ProjectFolder )
{
if ( projectItem . mParentFolder = = null )
{
isProject = true ;
var project = projectItem . mProject ;
if ( project . mFailed )
{
var item = menu . AddItem ( "Retry Load" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem ! = null )
gApp . RetryProjectLoad ( projectItem . mProject ) ;
} ) ;
2020-11-16 17:44:04 -08:00
menu . AddItem ( ) ;
//handled = true;
isFailedLoad = true ;
2019-08-23 11:56:54 -07:00
}
}
}
}
if ( ( projectItem ! = null ) & & ( ! handled ) )
{
Menu item = null ;
2019-09-05 08:18:24 -07:00
if ( isProject )
{
2020-11-16 17:44:04 -08:00
if ( ! isFailedLoad )
{
item = menu . AddItem ( "Set as Startup Project" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem ! = null )
SetAsStartupProject ( projectItem . mProject ) ;
} ) ;
2019-09-05 08:18:24 -07:00
2020-11-16 17:44:04 -08:00
item = menu . AddItem ( "Lock Project" ) ;
if ( projectItem . mProject . mLocked )
item . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem ! = null )
{
projectItem . mProject . mLocked = ! projectItem . mProject . mLocked ;
gApp . mWorkspace . SetChanged ( ) ;
}
} ) ;
}
2020-04-30 10:25:19 -07:00
item = menu . AddItem ( "Remove..." ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
RemoveSelectedItems ( ) ;
} ) ;
2019-09-29 07:44:23 -07:00
item = menu . AddItem ( "Rename" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem ! = null )
RenameItem ( projectItem ) ;
} ) ;
2019-09-05 08:18:24 -07:00
2020-11-16 17:44:04 -08:00
if ( ! isFailedLoad )
{
item = menu . AddItem ( "Refresh" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem ! = null )
2019-09-05 08:18:24 -07:00
{
2020-11-16 17:44:04 -08:00
let project = projectItem . mProject ;
if ( project . mNeedsCreate )
{
project . FinishCreate ( false ) ;
RebuildUI ( ) ;
}
else
{
if ( project . mRootFolder . mIsWatching )
project . mRootFolder . StopWatching ( ) ;
project . mRootFolder . StartWatching ( ) ;
RehupFolder ( project . mRootFolder , . FullTraversal ) ;
}
2019-09-05 08:18:24 -07:00
}
2020-11-16 17:44:04 -08:00
} ) ;
}
2020-04-26 05:54:19 -07:00
2020-11-16 17:44:04 -08:00
if ( ! isFailedLoad )
{
AddOpenContainingFolder ( ) ;
menu . AddItem ( ) ;
}
2019-09-05 08:18:24 -07:00
}
2019-08-23 11:56:54 -07:00
if ( ( projectItem ! = null ) & & ( ! isProject ) )
{
item = menu . AddItem ( "Remove ..." ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
RemoveSelectedItems ( ) ;
} ) ;
item = menu . AddItem ( "Rename" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem ! = null )
RenameItem ( projectItem ) ;
} ) ;
if ( projectItem . mIncludeKind = = . Auto )
{
item = menu . AddItem ( "Ignore" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var selectedItem = GetSelectedItem ( ) ;
if ( selectedItem ! = null )
{
ProjectItem projectItem ;
mListViewToProjectMap . TryGetValue ( selectedItem , out projectItem ) ;
2020-06-04 17:19:57 -07:00
DoDeleteItem ( selectedItem , null , . Ignore ) ;
2019-08-23 11:56:54 -07:00
if ( projectItem ! = null )
{
2020-06-04 17:19:57 -07:00
projectItem . mIncludeKind = . Ignore ;
2019-08-23 11:56:54 -07:00
projectItem . mProject . SetChanged ( ) ;
}
}
} ) ;
}
else if ( projectItem . mIncludeKind = = . Manual )
{
/ * item = menu . AddItem ( "Remove" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var selectedItem = GetSelectedItem ( ) ;
if ( selectedItem ! = null )
DoDeleteItem ( selectedItem , null ) ;
} ) ; * /
}
else if ( projectItem . mIncludeKind = = . Ignore )
{
item = menu . AddItem ( "Unignore" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( ( projectItem ! = null ) & & ( projectItem . mIncludeKind = = . Ignore ) )
{
if ( projectItem . mParentFolder . IsIgnored ( ) )
projectItem . mIncludeKind = . Auto ;
else
Unignore ( projectItem ) ;
}
} ) ;
}
if ( let projectFolder = projectItem as ProjectFolder )
{
//if (projectFolder.mIncludeKind == .Manual)
{
item = menu . AddItem ( "Auto Include" ) ;
if ( projectFolder . mAutoInclude )
item . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
let projectItem = GetSelectedProjectItem ( ) ;
if ( let projectFolder = projectItem as ProjectFolder )
{
projectFolder . mProject . SetChanged ( ) ;
projectFolder . mAutoInclude = ! projectFolder . mAutoInclude ;
if ( projectFolder . mAutoInclude )
{
if ( HasNonAutoItems ( projectFolder ) )
{
var dialog = ThemeFactory . mDefault . CreateDialog ( "Apply to children?" ,
"Do you want to apply auto-include to child items? Selecting 'no' means that current child items will remain manually specified and only new items will be auto-included." ) ;
dialog . AddButton ( "Yes" , new ( evt ) = >
{
let projectItem = GetSelectedProjectItem ( ) ;
if ( let projectFolder = projectItem as ProjectFolder )
{
RehupFolder ( projectFolder , . ApplyAutoToChildren ) ;
}
} ) ;
dialog . AddButton ( "No" , new ( evt ) = >
{
let projectItem = GetSelectedProjectItem ( ) ;
if ( let projectFolder = projectItem as ProjectFolder )
{
RehupFolder ( projectFolder ) ;
}
} ) ;
2019-09-05 08:18:24 -07:00
dialog . PopupWindow ( gApp . GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
}
else
RehupFolder ( projectFolder ) ;
}
else
//if ((!projectFolder.mAutoInclude) && (!projectFolder.IsAutoInclude()))
{
// Remove any previously auto-added items
for ( int childIdx = projectFolder . mChildItems . Count - 1 ; childIdx > = 0 ; childIdx - - )
{
let childItem = projectFolder . mChildItems [ childIdx ] ;
if ( childItem . mIncludeKind = = . Auto )
{
let listViewItem = ( ProjectListViewItem ) mProjectToListViewMap [ childItem ] ;
2020-06-04 17:19:57 -07:00
DoDeleteItem ( listViewItem , null , . ForceRemove ) ;
2019-08-23 11:56:54 -07:00
}
}
}
}
} ) ;
}
}
item = menu . AddItem ( "Copy Path" ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
let projectItem = GetSelectedProjectItem ( ) ;
String path = scope String ( ) ;
if ( var projectFileItem = projectItem as ProjectFileItem )
{
projectFileItem . GetFullImportPath ( path ) ;
gApp . SetClipboardText ( path ) ;
}
} ) ;
2020-04-26 05:54:19 -07:00
AddOpenContainingFolder ( ) ;
2019-08-23 11:56:54 -07:00
2019-09-05 08:18:24 -07:00
menu . AddItem ( ) ;
2019-08-23 11:56:54 -07:00
}
//menu.AddItem();
2020-11-16 17:44:04 -08:00
if ( ! isFailedLoad )
2019-08-23 11:56:54 -07:00
{
2020-11-16 17:44:04 -08:00
item = menu . AddItem ( "New Folder" ) ;
2019-08-23 11:56:54 -07:00
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
2020-11-16 17:44:04 -08:00
var projectFolder = GetSelectedProjectFolder ( ) ;
if ( projectFolder ! = null )
{
if ( CheckProjectModify ( projectFolder . mProject ) )
NewFolder ( projectFolder ) ;
}
2019-08-23 11:56:54 -07:00
} ) ;
2020-11-16 17:44:04 -08:00
item = menu . AddItem ( "New Class..." ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectFolder = GetSelectedProjectFolder ( ) ;
if ( projectFolder ! = null )
{
if ( CheckProjectModify ( projectFolder . mProject ) )
NewClass ( projectFolder ) ;
}
} ) ;
item = menu . AddItem ( "Import File..." ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = > { mImportFileDeferred = true ; /* ImportFile();*/ } ) ;
item = menu . AddItem ( "Import Folder..." ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = > { mImportFolderDeferred = true ; /* ImportFile();*/ } ) ;
if ( isProject )
{
menu . AddItem ( ) ;
item = menu . AddItem ( "Properties..." ) ;
item . mOnMenuItemSelected . Add ( new ( item ) = >
{
var projectItem = GetSelectedProjectItem ( ) ;
if ( projectItem ! = null )
ShowProjectProperties ( projectItem . mProject ) ;
} ) ;
}
2019-08-23 11:56:54 -07:00
}
}
/ * else if ( ! handled )
{
Menu anItem = menu . AddItem ( "Import Project" ) ;
anItem . mMenuItemSelectedHandler . Add ( new ( item ) = > { mImportProjectDeferred = true ; } ;
} * /
if ( menu . mItems . IsEmpty )
{
delete menu ;
return ;
}
MenuWidget menuWidget = ThemeFactory . mDefault . CreateMenuWidget ( menu ) ;
menuWidget . Init ( mListView . GetRoot ( ) , x , y ) ;
mMenuWidget = menuWidget ;
mMenuWidget . mOnRemovedFromParent . Add ( new ( widget , prevParent , widgetWindow ) = >
{
mMenuWidget = null ;
} ) ;
}
void ListViewItemClicked ( MouseEvent theEvent )
{
ListViewItem anItem = ( ListViewItem ) theEvent . mSender ;
if ( anItem . mColumnIdx ! = 0 )
anItem = anItem . GetSubItem ( 0 ) ;
if ( theEvent . mBtn = = 1 )
{
Widget widget = ( DarkListViewItem ) theEvent . mSender ;
float clickX = theEvent . mX ;
float clickY = widget . mHeight + GS ! ( 2 ) ;
float aX , aY ;
widget . SelfToOtherTranslate ( mListView . GetRoot ( ) , clickX , clickY , out aX , out aY ) ;
ShowRightClickMenu ( mListView , aX , aY ) ;
}
else
{
//if (anItem.IsParent)
//anItem.Selected = false;
}
}
void ListViewClicked ( MouseEvent theEvent )
{
if ( theEvent . mBtn = = 1 )
{
float aX , aY ;
theEvent . GetRootCoords ( out aX , out aY ) ;
ShowRightClickMenu ( mListView , aX , aY ) ;
}
}
void ListViewMouseDown ( MouseEvent theEvent )
{
// We clicked off all items, so deselect
mListView . GetRoot ( ) . WithSelectedItems ( scope ( item ) = > { item . Selected = false ; } ) ;
}
public override void Draw ( Graphics g )
{
base . Draw ( g ) ;
/ * using ( g . PushColor ( 0x80FF0000 ) )
g . FillRect ( 0 , 0 , mWidth , mHeight ) ; * /
}
public override void DrawAll ( Graphics g )
{
base . DrawAll ( g ) ;
}
public override void Update ( )
{
base . Update ( ) ;
if ( mSortDirty )
{
mSortDirty = false ;
Sort ( ) ;
}
if ( mWantsRehup )
{
mWantsRehup = false ;
mListView . GetRoot ( ) . WithItems ( scope ( item ) = >
{
let lvItem = ( ProjectListViewItem ) item ;
if ( lvItem . mWantsRehup )
{
lvItem . mWantsRehup = false ;
if ( ( mListViewToProjectMap . TryGetValue ( lvItem , var projectItem ) ) & &
( let projectFolder = projectItem as ProjectFolder ) )
{
RehupFolder ( projectFolder ) ;
}
}
} ) ;
}
if ( mRefreshVisibleViewsDeferred )
{
mRefreshVisibleViewsDeferred = false ;
IDEApp . sApp . RefreshVisibleViews ( ) ;
}
if ( mImportFileDeferred )
{
mImportFileDeferred = false ;
ImportFile ( ( ProjectFolder ) mListViewToProjectMap [ mSelectedParentItem ] ) ;
}
if ( mImportFolderDeferred )
{
mImportFolderDeferred = false ;
ImportFolder ( ( ProjectFolder ) mListViewToProjectMap [ mSelectedParentItem ] ) ;
}
if ( mImportProjectDeferred )
{
mImportProjectDeferred = false ;
ImportProject ( ) ;
}
if ( mImportInstalledDeferred )
{
mImportInstalledDeferred = false ;
ImportInstalledProject ( ) ;
}
}
public override void Resize ( float x , float y , float width , float height )
{
base . Resize ( x , y , width , height ) ;
mListView . Resize ( 0 , 0 , mWidth , mHeight ) ;
}
public override void MouseDown ( float x , float y , int32 btn , int32 btnCount )
{
base . MouseDown ( x , y , btn , btnCount ) ;
}
}
}