From d3230ef0d66e884410116dd1bc1138111ff40e6f Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Sun, 16 Jun 2019 09:29:54 -0700 Subject: [PATCH] Add addr/label target highlight When you select a line that references a label within the file, we highlight the address and label fields of the target offset. --- SourceGenWPF/DisplayList.cs | 33 +++++++++++++++ SourceGenWPF/MainController.cs | 44 ++++++++++++++++++++ SourceGenWPF/ProjWin/CodeListItemStyle.xaml | 40 ++++++++++++++++++ SourceGenWPF/ProjWin/MainWindow.xaml | 4 +- SourceGenWPF/ProjWin/MainWindow.xaml.cs | 45 +++++++++++++++++++++ 5 files changed, 164 insertions(+), 2 deletions(-) diff --git a/SourceGenWPF/DisplayList.cs b/SourceGenWPF/DisplayList.cs index d6b5098..57d8fe8 100644 --- a/SourceGenWPF/DisplayList.cs +++ b/SourceGenWPF/DisplayList.cs @@ -285,6 +285,9 @@ namespace SourceGenWPF { SelectedIndices = new DisplayListSelection(size); } + /// + /// List elements. Instances are immutable. + /// public class FormattedParts { public string Offset { get; private set; } public string Addr { get; private set; } @@ -297,11 +300,29 @@ namespace SourceGenWPF { public string Comment { get; private set; } public bool IsLongComment { get; private set; } + // Set to true if we want to highlight the address and label fields. + public bool HasAddrLabelHighlight { get; private set; } + public int ListIndex { get; set; } = -1; // Private constructor -- create instances with factory methods. private FormattedParts() { } + /// + /// Clones the specified object. + /// + private static FormattedParts Clone(FormattedParts orig) { + FormattedParts newParts = FormattedParts.Create(orig.Offset, orig.Addr, + orig.Bytes, orig.Flags, orig.Attr, orig.Label, orig.Opcode, orig.Operand, + orig.Comment); + + newParts.IsLongComment = orig.IsLongComment; + newParts.HasAddrLabelHighlight = orig.HasAddrLabelHighlight; + + newParts.ListIndex = orig.ListIndex; + return newParts; + } + public static FormattedParts Create(string offset, string addr, string bytes, string flags, string attr, string label, string opcode, string operand, string comment) { @@ -348,6 +369,18 @@ namespace SourceGenWPF { parts.Comment = comment; return parts; } + + public static FormattedParts AddSelectionHighlight(FormattedParts orig) { + FormattedParts newParts = Clone(orig); + newParts.HasAddrLabelHighlight = true; + return newParts; + } + + public static FormattedParts RemoveSelectionHighlight(FormattedParts orig) { + FormattedParts newParts = Clone(orig); + newParts.HasAddrLabelHighlight = false; + return newParts; + } } } } diff --git a/SourceGenWPF/MainController.cs b/SourceGenWPF/MainController.cs index 33d8cb8..da13261 100644 --- a/SourceGenWPF/MainController.cs +++ b/SourceGenWPF/MainController.cs @@ -1057,6 +1057,7 @@ namespace SourceGenWPF { UpdateReferencesPanel(); UpdateInfoPanel(); + UpdateSelectionHighlight(); } /// @@ -1256,6 +1257,49 @@ namespace SourceGenWPF { return false; } + /// + /// Updates the selection highlight. When a code item with an operand offset is + /// selected, such as a branch, we want to highlight the address and label of the + /// target. + /// + private void UpdateSelectionHighlight() { + int targetIndex = FindSelectionHighlight(); + + if (mTargetHighlightIndex != targetIndex) { + mMainWin.CodeListView_RemoveSelectionHighlight(mTargetHighlightIndex); + mMainWin.CodeListView_AddSelectionHighlight(targetIndex); + + mTargetHighlightIndex = targetIndex; + Debug.WriteLine("Selection highlight now " + targetIndex); + } + } + + private int FindSelectionHighlight() { + if (mMainWin.CodeListView_GetSelectionCount() != 1) { + return -1; + } + int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex(); + LineListGen.Line line = CodeListGen[selIndex]; + if (!line.IsCodeOrData) { + return -1; + } + Debug.Assert(line.FileOffset >= 0); + + // Does this have an operand with an in-file target offset? + Anattrib attr = mProject.GetAnattrib(line.FileOffset); + if (attr.OperandOffset >= 0) { + return CodeListGen.FindCodeDataIndexByOffset(attr.OperandOffset); + } else if (attr.IsDataStart || attr.IsInlineDataStart) { + // If it's an Address or Symbol, we can try to resolve + // the value. + int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset); + if (operandOffset >= 0) { + return CodeListGen.FindCodeDataIndexByOffset(operandOffset); + } + } + return -1; + } + public bool CanUndo() { return (mProject != null && mProject.CanUndo); } diff --git a/SourceGenWPF/ProjWin/CodeListItemStyle.xaml b/SourceGenWPF/ProjWin/CodeListItemStyle.xaml index 0c46f88..1e6b32f 100644 --- a/SourceGenWPF/ProjWin/CodeListItemStyle.xaml +++ b/SourceGenWPF/ProjWin/CodeListItemStyle.xaml @@ -66,6 +66,7 @@ See also https://github.com/fadden/DisasmUiTest + @@ -139,10 +140,49 @@ See also https://github.com/fadden/DisasmUiTest wrong place you'll feel like you clicked and nothing happened. --> + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SourceGenWPF/ProjWin/MainWindow.xaml b/SourceGenWPF/ProjWin/MainWindow.xaml index 88b319f..60e9598 100644 --- a/SourceGenWPF/ProjWin/MainWindow.xaml +++ b/SourceGenWPF/ProjWin/MainWindow.xaml @@ -350,11 +350,11 @@ limitations under the License. - + - + diff --git a/SourceGenWPF/ProjWin/MainWindow.xaml.cs b/SourceGenWPF/ProjWin/MainWindow.xaml.cs index 81427fb..57348f1 100644 --- a/SourceGenWPF/ProjWin/MainWindow.xaml.cs +++ b/SourceGenWPF/ProjWin/MainWindow.xaml.cs @@ -413,11 +413,56 @@ namespace SourceGenWPF.ProjWin { codeListView.ScrollToTopItem(CodeDisplayList[index]); } + /// + /// Scrolls the code list to ensure that the specified index is visible. + /// + /// Line index of item. public void CodeListView_EnsureVisible(int index) { Debug.Assert(index >= 0 && index < CodeDisplayList.Count); codeListView.ScrollIntoView(CodeDisplayList[index]); } + /// + /// Adds an address/label selection highlight to the specified line. + /// + /// Line index. If < 0, method has no effect. + public void CodeListView_AddSelectionHighlight(int index) { + if (index < 0) { + return; + } + CodeListView_ReplaceEntry(index, + DisplayList.FormattedParts.AddSelectionHighlight(CodeDisplayList[index])); + } + + /// + /// Removes an address/label selection highlight from the specified line. + /// + /// Line index. If < 0, method has no effect. + public void CodeListView_RemoveSelectionHighlight(int index) { + if (index < 0) { + return; + } + CodeListView_ReplaceEntry(index, + DisplayList.FormattedParts.RemoveSelectionHighlight(CodeDisplayList[index])); + } + + /// + /// Replaces an entry in the code list. If the item was selected, the selection is + /// cleared and restored. + /// + /// List index. + /// Replacement parts. + private void CodeListView_ReplaceEntry(int index, DisplayList.FormattedParts newParts) { + bool isSelected = CodeDisplayList.SelectedIndices[index]; + if (isSelected) { + codeListView.SelectedItems.Remove(CodeDisplayList[index]); + } + CodeDisplayList[index] = newParts; + if (isSelected) { + codeListView.SelectedItems.Add(newParts); + } + } + #endregion Selection management #region Can-execute handlers