using System; using System.Collections; using System.Text; using System.Threading.Tasks; using Beefy; using Beefy.gfx; using Beefy.theme.dark; using Beefy.widgets; namespace IDE.ui { public class FindAndReplaceDialog : IDEDialog { EditWidget mEditWidget; EditWidget mReplaceWidget; DarkComboBox mLocationCombo; DarkComboBox mFileTypesCombo; bool mIsReplace; DarkCheckBox mRecurseDirCheckbox; DarkCheckBox mMatchCaseCheckbox; DarkCheckBox mMatchWholeWordCheckbox; bool mIgnoreContentChanged; DarkButton mAbortButton; public this(bool isReplace) { mSettingHistoryManager = gApp.mFindAndReplaceHistoryManager; mIsReplace = isReplace; mWindowFlags = BFWindow.Flags.ClientSized | BFWindow.Flags.TopMost | BFWindow.Flags.Caption | BFWindow.Flags.Border | BFWindow.Flags.SysMenu | BFWindow.Flags.Resizable | .PopupPosition; AddOkCancelButtons(new (evt) => { DoFind(); }, null, 0, 1); mButtonBottomMargin = GS!(6); mButtonRightMargin = GS!(6); mEditWidget = AddEdit(""); if (mIsReplace) { mReplaceWidget = AddEdit(""); } mLocationCombo = new PathComboBox(); mLocationCombo.MakeEditable(new PathEditWidget()); mLocationCombo.Label = isReplace ? FindResultsPanel.sCurrentDocument : FindResultsPanel.sEntireSolution; mLocationCombo.mPopulateMenuAction.Add(new => PopulateLocationMenu); mLocationCombo.mEditWidget.mOnContentChanged.Add(new (evt) => { UpdateUI(); }); AddWidget(mLocationCombo); AddEdit(mLocationCombo.mEditWidget); mFileTypesCombo = new DarkComboBox(); mFileTypesCombo.MakeEditable(); mFileTypesCombo.Label = "*"; mFileTypesCombo.mPopulateMenuAction.Add(new => PopulateFileTypesMenu); AddWidget(mFileTypesCombo); AddEdit(mFileTypesCombo.mEditWidget); mRecurseDirCheckbox = new DarkCheckBox(); mRecurseDirCheckbox.Label = "&Recurse directories"; mRecurseDirCheckbox.Checked = true; AddDialogComponent(mRecurseDirCheckbox); mMatchCaseCheckbox = new DarkCheckBox(); mMatchCaseCheckbox.Label = "Match &case"; AddDialogComponent(mMatchCaseCheckbox); mMatchWholeWordCheckbox = new DarkCheckBox(); mMatchWholeWordCheckbox.Label = "Match &whole case"; AddDialogComponent(mMatchWholeWordCheckbox); mAbortButton = new DarkButton(); mAbortButton.Label = "Abort Current"; mAbortButton.mOnMouseClick.Add(new (evt) => { gApp.mFindResultsPanel.CancelSearch(); }); AddDialogComponent(mAbortButton); mAbortButton.mVisible = false; CreatePrevNextButtons(); if (var editWidget = gApp.GetActiveWindow().mFocusWidget as EditWidget) { bool isMultiline = false; var content = editWidget.mEditWidgetContent; if (content.mSelection.HasValue) { int selStart = content.mSelection.Value.MinPos; int selEnd = content.mSelection.Value.MaxPos; for (int i = selStart; i < selEnd; i++) { if (content.mData.mText[i].mChar == '\n') { isMultiline = true; break; } } } if (!isMultiline) { var selText = scope String(); content.GetSelectionText(selText); mEditWidget.SetText(selText); mEditWidget.Content.SelectAll(); } } UpdateUI(); //mEditWidget.mKeyDownHandler += EditKeyDownHandler; //mEditWidget.mContentChangedHandler += (evt) => mFilterChanged = true; } protected override void UseProps(PropertyBag propBag) { mIgnoreContentChanged = true; mEditWidget.SetText(propBag.Get("Find") ?? ""); mEditWidget.mEditWidgetContent.SelectAll(); if (mReplaceWidget != null) mReplaceWidget.SetText(propBag.Get("Replace") ?? ""); mLocationCombo.Label = propBag.Get("Location", FindResultsPanel.sEntireSolution) ?? ""; mFileTypesCombo.Label = propBag.Get("FileTypes", "*") ?? ""; mRecurseDirCheckbox.Checked = propBag.Get("RecurseDir", true); mMatchCaseCheckbox.Checked = propBag.Get("MatchCase"); mMatchWholeWordCheckbox.Checked = propBag.Get("MatchWholeWord"); mIgnoreContentChanged = false; UpdateUI(); } void SaveProps() { PropertyBag propBag = new PropertyBag(); var str = scope String(); mEditWidget.GetText(str); propBag.Add("Find", str); if (mReplaceWidget != null) { str.Clear(); mReplaceWidget.GetText(str); propBag.Add("Replace", str); } propBag.Add("Location", mLocationCombo.Label); propBag.Add("FileTypes", mFileTypesCombo.Label); propBag.Add("RecurseDir", mRecurseDirCheckbox.Checked); propBag.Add("MatchCase", mMatchCaseCheckbox.Checked); propBag.Add("MatchWholeWord", mMatchWholeWordCheckbox.Checked); mSettingHistoryManager.Add(propBag); } void UpdateUI() { if (mIgnoreContentChanged) return; bool foundLocation = false; for (var str in FindResultsPanel.sLocationStrings) { if (str == mLocationCombo.Label) { foundLocation = true; break; } } mRecurseDirCheckbox.mDisabled = foundLocation; UpdateProgress(); } void UpdateProgress() { var title = scope String(); title.Append(mIsReplace ? "Find and Replace in Files" : "Find in Files"); bool isSearching = gApp.mFindResultsPanel.IsSearching; if (mAbortButton.mVisible != isSearching) { mAbortButton.mVisible = isSearching; mDefaultButton.mDisabled = isSearching; MarkDirty(); if (!isSearching) Title = title; } if ((isSearching) && (mUpdateCnt % 8 == 0)) { title.Append(" - Searching"); title.Append('.', (mUpdateCnt / 30) % 4); MarkDirty(); } Title = title; } void PopulateLocationMenu(Menu menu) { for (var str in FindResultsPanel.sLocationStrings) { var item = menu.AddItem(str); item.mOnMenuItemSelected.Add(new (dlg) => { mIgnoreContentChanged = true; mLocationCombo.Label = str; mIgnoreContentChanged = false; }); } } void PopulateFileTypesMenu(Menu menu) { var strings = scope List(); strings.Add("*"); strings.Add("*.bf"); for (var str in strings) { var item = menu.AddItem(str); item.mOnMenuItemSelected.Add(new (dlg) => { mFileTypesCombo.Label = str; }); } } void DoFind() { IDEApp.sApp.ShowFindResults(false); FindResultsPanel.SearchOptions searchOptions = new FindResultsPanel.SearchOptions(); searchOptions.mSearchString = new String(); mEditWidget.GetText(searchOptions.mSearchString); if (mReplaceWidget != null) { searchOptions.mReplaceString = new String(); mReplaceWidget.GetText(searchOptions.mReplaceString); } searchOptions.mSearchLocation = new String(mLocationCombo.Label); searchOptions.mFileTypes = new List(); var fileTypes = scope String(); mFileTypesCombo.GetLabel(fileTypes); for (var fileType in fileTypes.Split(';')) { let fileType = new String(fileType); fileType.Trim(); searchOptions.mFileTypes.Add(fileType); } searchOptions.mRecurseDirectories = mRecurseDirCheckbox.Checked; searchOptions.mMatchCase = mMatchCaseCheckbox.Checked; searchOptions.mMatchWholeWord = mMatchWholeWordCheckbox.Checked; gApp.mFindResultsPanel.Search(searchOptions); SaveProps(); } public override void ResizeComponents() { base.ResizeComponents(); float curY = GS!(30); mAbortButton.Resize(GS!(6), mDefaultButton.mY, mFont.GetWidth(mAbortButton.mLabel) + GS!(30), mDefaultButton.mHeight); mEditWidget.Resize(GS!(6), curY, mWidth - GS!(6) - GS!(6), GS!(22)); if (mReplaceWidget != null) { curY += GS!(42); mReplaceWidget.Resize(GS!(6), curY, mWidth - GS!(6) - GS!(6), GS!(22)); } curY += GS!(42); mLocationCombo.Resize(GS!(6), curY, mWidth - GS!(6) - GS!(6), GS!(22)); curY += GS!(42); mFileTypesCombo.Resize(GS!(6), curY, mWidth - GS!(6) - GS!(6), GS!(22)); curY += GS!(28); mRecurseDirCheckbox.Resize(GS!(6), curY, mRecurseDirCheckbox.CalcWidth(), GS!(22)); curY += GS!(22); mMatchCaseCheckbox.Resize(GS!(6), curY, mMatchCaseCheckbox.CalcWidth(), GS!(22)); curY += GS!(22); mMatchWholeWordCheckbox.Resize(GS!(6), curY, mMatchWholeWordCheckbox.CalcWidth(), GS!(22)); } public override void CalcSize() { mWidth = GS!(400); mHeight = GS!(mIsReplace ? 280 : 240); } public override void AddedToParent() { base.AddedToParent(); RehupMinSize(); } void RehupMinSize() { mWidgetWindow.SetMinimumSize(GS!(300), (.)GS!(mIsReplace ? 264 : 224), true); } public override void RehupScale(float oldScale, float newScale) { base.RehupScale(oldScale, newScale); RehupMinSize(); } public override void Resize(float x, float y, float width, float height) { base.Resize(x, y, width, height); ResizeComponents(); } public override void Draw(Graphics g) { base.Draw(g); g.DrawString("Find what:", 6, mEditWidget.mY - GS!(18)); if (mReplaceWidget != null) g.DrawString("Replace with:", GS!(6), mReplaceWidget.mY - GS!(18)); g.DrawString("Look in:", GS!(6), mLocationCombo.mY - GS!(18)); g.DrawString("Look at these file types:", GS!(6), mFileTypesCombo.mY - GS!(18)); } public override void Update() { base.Update(); UpdateProgress(); } } }