using Beefy.theme.dark; using System; using System.IO; using System.Threading.Tasks; using System.Threading; using System.Collections.Generic; namespace IDE.ui { class PathEditWidget : ExpressionEditWidget { enum PathKind { Unknown, Folder, File } class DirectoryTask : Task { class Entry { public bool mIsDirectory; public String mFileName ~ delete _; } public PathEditWidget mPathEditWidget; public String mDirectoryPath = new .() ~ delete _; public List mEntries = new .() ~ DeleteContainerAndItems!(_); public this() { } protected override void InnerInvoke() { var searchStr = scope String(); searchStr.Append(mDirectoryPath); searchStr.Append("/*"); for (var dirEntry in Directory.Enumerate(searchStr, .Directories | .Files)) { var entry = new Entry(); entry.mIsDirectory = dirEntry.IsDirectory; entry.mFileName = new String(); dirEntry.GetFileName(entry.mFileName); mEntries.Add(entry); } if (!mDetachState.HasFlag(.Deatched)) mPathEditWidget.mAutocompleteDirty = true; } } DirectoryTask mDirectoryTask ~ { if (_ != null) _.Detach(); }; bool mAutocompleteDirty; public String mRelPath ~ delete _; PathKind mPathKind; DarkButton mBrowseButton; public this(PathKind pathKind = .Unknown) { mPathKind = pathKind; if (mPathKind != .Unknown) { mBrowseButton = new DarkButton(); mBrowseButton.Label = "..."; AddWidget(mBrowseButton); mBrowseButton.mOnMouseClick.Add(new (mouseArgs) => { if (mPathKind == .Folder) { String path = scope .(); GetText(path); #if !CLI FolderBrowserDialog folderDialog = scope .(); folderDialog.SelectedPath = path; mWidgetWindow.PreModalChild(); if (folderDialog.ShowDialog(gApp.GetActiveWindow()).GetValueOrDefault() == .OK) { SetText(scope String()..Append(folderDialog.SelectedPath)); } #endif } }); mEditWidgetContent.mTextInsets.mRight += GS!(20); } } public override void UpdateText(char32 keyChar, bool doAutoComplete) { if (!doAutoComplete) return; var editText = scope String(); GetText(editText); int cursorPos = mEditWidgetContent.CursorTextPos; int firstSlash = -1; int startSlash = -1; int nextSlash = -1; for (int i < editText.Length) { let c = editText[i]; if ((c == '\\') || (c == '/')) { if (firstSlash == -1) firstSlash = i; if (cursorPos >= i) { startSlash = i; } else { if (nextSlash == -1) nextSlash = i; } } } var editWidgetContent = (ExpressionEditWidgetContent)mEditWidgetContent; if ((firstSlash != -1) && (keyChar != '\'') && (keyChar != '/')) { String selStr = scope String(); if (nextSlash != -1) selStr.Append(editText, startSlash + 1, nextSlash - startSlash - 1); else selStr.Append(editText, startSlash + 1, Math.Max(cursorPos - startSlash - 1, 0)); String info = scope .(); info.Append("uncertain\n"); info.AppendF("insertRange\t{0} {1}\n", startSlash + 1, cursorPos); //info.Append("directory\thi\n"); //info.Append("directory\thi2\n"); String subRelPath = scope String(); if (startSlash != -1) subRelPath.Append(editText, 0, startSlash); var subAbsPath = scope String(); if (mRelPath != null) Path.GetAbsolutePath(subRelPath, mRelPath, subAbsPath); else Path.GetAbsolutePath(subRelPath, gApp.mInstallDir, subAbsPath); if ((mDirectoryTask == null) || (mDirectoryTask.mDirectoryPath != subAbsPath)) { if (mDirectoryTask != null) { mDirectoryTask.Detach(); mDirectoryTask = null; } if (editWidgetContent.mAutoComplete != null) editWidgetContent.mAutoComplete.Close(); mDirectoryTask = new DirectoryTask(); mDirectoryTask.mPathEditWidget = this; mDirectoryTask.mDirectoryPath.Set(subAbsPath); mDirectoryTask.Start(); return; } if (!mDirectoryTask.IsCompleted) { return; } for (var entry in mDirectoryTask.mEntries) { if (!entry.mFileName.StartsWith(selStr, .OrdinalIgnoreCase)) continue; if (entry.mIsDirectory) info.AppendF("folder\t{0}\n", entry.mFileName); else info.AppendF("file\t{0}\n", entry.mFileName); } var autoComplete = GetAutoComplete(); autoComplete.mUncertain = true; SetAutoCompleteInfo(info, 0); } else { if (mDirectoryTask != null) { mDirectoryTask.Detach(); mDirectoryTask = null; } if (editWidgetContent.mAutoComplete != null) editWidgetContent.mAutoComplete.Close(); } } public override void Update() { base.Update(); if (mAutocompleteDirty) { UpdateText(0, true); mAutocompleteDirty = false; } } public override void Resize(float x, float y, float width, float height) { base.Resize(x, y, width, height); let btnSize = (int)(height - GS!(4)); if (mBrowseButton != null) { mBrowseButton.Resize(mWidth - btnSize - GS!(2), GS!(2), btnSize, btnSize); } } } class PathComboBox : DarkComboBox { public override bool WantsKeyHandling() { if (mEditWidget == null) return true; var expressionEditWidget = (ExpressionEditWidgetContent)mEditWidget.mEditWidgetContent; return expressionEditWidget.mAutoComplete == null; } } }