diff --git a/SourceGenWPF/DisplayList.cs b/SourceGenWPF/DisplayList.cs index 104e5ee..d6b5098 100644 --- a/SourceGenWPF/DisplayList.cs +++ b/SourceGenWPF/DisplayList.cs @@ -42,7 +42,7 @@ namespace SourceGenWPF { /// LineListGen object. /// /// NOTE: it may or may not be possible to implement this trivially with an - /// ObservedCollection. At an earlier iteration it wasn't, and I'd like to keep this + /// ObservableCollection. At an earlier iteration it wasn't, and I'd like to keep this /// around even if it is now possible, in case the pendulum swings back the other way. /// public class DisplayList : IList, IList, @@ -156,6 +156,9 @@ namespace SourceGenWPF { OnPropertyChanged(CountString); OnPropertyChanged(IndexerName); OnCollectionReset(); + + // Not strictly necessary, but does free up the memory sooner. + SelectedIndices = new DisplayListSelection(); } public bool Contains(FormattedParts item) { diff --git a/SourceGenWPF/MainController.cs b/SourceGenWPF/MainController.cs index 22050ab..5d2b920 100644 --- a/SourceGenWPF/MainController.cs +++ b/SourceGenWPF/MainController.cs @@ -992,13 +992,11 @@ namespace SourceGenWPF { mProjectPathName = null; #if false mSymbolSubset = new SymbolTableSubset(new SymbolTable()); - mCodeViewSelection = new VirtualListViewSelection(); - mDisplayList = null; - codeListView.VirtualListSize = 0; - //codeListView.Items.Clear(); - ShowNoProject(); - InvalidateControls(null); #endif + // Clear this to release the memory. + mMainWin.CodeDisplayList.Clear(); + + mMainWin.InfoPanelContents = String.Empty; mMainWin.ShowCodeListView = false; mGenerationLog = null; @@ -1017,6 +1015,7 @@ namespace SourceGenWPF { public void SelectionChanged(out SelectionState newState) { newState = UpdateSelectionState(); + UpdateReferencesPanel(); UpdateInfoPanel(); } @@ -1290,12 +1289,107 @@ namespace SourceGenWPF { #endregion Main window UI event handlers + #region References panel + + /// + /// Updates the "references" panel to reflect the current selection. + /// + /// The number of references to any given address should be relatively small, and + /// won't change without a data refresh, so recreating the list every time shouldn't + /// be a problem. + /// + private void UpdateReferencesPanel() { + mMainWin.ReferencesList.Clear(); + + if (mMainWin.GetSelectionCount() != 1) { + // Nothing selected, or multiple lines selected. + return; + } + int lineIndex = mMainWin.GetFirstSelectedIndex(); + LineListGen.Line.Type type = CodeListGen[lineIndex].LineType; + if (type != LineListGen.Line.Type.Code && + type != LineListGen.Line.Type.Data && + type != LineListGen.Line.Type.EquDirective) { + // Code, data, and platform symbol EQUs have xrefs. + return; + } + + // Find the appropriate xref set. + int offset = CodeListGen[lineIndex].FileOffset; + XrefSet xrefs; + if (offset < 0) { + int index = LineListGen.DefSymIndexFromOffset(offset); + DefSymbol defSym = mProject.ActiveDefSymbolList[index]; + xrefs = defSym.Xrefs; + } else { + xrefs = mProject.GetXrefSet(offset); + } + if (xrefs == null || xrefs.Count == 0) { + return; + } + + // TODO(someday): localization + Asm65.Formatter formatter = mOutputFormatter; + bool showBank = !mProject.CpuDef.HasAddr16; + for (int i = 0; i < xrefs.Count; i++) { + XrefSet.Xref xr = xrefs[i]; + + string typeStr; + switch (xr.Type) { + case XrefSet.XrefType.SubCallOp: + typeStr = "call "; + break; + case XrefSet.XrefType.BranchOp: + typeStr = "branch "; + break; + case XrefSet.XrefType.RefFromData: + typeStr = "data "; + break; + case XrefSet.XrefType.MemAccessOp: + switch (xr.AccType) { + case OpDef.MemoryEffect.Read: + typeStr = "read "; + break; + case OpDef.MemoryEffect.Write: + typeStr = "write "; + break; + case OpDef.MemoryEffect.ReadModifyWrite: + typeStr = "rmw "; + break; + case OpDef.MemoryEffect.None: // e.g. LDA # + FontFamily="{StaticResource GeneralMonoFont}" + SnapsToDevicePixels="True" + ItemsSource="{Binding ReferencesList}" + AutoGenerateColumns="False" + GridLinesVisibility="Vertical" VerticalGridLinesBrush="#FF7F7F7F"> @@ -314,7 +318,7 @@ limitations under the License. - diff --git a/SourceGenWPF/ProjWin/MainWindow.xaml.cs b/SourceGenWPF/ProjWin/MainWindow.xaml.cs index d922483..86108e3 100644 --- a/SourceGenWPF/ProjWin/MainWindow.xaml.cs +++ b/SourceGenWPF/ProjWin/MainWindow.xaml.cs @@ -15,6 +15,7 @@ */ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Linq; @@ -208,20 +209,6 @@ namespace SourceGenWPF.ProjWin { get { return mShowCodeListView ? Visibility.Visible : Visibility.Hidden; } } - /// - /// Text to display in the Info panel. This is a simple TextBox. - /// - public string InfoBoxContents { - get { - return mInfoBoxContents; - } - set { - mInfoBoxContents = value; - OnPropertyChanged(); - } - } - private string mInfoBoxContents; - private void CodeListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { //DateTime startWhen = DateTime.Now; @@ -408,5 +395,49 @@ namespace SourceGenWPF.ProjWin { } #endregion Command handlers + + + #region Info panel + + /// + /// Text to display in the Info panel. This is a simple TextBox. + /// + public string InfoPanelContents { + get { + return mInfoBoxContents; + } + set { + mInfoBoxContents = value; + OnPropertyChanged(); + } + } + private string mInfoBoxContents; + + #endregion Info panel + + #region References panel + + public class ReferencesListItem { + public string Offset { get; private set; } + public string Addr { get; private set; } + public string Type { get; private set; } + + public ReferencesListItem(string offset, string addr, string type) { + Offset = offset; + Addr = addr; + Type = type; + } + + public override string ToString() { + return "[ReferencesListItem: off=" + Offset + " addr=" + Addr + " type=" + + Type + "]"; + } + } + + public ObservableCollection ReferencesList { get; private set; } = + new ObservableCollection(); + + #endregion References panel + } }