2019-08-23 11:56:54 -07:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Beefy;
|
|
|
|
using Beefy.events;
|
|
|
|
using Beefy.gfx;
|
|
|
|
using Beefy.theme.dark;
|
|
|
|
using Beefy.widgets;
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
namespace IDE.ui
|
|
|
|
{
|
|
|
|
class OpenFileInSolutionDialog : DarkDialog
|
|
|
|
{
|
|
|
|
class TimeEntry
|
|
|
|
{
|
|
|
|
public DateTime mLastWriteTime;
|
|
|
|
public DateTime mCheckedTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected class EntryListViewItem : DarkListViewItem
|
|
|
|
{
|
|
|
|
public override void Draw(Graphics g)
|
|
|
|
{
|
|
|
|
if ((mColumnIdx == 3) && (Label.IsEmpty))
|
|
|
|
{
|
|
|
|
var pathItem = GetSubItem(2);
|
|
|
|
DateTime lastWriteTime = GetLastWriteTime(pathItem.Label);
|
|
|
|
String label = scope String();
|
|
|
|
lastWriteTime.ToShortDateString(label);
|
|
|
|
label.Append(" ");
|
|
|
|
lastWriteTime.ToShortTimeString(label);
|
|
|
|
|
|
|
|
Label = label;
|
|
|
|
}
|
|
|
|
|
|
|
|
base.Draw(g);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected class EntryListView : DarkListView
|
|
|
|
{
|
|
|
|
protected override ListViewItem CreateListViewItem()
|
|
|
|
{
|
|
|
|
return new EntryListViewItem();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Dictionary<String, int32> sMRU = new .() ~
|
|
|
|
{
|
|
|
|
for (let key in _.Keys)
|
|
|
|
delete key;
|
|
|
|
delete _;
|
|
|
|
};
|
|
|
|
public static int32 sCurrentMRUIndex = 1;
|
2020-02-08 06:12:04 -08:00
|
|
|
static Dictionary<String, TimeEntry> sTimeCache = new .() ~ DeleteDictionaryAndKeysAndItems!(_);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
|
|
|
protected EntryListView mFileList;
|
|
|
|
EditWidget mEditWidget;
|
|
|
|
List<ProjectSource> mProjectSourceList = new .() ~ delete _;
|
|
|
|
public bool mFilterChanged;
|
|
|
|
public volatile bool mExitingThread;
|
|
|
|
public Thread mDateThread;
|
|
|
|
|
|
|
|
public this()
|
|
|
|
{
|
|
|
|
mWindowFlags = .ClientSized | .TopMost | .Caption | .Border | .SysMenu | .Resizable;
|
|
|
|
|
|
|
|
AddOkCancelButtons(new (evt) => { GotoFile(); }, null, 0, 1);
|
|
|
|
//mApplyButton = AddButton("Apply", (evt) => { evt.mCloseDialog = false; ApplyChanges(); });
|
|
|
|
|
|
|
|
Title = "Open File in Workspace";
|
|
|
|
|
|
|
|
mButtonBottomMargin = GS!(6);
|
|
|
|
mButtonRightMargin = GS!(6);
|
|
|
|
|
|
|
|
mFileList = new EntryListView();
|
|
|
|
mFileList.InitScrollbars(false, true);
|
|
|
|
mFileList.mAllowMultiSelect = false;
|
|
|
|
mFileList.mOnItemMouseDown.Add(new => ValueMouseDown);
|
|
|
|
|
|
|
|
ListViewColumn column = mFileList.AddColumn(GS!(200), "File");
|
|
|
|
column.mMinWidth = GS!(100);
|
|
|
|
column = mFileList.AddColumn(GS!(80), "Project");
|
|
|
|
column = mFileList.AddColumn(GS!(200), "Path");
|
|
|
|
column = mFileList.AddColumn(GS!(200), "Modified");
|
|
|
|
|
|
|
|
AddWidget(mFileList);
|
|
|
|
mTabWidgets.Add(mFileList);
|
|
|
|
|
|
|
|
mEditWidget = AddEdit("");
|
|
|
|
mEditWidget.mOnKeyDown.Add(new => EditKeyDownHandler);
|
|
|
|
mEditWidget.mOnContentChanged.Add(new (evt) => { mFilterChanged = true; });
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShutdownThread()
|
|
|
|
{
|
|
|
|
if (mDateThread != null)
|
|
|
|
{
|
|
|
|
mExitingThread = true;
|
|
|
|
mDateThread.Join();
|
|
|
|
mDateThread = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditKeyDownHandler(KeyDownEvent evt)
|
|
|
|
{
|
|
|
|
switch (evt.mKeyCode)
|
|
|
|
{
|
|
|
|
case .Up,
|
|
|
|
.Down,
|
|
|
|
.PageUp,
|
|
|
|
.PageDown:
|
|
|
|
mFileList.KeyDown(evt.mKeyCode, false);
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evt.mKeyFlags == .Ctrl)
|
|
|
|
{
|
|
|
|
switch (evt.mKeyCode)
|
|
|
|
{
|
|
|
|
case .Home,
|
|
|
|
.End:
|
|
|
|
mFileList.KeyDown(evt.mKeyCode, false);
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ValueMouseDown(ListViewItem clickedItem, float x, float y, int32 btnNum, int32 btnCount)
|
|
|
|
{
|
|
|
|
DarkListViewItem item = (DarkListViewItem)clickedItem.GetSubItem(0);
|
|
|
|
|
|
|
|
mFileList.GetRoot().SelectItemExclusively(item);
|
|
|
|
mFileList.SetFocus();
|
|
|
|
|
|
|
|
if ((btnNum == 0) && (btnCount > 1))
|
|
|
|
{
|
|
|
|
GotoFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilterFilesFolder(String filterString, ProjectFolder projectFolder)
|
|
|
|
{
|
|
|
|
for (var projectEntry in projectFolder.mChildItems)
|
|
|
|
{
|
|
|
|
var childFolder = projectEntry as ProjectFolder;
|
|
|
|
if (childFolder != null)
|
|
|
|
FilterFilesFolder(filterString, childFolder);
|
|
|
|
|
|
|
|
var projectSource = projectEntry as ProjectSource;
|
|
|
|
if (projectSource != null)
|
|
|
|
{
|
|
|
|
String fileName = scope String();
|
|
|
|
Path.GetFileName(projectSource.mPath, fileName);
|
|
|
|
if (filterString.Length > 0)
|
|
|
|
{
|
|
|
|
if (fileName.IndexOf(filterString, true) == -1)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
mProjectSourceList.Add(projectSource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int CompareFileNames(String pathA, String pathB)
|
|
|
|
{
|
|
|
|
int pathStartA = pathA.LastIndexOf(IDEUtils.cNativeSlash);
|
|
|
|
int pathStartB = pathB.LastIndexOf(IDEUtils.cNativeSlash);
|
|
|
|
|
|
|
|
int lenA = pathA.Length - pathStartA - 1;
|
|
|
|
int lenB = pathB.Length - pathStartB - 1;
|
|
|
|
|
|
|
|
//int result = String.CompareOrdinal(pathA, pathStartA + 1, pathB, pathStartB + 1, Math.Min(lenA, lenB));
|
|
|
|
int result = String.Compare(pathA, pathStartA + 1, pathB, pathStartB + 1, Math.Min(lenA, lenB), true);
|
|
|
|
|
|
|
|
/*if (result == 0)
|
|
|
|
result = lenA - lenB;*/
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static DateTime GetLastWriteTime(StringView path)
|
|
|
|
{
|
|
|
|
var fixedPath = scope String(path);
|
|
|
|
IDEUtils.MakeComparableFilePath(fixedPath);
|
|
|
|
bool added = sTimeCache.TryAdd(fixedPath, var keyPtr, var valuePtr);
|
|
|
|
if (added)
|
|
|
|
{
|
|
|
|
*keyPtr = new String(fixedPath);
|
|
|
|
|
|
|
|
TimeEntry te = new .();
|
|
|
|
te.mLastWriteTime = File.GetLastWriteTime(path);
|
|
|
|
te.mCheckedTime = DateTime.Now;
|
|
|
|
*valuePtr = te;
|
|
|
|
return te.mLastWriteTime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TimeEntry te = *valuePtr;
|
|
|
|
if ((DateTime.Now - te.mCheckedTime).TotalSeconds > 60)
|
|
|
|
{
|
|
|
|
te.mCheckedTime = DateTime.Now;
|
|
|
|
te.mLastWriteTime = File.GetLastWriteTime(path);
|
|
|
|
}
|
|
|
|
return te.mLastWriteTime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void ClearWriteTime(StringView path)
|
|
|
|
{
|
|
|
|
var fixedPath = scope String(path);
|
|
|
|
IDEUtils.MakeComparableFilePath(fixedPath);
|
|
|
|
if (sTimeCache.TryGetValue(fixedPath, var key, var value))
|
|
|
|
{
|
|
|
|
value.mCheckedTime = default;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilterFiles()
|
|
|
|
{
|
|
|
|
String filterString = scope String();
|
|
|
|
mEditWidget.GetText(filterString);
|
|
|
|
filterString.Trim();
|
|
|
|
|
|
|
|
mProjectSourceList.Clear();
|
|
|
|
var root = mFileList.GetRoot();
|
|
|
|
root.Clear();
|
|
|
|
|
|
|
|
for (var project in IDEApp.sApp.mWorkspace.mProjects)
|
|
|
|
{
|
|
|
|
FilterFilesFolder(filterString, project.mRootFolder);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*var selectedItem = null;// root.FindSelectedItem();
|
|
|
|
if ((selectedItem == null) && (root.GetChildCount() > 0))
|
|
|
|
{
|
|
|
|
selectedItem = root.GetChildAtIndex(0);
|
|
|
|
root.SelectItemExclusively(selectedItem);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
mProjectSourceList.Sort(scope (itemA, itemB) => CompareFileNames(itemA.mPath, itemB.mPath));
|
|
|
|
|
|
|
|
for (var projectSource in mProjectSourceList)
|
|
|
|
{
|
|
|
|
String fileName = scope String();
|
|
|
|
Path.GetFileName(projectSource.mPath, fileName);
|
|
|
|
|
|
|
|
var listViewItem = mFileList.GetRoot().CreateChildItem();
|
|
|
|
listViewItem.Label = fileName;
|
|
|
|
|
|
|
|
var subListViewItem = listViewItem.CreateSubItem(1);
|
|
|
|
subListViewItem.Label = projectSource.mProject.mProjectName;
|
|
|
|
|
|
|
|
String fullPath = scope String();
|
|
|
|
projectSource.GetFullImportPath(fullPath);
|
|
|
|
|
|
|
|
subListViewItem = listViewItem.CreateSubItem(2);
|
|
|
|
subListViewItem.Label = fullPath;
|
|
|
|
|
|
|
|
subListViewItem = listViewItem.CreateSubItem(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
ListViewItem bestItem = null;
|
|
|
|
int32 bestPri = -1;
|
|
|
|
for (int32 childIdx = 0; childIdx < root.GetChildCount(); childIdx++)
|
|
|
|
{
|
|
|
|
var listViewItem = root.GetChildAtIndex(childIdx);
|
|
|
|
var projectSource = mProjectSourceList[childIdx];
|
|
|
|
|
|
|
|
int32 pri;
|
|
|
|
sMRU.TryGetValue(projectSource.mPath, out pri);
|
|
|
|
if (pri > bestPri)
|
|
|
|
{
|
|
|
|
bestItem = listViewItem;
|
|
|
|
bestPri = pri;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bestItem != null)
|
|
|
|
{
|
|
|
|
mFileList.GetRoot().SelectItemExclusively(bestItem);
|
|
|
|
mFileList.EnsureItemVisible(bestItem, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*ShutdownThread();
|
|
|
|
mExitingThread = true;
|
|
|
|
mDateThread = new Thread(CheckFileDates);
|
|
|
|
mDateThread.Start();*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void GotoFile()
|
|
|
|
{
|
|
|
|
Close();
|
|
|
|
|
|
|
|
var root = mFileList.GetRoot();
|
|
|
|
var selectedListViewItem = root.FindFirstSelectedItem();
|
|
|
|
if (selectedListViewItem != null)
|
|
|
|
{
|
|
|
|
var itemIdx = root.mChildItems.IndexOf(selectedListViewItem);
|
|
|
|
var projectSource = mProjectSourceList[itemIdx];
|
|
|
|
gApp.RecordHistoryLocation(true);
|
|
|
|
gApp.ShowProjectItem(projectSource, false);
|
|
|
|
if (sMRU.TryAdd(projectSource.mPath, var keyPtr, var valuePtr))
|
|
|
|
{
|
|
|
|
*keyPtr = new String(projectSource.mPath);
|
|
|
|
*valuePtr = sCurrentMRUIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void AddedToParent()
|
|
|
|
{
|
|
|
|
base.AddedToParent();
|
|
|
|
mEditWidget.SetFocus();
|
|
|
|
|
|
|
|
FilterFiles();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void ResizeComponents()
|
|
|
|
{
|
|
|
|
base.ResizeComponents();
|
|
|
|
|
|
|
|
//var font = DarkTheme.sDarkTheme.mSmallFont;
|
|
|
|
|
|
|
|
float insetSize = GS!(6);
|
|
|
|
mFileList.Resize(insetSize, insetSize, mWidth - insetSize - insetSize, mHeight - GS!(66));
|
|
|
|
mEditWidget.Resize(insetSize, mFileList.mY + mFileList.mHeight + insetSize, mWidth - insetSize - insetSize, GS!(22));
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void CalcSize()
|
|
|
|
{
|
|
|
|
mWidth = GS!(660);
|
|
|
|
mHeight = GS!(512);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Resize(float x, float y, float width, float height)
|
|
|
|
{
|
|
|
|
base.Resize(x, y, width, height);
|
|
|
|
ResizeComponents();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Outline(Graphics g, Widget widget, int32 inflateX, int32 inflateY, uint32 color)
|
|
|
|
{
|
|
|
|
using (g.PushColor(color))
|
|
|
|
{
|
|
|
|
g.OutlineRect(widget.mX - inflateX, widget.mY - inflateY, widget.mWidth + inflateX * 2, widget.mHeight + inflateY * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void DrawAll(Graphics g)
|
|
|
|
{
|
|
|
|
base.DrawAll(g);
|
|
|
|
|
|
|
|
//Outline(g, mCategorySelector, 0, 0, 0xFF404040);
|
|
|
|
//Outline(g, mCategorySelector, -1, -1, 0xFF202020);
|
|
|
|
|
|
|
|
Outline(g, mFileList, 0, 0, IDEApp.cDialogOutlineLightColor);
|
|
|
|
Outline(g, mFileList, -1, -1, IDEApp.cDialogOutlineDarkColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckFileDates()
|
|
|
|
{
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Update()
|
|
|
|
{
|
|
|
|
base.Update();
|
|
|
|
|
|
|
|
if (mFilterChanged)
|
|
|
|
{
|
|
|
|
FilterFiles();
|
|
|
|
mFilterChanged = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|