/// <summary> /// Applies the changes to the project, and updates the display. /// /// This is called by the undo/redo commands. Don't call this directly from the /// various UI-driven functions, as this does not add the change to the undo stack. /// </summary> /// <param name="cs">Set of changes to apply.</param> /// <param name="backward">If set, undo the changes instead.</param> private void ApplyChanges(ChangeSet cs, bool backward) { mReanalysisTimer.Clear(); mReanalysisTimer.StartTask("ProjectView.ApplyChanges()"); mReanalysisTimer.StartTask("Save selection"); #if false int topItem = codeListView.TopItem.Index; #else int topItem = 0; #endif int topOffset = mDisplayList[topItem].FileOffset; DisplayListGen.SavedSelection savedSel = DisplayListGen.SavedSelection.Generate( mDisplayList, mCodeViewSelection, topOffset); //savedSel.DebugDump(); mReanalysisTimer.EndTask("Save selection"); mReanalysisTimer.StartTask("Apply changes"); UndoableChange.ReanalysisScope needReanalysis = mProject.ApplyChanges(cs, backward, out RangeSet affectedOffsets); mReanalysisTimer.EndTask("Apply changes"); string refreshTaskStr = "Refresh w/reanalysis=" + needReanalysis; mReanalysisTimer.StartTask(refreshTaskStr); if (needReanalysis != UndoableChange.ReanalysisScope.None) { Debug.WriteLine("Refreshing project (" + needReanalysis + ")"); RefreshProject(needReanalysis); } else { Debug.WriteLine("Refreshing " + affectedOffsets.Count + " offsets"); RefreshCodeListViewEntries(affectedOffsets); mProject.Validate(); // shouldn't matter w/o reanalysis, but do it anyway } mReanalysisTimer.EndTask(refreshTaskStr); VirtualListViewSelection newSel = savedSel.Restore(mDisplayList, out int topIndex); //newSel.DebugDump(); // Refresh the various windows, and restore the selection. mReanalysisTimer.StartTask("Invalidate controls"); #if false InvalidateControls(newSel); #endif mReanalysisTimer.EndTask("Invalidate controls"); // This apparently has to be done after the EndUpdate, and inside try/catch. // See https://stackoverflow.com/questions/626315/ for notes. try { Debug.WriteLine("Setting TopItem to index=" + topIndex); #if false codeListView.TopItem = codeListView.Items[topIndex]; #endif } catch (NullReferenceException) { Debug.WriteLine("Caught an NRE from TopItem"); } mReanalysisTimer.EndTask("ProjectView.ApplyChanges()"); //mReanalysisTimer.DumpTimes("ProjectView timers:", mGenerationLog); #if false if (mShowAnalysisTimersDialog != null) { string timerStr = mReanalysisTimer.DumpToString("ProjectView timers:"); mShowAnalysisTimersDialog.BodyText = timerStr; } #endif // Lines may have moved around. Update the selection highlight. It's important // we do it here, and not down in DoRefreshProject(), because at that point the // ListView's selection index could be referencing a line off the end. #if false UpdateSelectionHighlight(); #endif }
/// <summary> /// Closes the project and associated modeless dialogs. Unsaved changes will be /// lost, so if the project has outstanding changes the user will be given the /// opportunity to cancel. /// </summary> /// <returns>True if the project was closed, false if the user chose to cancel.</returns> private bool DoClose() { Debug.WriteLine("ProjectView.DoClose() - dirty=" + (mProject == null ? "N/A" : mProject.IsDirty.ToString())); if (mProject != null && mProject.IsDirty) { DiscardChanges dlg = new DiscardChanges(); bool? ok = dlg.ShowDialog(); if (ok != true) { return(false); } else if (dlg.UserChoice == DiscardChanges.Choice.SaveAndContinue) { if (!DoSave()) { return(false); } } } #if false // Close modeless dialogs that depend on project. if (mShowUndoRedoHistoryDialog != null) { mShowUndoRedoHistoryDialog.Close(); } if (mShowAnalysisTimersDialog != null) { mShowAnalysisTimersDialog.Close(); } if (mShowAnalyzerOutputDialog != null) { mShowAnalyzerOutputDialog.Close(); } if (mHexDumpDialog != null) { mHexDumpDialog.Close(); } #endif // Discard all project state. if (mProject != null) { mProject.Cleanup(); mProject = null; } mDataPathName = null; mProjectPathName = null; #if false mSymbolSubset = new SymbolTableSubset(new SymbolTable()); mCodeViewSelection = new VirtualListViewSelection(); mDisplayList = null; codeListView.VirtualListSize = 0; //codeListView.Items.Clear(); ShowNoProject(); InvalidateControls(null); #endif mMainWin.ShowCodeListView = false; mGenerationLog = null; // Not necessary, but it lets us check the memory monitor to see if we got // rid of everything. GC.Collect(); return(true); }