diff --git a/SourceGen/Symbol.cs b/SourceGen/Symbol.cs
index d5b785e..1723677 100644
--- a/SourceGen/Symbol.cs
+++ b/SourceGen/Symbol.cs
@@ -122,7 +122,6 @@ namespace SourceGen {
SourceTypeString = sts;
}
-
public override string ToString() {
return Label + "{" + SymbolSource + "," + SymbolType +
",val=$" + Value.ToString("x4") + "}";
diff --git a/SourceGenWPF/MainController.cs b/SourceGenWPF/MainController.cs
index 9a6067c..dca6e3b 100644
--- a/SourceGenWPF/MainController.cs
+++ b/SourceGenWPF/MainController.cs
@@ -401,16 +401,14 @@ namespace SourceGenWPF {
CodeListGen = new LineListGen(mProject, mMainWin.CodeDisplayList,
mOutputFormatter, mPseudoOpNames);
- // Prep the symbol table subset object. Replace the old one with a new one.
- //mSymbolSubset = new SymbolTableSubset(mProject.SymbolTable);
-
RefreshProject(UndoableChange.ReanalysisScope.CodeAndData);
- //ShowProject();
- //InvalidateControls(null);
+
+ // Populate the Symbols list.
+ PopulateSymbolsList();
+
mMainWin.ShowCodeListView = true;
mNavStack.Clear();
- // Want to do this after ShowProject() or we see a weird glitch.
UpdateRecentProjectList(mProjectPathName);
}
@@ -1388,6 +1386,21 @@ namespace SourceGenWPF {
#endregion References panel
+ #region Symbols panel
+
+ private void PopulateSymbolsList() {
+ mMainWin.SymbolsList.Clear();
+ foreach (Symbol sym in mProject.SymbolTable) {
+ MainWindow.SymbolsListItem sli = new MainWindow.SymbolsListItem(sym,
+ sym.SourceTypeString,
+ mOutputFormatter.FormatHexValue(sym.Value, 0),
+ sym.Label);
+ mMainWin.SymbolsList.Add(sli);
+ }
+ }
+
+ #endregion Symbols panel
+
#region Info panel
private void UpdateInfoPanel() {
diff --git a/SourceGenWPF/ProjWin/MainWindow.xaml b/SourceGenWPF/ProjWin/MainWindow.xaml
index 1f2aeb6..f648d81 100644
--- a/SourceGenWPF/ProjWin/MainWindow.xaml
+++ b/SourceGenWPF/ProjWin/MainWindow.xaml
@@ -69,6 +69,9 @@ limitations under the License.
Ctrl+Z
+
+
@@ -344,26 +347,38 @@ limitations under the License.
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/SourceGenWPF/ProjWin/MainWindow.xaml.cs b/SourceGenWPF/ProjWin/MainWindow.xaml.cs
index 2bdd068..79321c9 100644
--- a/SourceGenWPF/ProjWin/MainWindow.xaml.cs
+++ b/SourceGenWPF/ProjWin/MainWindow.xaml.cs
@@ -14,6 +14,7 @@
* limitations under the License.
*/
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
@@ -516,24 +517,6 @@ 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 {
@@ -557,5 +540,192 @@ namespace SourceGenWPF.ProjWin {
new ObservableCollection();
#endregion References panel
+
+
+ #region Notes panel
+ // TODO
+ #endregion Notes panel
+
+
+ #region Symbols panel
+
+ public class SymbolsListItem {
+ public Symbol Sym { get; private set; }
+ public string Type { get; private set; }
+ public string Value { get; private set; }
+ public string Name { get; private set; }
+
+ public SymbolsListItem(Symbol sym, string type, string value, string name) {
+ Sym = sym;
+
+ Type = type;
+ Value = value;
+ Name = name;
+ }
+
+ public override string ToString() {
+ return "[SymbolsListItem: type=" + Type + " value=" + Value + " name=" +
+ Name + "]";
+ }
+ }
+
+ public ObservableCollection SymbolsList { get; private set; } =
+ new ObservableCollection();
+
+ private void SymbolsList_Filter(object sender, FilterEventArgs e) {
+ SymbolsListItem sli = (SymbolsListItem)e.Item;
+ if (sli == null) {
+ return;
+ }
+ if ((symUserLabels.IsChecked != true && sli.Sym.SymbolSource == Symbol.Source.User) ||
+ (symProjectSymbols.IsChecked != true && sli.Sym.SymbolSource == Symbol.Source.Project) ||
+ (symPlatformSymbols.IsChecked != true && sli.Sym.SymbolSource == Symbol.Source.Platform) ||
+ (symAutoLabels.IsChecked != true && sli.Sym.SymbolSource == Symbol.Source.Auto) ||
+ (symConstants.IsChecked != true && sli.Sym.SymbolType == Symbol.Type.Constant) ||
+ (symAddresses.IsChecked != true && sli.Sym.SymbolType != Symbol.Type.Constant))
+ {
+ e.Accepted = false;
+ } else {
+ e.Accepted = true;
+ }
+ }
+
+ ///
+ /// Refreshes the symbols list when a filter option changes. Set this to be called
+ /// for Checked/Unchecked events on the filter option buttons.
+ ///
+ private void SymbolsListFilter_Changed(object sender, RoutedEventArgs e) {
+ // This delightfully obscure call causes the list to refresh. See
+ // https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-group-sort-and-filter-data-in-the-datagrid-control
+ CollectionViewSource.GetDefaultView(symbolsList.ItemsSource).Refresh();
+ }
+
+ ///
+ /// Handles a Sorting event. We want to do a secondary sort on Name when one of the
+ /// other columns is the primary sort key.
+ ///
+ private void SymbolsList_Sorting(object sender, DataGridSortingEventArgs e) {
+ DataGridColumn col = e.Column;
+
+ // Set the SortDirection to a specific value. If we don't do this, SortDirection
+ // remains un-set, and the column header doesn't show up/down arrows or change
+ // direction when clicked twice.
+ ListSortDirection direction = (col.SortDirection != ListSortDirection.Ascending) ?
+ ListSortDirection.Ascending : ListSortDirection.Descending;
+ col.SortDirection = direction;
+
+ bool isAscending = direction != ListSortDirection.Descending;
+
+ IComparer comparer;
+
+ switch (col.Header) {
+ case "Type":
+ comparer = new SymTabSortComparer(SymTabSortField.CombinedType, isAscending);
+ break;
+ case "Value":
+ comparer = new SymTabSortComparer(SymTabSortField.Value, isAscending);
+ break;
+ case "Name":
+ comparer = new SymTabSortComparer(SymTabSortField.Name, isAscending);
+ break;
+ default:
+ comparer = null;
+ Debug.Assert(false);
+ break;
+ }
+
+ ListCollectionView lcv =
+ (ListCollectionView)CollectionViewSource.GetDefaultView(symbolsList.ItemsSource);
+ lcv.CustomSort = comparer;
+ e.Handled = true;
+ }
+
+ // Symbol table sort comparison helper.
+ private enum SymTabSortField { CombinedType, Value, Name };
+ private class SymTabSortComparer : IComparer {
+ private SymTabSortField mSortField;
+ private bool mIsAscending;
+
+ public SymTabSortComparer(SymTabSortField prim, bool isAscending) {
+ mSortField = prim;
+ mIsAscending = isAscending;
+ }
+
+ // IComparer interface
+ public int Compare(object oa, object ob) {
+ Symbol a = ((SymbolsListItem)oa).Sym;
+ Symbol b = ((SymbolsListItem)ob).Sym;
+
+ // Label is always unique, so we use it as a secondary sort.
+ if (mSortField == SymTabSortField.CombinedType) {
+ if (mIsAscending) {
+ int cmp = string.Compare(a.SourceTypeString, b.SourceTypeString);
+ if (cmp == 0) {
+ cmp = string.Compare(a.Label, b.Label);
+ }
+ return cmp;
+ } else {
+ int cmp = string.Compare(a.SourceTypeString, b.SourceTypeString);
+ if (cmp == 0) {
+ // secondary sort is always ascending, so negate
+ cmp = -string.Compare(a.Label, b.Label);
+ }
+ return -cmp;
+ }
+ } else if (mSortField == SymTabSortField.Value) {
+ if (mIsAscending) {
+ int cmp;
+ if (a.Value < b.Value) {
+ cmp = -1;
+ } else if (a.Value > b.Value) {
+ cmp = 1;
+ } else {
+ cmp = string.Compare(a.Label, b.Label);
+ }
+ return cmp;
+ } else {
+ int cmp;
+ if (a.Value < b.Value) {
+ cmp = -1;
+ } else if (a.Value > b.Value) {
+ cmp = 1;
+ } else {
+ cmp = -string.Compare(a.Label, b.Label);
+ }
+ return -cmp;
+ }
+ } else if (mSortField == SymTabSortField.Name) {
+ if (mIsAscending) {
+ return string.Compare(a.Label, b.Label);
+ } else {
+ return -string.Compare(a.Label, b.Label);
+ }
+ } else {
+ Debug.Assert(false);
+ return 0;
+ }
+ }
+ }
+
+ #endregion Symbols panel
+
+
+ #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
}
}