1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00
Beef/IDE/src/ui/ProjectPanel.bf

2287 lines
74 KiB
Beef
Raw Normal View History

2019-08-23 11:56:54 -07:00
using System;
using System.Collections.Generic;
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;
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)
{
uint32 color = Color.White;
let projectPanel = ((ProjectListView)mListView).mProjectPanel;
ProjectItem projectItem;
projectPanel.mListViewToProjectMap.TryGetValue(this, out projectItem);
if ((projectItem != null) && (projectItem.mParentFolder != null))
{
if (projectItem.mIncludeKind == .Manual)
color = 0xFFE0E0FF;
else if (projectItem.mIncludeKind == .Ignore)
color = 0xFF909090;
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);
/*mListView.mOnDragEnd.Add(new => HandleDragEnd);
mListView.mOnDragUpdate.Add(new => HandleDragUpdate);*/
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)
{
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;
if (source.mListView == target.mListView)
{
ProjectItem sourceProjectItem = mListViewToProjectMap[source];
ProjectItem targetProjectItem = mListViewToProjectMap[target];
if (((sourceProjectItem.mParentFolder == null) || (targetProjectItem.mParentFolder == null)) ||
(sourceProjectItem.mProject != targetProjectItem.mProject))
theEvent.mDragAllowed = false;
}
}
void HandleDragEnd(DragEvent theEvent)
{
if (!theEvent.mDragAllowed)
return;
if (theEvent.mDragTarget is DarkListViewItem)
{
DarkListViewItem source = (DarkListViewItem)theEvent.mSender;
DarkListViewItem target = (DarkListViewItem)theEvent.mDragTarget;
if (source.mListView == target.mListView)
{
ProjectItem targetProjectItem = mListViewToProjectMap[target];
ProjectItem sourceProjectItem = mListViewToProjectMap[source];
if ((targetProjectItem == null) || (sourceProjectItem == null))
return;
if (source == target)
return;
source.mParentItem.RemoveChildItem(source);
sourceProjectItem.mParentFolder.RemoveChild(sourceProjectItem);
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);
}
}
}
}
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;
listViewItem.mFocusColor = 0xFFA0A0A0;
listViewItem.mSelectColor = 0xFFA0A0A0;
}
void UpdateColors()
{
}
public ProjectListViewItem AddProjectItem(ProjectItem projectItem, ProjectListViewItem existingListViewItem = null)
{
var projectSource = projectItem as ProjectSource;
ProjectListViewItem listViewItem = null;
if ((projectSource != null) && (gApp.IsProjectSourceEnabled(projectSource)))
{
var resolveCompiler = gApp.GetProjectCompilerForFile(projectSource.mName);
if (resolveCompiler != null)
{
resolveCompiler.QueueProjectSource(projectSource);
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,
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);
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;
}
let ext = scope String();
Path.GetExtension(fileName, ext);
let projectSource = new ProjectSource();
projectSource.mProject = projectFolder.mProject;
projectSource.mName.Set(fileName);
projectSource.mPath = new String();
projectSource.mPath.Append(projectFolder.mPath);
projectSource.mPath.Append("/");
projectSource.mPath.Append(fileName);
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);
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;
projectFolder.AddChild(childProjectFolder);
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-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];
DoDeleteItem(listItem, null, true);
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();
projectFolder.mName.Set("New Folder");
projectFolder.mProject = folder.mProject;
projectFolder.mPath = new String();
if (folder.mParentFolder == null)
projectFolder.mPath.Append("src/", projectFolder.mName);
else
projectFolder.mPath.Append(folder.mPath, "/", projectFolder.mName);
projectFolder.mIncludeKind = folder.mIncludeKind;
projectFolder.mAutoInclude = folder.IsAutoInclude();
folder.AddChild(projectFolder);
AddProjectItem(projectFolder);
if (projectFolder.mIncludeKind != .Auto)
projectFolder.mProject.SetChanged();
}
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");
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;
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();
folder.GetRelDir(namespaceName); namespaceName.Replace('/', '.'); namespaceName.Replace('\\', '.');
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);
AddProjectItem(projectSource);
Sort();
if (folder.mIncludeKind != .Auto)
folder.mProject.SetChanged();
gApp.ShowProjectItem(projectSource);
}
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;
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);
}
});
}
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);*/
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;
gApp.GetActiveWindow().PreModalChild();
2019-08-23 11:56:54 -07:00
if (fileDialog.ShowDialog(gApp.GetActiveWindow()).GetValueOrDefault() == .OK)
{
if (mSelectedParentItem.mOpenButton != null)
mSelectedParentItem.mOpenButton.Open(true, false);
String dir = scope String(fileDialog.InitialDirectory);
List<String> alreadyHadFileList = scope List<String>();
defer(scope) ClearAndDeleteItems(alreadyHadFileList);
for (String fileNameIn in fileDialog.FileNames)
{
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, fileDialog.FileNames.Count);
folder.mProject.GetProjectRelPath(scope String(dir), dir);
//folder.mLastImportDir.Set(dir);
//folder.mProject.mLastImportDir.Set(dir);
Sort();
}
#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
//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;
}
public void SelectItem(ListViewItem item, bool checkKeyStates = false)
{
if (item.Focused)
{
// 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;
}
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);
}
void ProjectItemUnregister(ProjectItem projectItem)
{
var projectSource = projectItem as ProjectSource;
if (projectSource != null)
{
bool isProjectEnabled = gApp.IsProjectSourceEnabled(projectSource);
String fullPath = scope String();
projectSource.GetFullImportPath(fullPath);
gApp.mWorkspace.mForceNextCompile = true;
if ((IDEApp.IsBeefFile(fullPath)) && (isProjectEnabled))
{
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))
{
sourceViewPanel.DetachFromProjectItem();
}
});
if (isProjectEnabled)
{
gApp.mBfResolveHelper.ProjectSourceRemoved(projectSource);
gApp.mWorkspace.ProjectSourceRemoved(projectSource);
gApp.RefreshVisibleViews();
}
}
}
void ProjectItemRegister(Project projectItem)
{
}
public void DoDeleteItem(ListViewItem listItem, delegate bool(String path) deletePathFunc, bool forceRemove = false)
{
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;
if ((sourceViewPanel != null) && (sourceViewPanel.mProjectSource.mProject == project))
{
sourceViewPanel.DetachFromProjectItem();
}
});
RemoveProject(project);
return;
}
if (listItem.mChildItems != null)
{
for (int childIdx = listItem.mChildItems.Count - 1; childIdx >= 0; childIdx--)
DoDeleteItem(listItem.mChildItems[childIdx], deletePathFunc);
}
if (projectItem == null)
return;
ProjectItemUnregister(projectItem);
bool doReleaseRef = false;
bool didRemove = false;
if ((forceRemove) || (projectItem.mParentFolder == null) || (projectItem.mParentFolder.mIncludeKind == .Manual) || (projectItem.mIncludeKind == .Manual) || (deletePathFunc != null))
{
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
{
/*if (projectItem.mParentFolder.mIncludeKind == .Ignore)
projectItem.mIncludeKind = .Auto;
else
projectItem.mIncludeKind = .Ignore;*/
}
if ((didRemove) || (!mShowIgnored))
listItem.mParentItem.RemoveChildItem(listItem);
using (gApp.mMonitor.Enter())
projectItem.Dispose();
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)
{
DoDeleteItem(selectedItem, null);
}
else
{
DoDeleteItem(selectedItem, scope [&] (filePath) =>
{
if (File.Delete(filePath) case .Ok)
return true;
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++;
}
else if (selectedProjectItem is ProjectItem)
{
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");
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");
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);
}
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);
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);
}
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);
RenameItem(projectItem);
}
}
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;
}
2019-08-23 11:56:54 -07:00
bool failed = false;
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;
}
//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);
IDEApp.sApp.AddNewProjectToWorkspace(proj, verSpec);
IDEApp.sApp.mWorkspace.FixOptions();
InitProject(proj);
if (failed)
{
gApp.Fail(StackStringFormat!("Failed to load project: {0}", filePath));
return proj;
}
return proj;
}
void ImportProject()
{
#if !CLI
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 (*.*)|*.*");
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);
projectProperties.PopupWindow(gApp.GetActiveWindow());
2019-08-23 11:56:54 -07:00
}
public void ShowWorkspaceProperties()
{
var workspaceProperties = new WorkspaceProperties();
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);
listViewItem.mTextColor = (projectOptions != null) ? Color.White : 0xFFA0A0A0;
if (checkProject.mFailed)
listViewItem.mTextColor = 0xFFE04040;
}
}
void SetAsStartupProject(Project project)
{
IDEApp.sApp.mWorkspace.mStartupProject = project;
IDEApp.sApp.mWorkspace.SetChanged();
RehupProjects();
}
void AddNewProject()
{
var newProjectDialog = new NewProjectDialog();
newProjectDialog.Init();
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;
if (projectItem == null)
{
Menu anItem;
if (gApp.mWorkspace.IsInitialized)
{
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; });
anItem = menu.AddItem("Properties...");
anItem.mOnMenuItemSelected.Add(new (item) => { ShowWorkspaceProperties(); });
handled = true;
}
}
bool isProject = false;
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);
});
handled = true;
}
}
}
}
if ((projectItem != null) && (!handled))
{
Menu item = null;
if (isProject)
{
item = menu.AddItem("Set as Startup Project");
item.mOnMenuItemSelected.Add(new (item) =>
{
var projectItem = GetSelectedProjectItem();
if (projectItem != null)
SetAsStartupProject(projectItem.mProject);
});
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();
}
});
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);
});
item = menu.AddItem("Refresh");
item.mOnMenuItemSelected.Add(new (item) =>
{
var projectItem = GetSelectedProjectItem();
if (projectItem != null)
{
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);
}
}
});
menu.AddItem();
}
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);
DoDeleteItem(selectedItem, null);
if (projectItem != null)
{
//ProjectItemUnregister(projectItem);
projectItem.mIncludeKind = .Ignore;
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);
}
});
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];
DoDeleteItem(listViewItem, null, true);
}
}
}
}
});
}
}
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);
}
});
item = menu.AddItem("Open Containing Folder");
item.mOnMenuItemSelected.Add(new (item) =>
{
let projectItem = GetSelectedProjectItem();
String path = scope String();
if (let projectFolder = projectItem as ProjectFolder)
projectFolder.GetFullImportPath(path);
else
projectItem.mParentFolder.GetFullImportPath(path);
ProcessStartInfo psi = scope ProcessStartInfo();
psi.SetFileName(path);
psi.UseShellExecute = true;
psi.SetVerb("Open");
var process = scope SpawnedProcess();
process.Start(psi).IgnoreError();
});
menu.AddItem();
2019-08-23 11:56:54 -07:00
}
//menu.AddItem();
item = menu.AddItem("New Folder");
item.mOnMenuItemSelected.Add(new (item) =>
{
var projectFolder = GetSelectedProjectItem() as ProjectFolder;
if (projectFolder != null)
NewFolder(projectFolder);
});
item = menu.AddItem("New Class...");
item.mOnMenuItemSelected.Add(new (item) =>
{
var projectFolder = GetSelectedProjectItem() as ProjectFolder;
if (projectFolder != null)
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();
2019-08-23 11:56:54 -07:00
item = menu.AddItem("Properties...");
item.mOnMenuItemSelected.Add(new (item) =>
{
var projectItem = GetSelectedProjectItem();
if (projectItem != null)
ShowProjectProperties(projectItem.mProject);
});
}
}
/*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);
}
}
}