mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-31 21:30:59 +00:00
Finish wiring up code hint commands
This commit is contained in:
parent
80ec6b6c78
commit
fa386a0d03
@ -23,12 +23,14 @@ using CommonUtil;
|
||||
|
||||
namespace SourceGenWPF {
|
||||
/// <summary>
|
||||
/// Tracks the items selected in the DisplayList.
|
||||
///
|
||||
/// Forward the SelectionChanged event. In WPF you can't get indices, only items, so we
|
||||
/// have to store the item index in the item itself.
|
||||
/// Tracks the items selected in the DisplayList, using forwarded SelectionChanged events.
|
||||
/// When enumerated, provides an ordered list of selected indices.
|
||||
/// </summary>
|
||||
public class DisplayListSelection {
|
||||
/// <remarks>
|
||||
/// In WPF you can't get indices, only items, so we have to store the item index in the
|
||||
/// item itself.
|
||||
/// </remarks>
|
||||
public class DisplayListSelection : IEnumerable<int> {
|
||||
private BitArray mSelection;
|
||||
|
||||
/// <summary>
|
||||
@ -49,26 +51,45 @@ namespace SourceGenWPF {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an empty list.
|
||||
/// </summary>
|
||||
public DisplayListSelection() {
|
||||
mSelection = new BitArray(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a list of the specified length.
|
||||
/// </summary>
|
||||
/// <param name="length">Number of elements.</param>
|
||||
public DisplayListSelection(int length) {
|
||||
mSelection = new BitArray(length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumeration of selected indices, in ascending order.
|
||||
/// </summary>
|
||||
public IEnumerator<int> GetEnumerator() {
|
||||
for (int i = 0; i < mSelection.Length; i++) {
|
||||
if (mSelection[i]) {
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the length of the selection array.
|
||||
///
|
||||
/// If the new length is longer, the new elements are initialized to false. If the
|
||||
/// new length is shorter, the excess elements are discarded. (This matches the behavior
|
||||
/// of a virtual ListView selection set.)
|
||||
/// new length is shorter, the excess elements are discarded.
|
||||
/// </summary>
|
||||
/// <param name="length">New length.</param>
|
||||
public void SetLength(int length) {
|
||||
//Debug.WriteLine("VirtualListViewSelection length now " + length);
|
||||
mSelection.Length = length;
|
||||
}
|
||||
//public void SetLength(int length) {
|
||||
// mSelection.Length = length;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Handles selection change.
|
||||
|
@ -388,13 +388,13 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the Formatter object. Clears the display list, instigating a full re-render.
|
||||
/// Changes the Formatter object. Clears the line list, instigating a full re-render.
|
||||
/// </summary>
|
||||
/// <param name="formatter">Formatter object.</param>
|
||||
public void SetFormatter(Formatter formatter) {
|
||||
mFormatter = formatter;
|
||||
mLineList.Clear();
|
||||
// TODO: update display list
|
||||
mDisplayList.Clear();
|
||||
|
||||
// We probably just changed settings, so update this as well.
|
||||
mShowCycleCounts = AppSettings.Global.GetBool(AppSettings.SRCGEN_SHOW_CYCLE_COUNTS,
|
||||
@ -402,14 +402,14 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the pseudo-op name object. Clears the display list, instigating a
|
||||
/// Changes the pseudo-op name object. Clears the line list, instigating a
|
||||
/// full re-render.
|
||||
/// </summary>
|
||||
/// <param name="opNames">Pseudo-op names.</param>
|
||||
public void SetPseudoOpNames(PseudoOp.PseudoOpNames opNames) {
|
||||
mPseudoOpNames = opNames;
|
||||
mLineList.Clear();
|
||||
// TODO: update display list
|
||||
mDisplayList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -654,7 +654,7 @@ namespace SourceGenWPF {
|
||||
// Out with the old, in with the new.
|
||||
mLineList.RemoveRange(startIndex, endIndex - startIndex + 1);
|
||||
mLineList.InsertRange(startIndex, newLines);
|
||||
// TODO: update display list
|
||||
Debug.Assert(false); // TODO: update display list
|
||||
|
||||
Debug.Assert(ValidateLineList(), "Display list failed validation");
|
||||
}
|
||||
@ -720,7 +720,7 @@ namespace SourceGenWPF {
|
||||
}
|
||||
Debug.WriteLine("Removing " + endIndex + " header lines");
|
||||
mLineList.RemoveRange(0, endIndex);
|
||||
// TODO: update display list
|
||||
Debug.Assert(false); // TODO: update display list
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -51,15 +51,6 @@ namespace SourceGenWPF {
|
||||
/// an empty symbol table.
|
||||
/// </summary>
|
||||
private SymbolTableSubset mSymbolSubset;
|
||||
|
||||
/// <summary>
|
||||
/// Current code list view selection. The length will match the DisplayList Count.
|
||||
///
|
||||
/// WinForms was bad -- a simple foreach through SelectedIndices on a 500K-line data set
|
||||
/// took about 2.5 seconds on a fast Win10 x64 machine. In WPF you get a list of
|
||||
/// selected objects, which is fine unless what you really want is the line number.
|
||||
/// </summary>
|
||||
private VirtualListViewSelection mCodeViewSelection = new VirtualListViewSelection();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@ -493,7 +484,7 @@ namespace SourceGenWPF {
|
||||
#endif
|
||||
int topOffset = CodeListGen[topItem].FileOffset;
|
||||
LineListGen.SavedSelection savedSel = LineListGen.SavedSelection.Generate(
|
||||
CodeListGen, null /*mCodeViewSelection*/, topOffset);
|
||||
CodeListGen, mMainWin.CodeDisplayList.SelectedIndices, topOffset);
|
||||
//savedSel.DebugDump();
|
||||
mReanalysisTimer.EndTask("Save selection");
|
||||
|
||||
@ -1051,18 +1042,19 @@ namespace SourceGenWPF {
|
||||
/// </summary>
|
||||
/// is selected.</param>
|
||||
public SelectionState UpdateSelectionState() {
|
||||
int firstIndex = mMainWin.GetFirstSelectedIndex();
|
||||
Debug.WriteLine("SelectionChanged, firstIndex=" + firstIndex);
|
||||
int selCount = mMainWin.GetSelectionCount();
|
||||
Debug.WriteLine("SelectionChanged, selCount=" + selCount);
|
||||
|
||||
SelectionState state = new SelectionState();
|
||||
|
||||
// Use IsSingleItemSelected(), rather than just checking sel.Count, because we
|
||||
// want the user to be able to e.g. EditData on a multi-line string even if all
|
||||
// lines in the string are selected.
|
||||
if (firstIndex == -1) {
|
||||
if (selCount < 0) {
|
||||
// nothing selected, leave everything set to false / 0
|
||||
state.mEntityCounts = new EntityCounts();
|
||||
} else if (IsSingleItemSelected()) {
|
||||
int firstIndex = mMainWin.GetFirstSelectedIndex();
|
||||
state.mNumSelected = 1;
|
||||
state.mEntityCounts = GatherEntityCounts(firstIndex);
|
||||
LineListGen.Line line = CodeListGen[firstIndex];
|
||||
@ -1148,7 +1140,8 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
// A single line can span multiple offsets, each of which could have a
|
||||
// different hint.
|
||||
// different hint. Note the code/data hints are only applied to the first
|
||||
// byte of each selected line, so we're not quite in sync with that.
|
||||
for (int offset = line.FileOffset; offset < line.FileOffset + line.OffsetSpan;
|
||||
offset++) {
|
||||
switch (mProject.TypeHints[offset]) {
|
||||
@ -1171,7 +1164,7 @@ namespace SourceGenWPF {
|
||||
}
|
||||
}
|
||||
|
||||
//Debug.WriteLine("GatherEntityCounts (len=" + mCodeViewSelection.Length + ") took " +
|
||||
//Debug.WriteLine("GatherEntityCounts (len=" + CodeListGen.Count + ") took " +
|
||||
// (DateTime.Now - startWhen).TotalMilliseconds + " ms");
|
||||
|
||||
return new EntityCounts() {
|
||||
@ -1214,6 +1207,80 @@ namespace SourceGenWPF {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void MarkAsType(CodeAnalysis.TypeHint hint, bool firstByteOnly) {
|
||||
RangeSet sel;
|
||||
|
||||
if (firstByteOnly) {
|
||||
sel = new RangeSet();
|
||||
foreach (int index in mMainWin.CodeDisplayList.SelectedIndices) {
|
||||
int offset = CodeListGen[index].FileOffset;
|
||||
if (offset >= 0) {
|
||||
// Not interested in the header stuff for hinting.
|
||||
sel.Add(offset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sel = OffsetSetFromSelected();
|
||||
}
|
||||
|
||||
TypedRangeSet newSet = new TypedRangeSet();
|
||||
TypedRangeSet undoSet = new TypedRangeSet();
|
||||
|
||||
foreach (int offset in sel) {
|
||||
if (offset < 0) {
|
||||
// header comment
|
||||
continue;
|
||||
}
|
||||
CodeAnalysis.TypeHint oldType = mProject.TypeHints[offset];
|
||||
if (oldType == hint) {
|
||||
// no change, don't add to set
|
||||
continue;
|
||||
}
|
||||
undoSet.Add(offset, (int)oldType);
|
||||
newSet.Add(offset, (int)hint);
|
||||
}
|
||||
if (newSet.Count == 0) {
|
||||
Debug.WriteLine("No changes found (" + hint + ", " + sel.Count + " offsets)");
|
||||
return;
|
||||
}
|
||||
|
||||
UndoableChange uc = UndoableChange.CreateTypeHintChange(undoSet, newSet);
|
||||
ChangeSet cs = new ChangeSet(uc);
|
||||
|
||||
ApplyUndoableChanges(cs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the set of selected items into a set of offsets. If a line
|
||||
/// spans multiple offsets (e.g. a 3-byte instruction), offsets for every
|
||||
/// byte are included.
|
||||
///
|
||||
/// Boundaries such as labels and address changes are ignored.
|
||||
/// </summary>
|
||||
/// <returns>RangeSet with all offsets.</returns>
|
||||
private RangeSet OffsetSetFromSelected() {
|
||||
RangeSet rs = new RangeSet();
|
||||
|
||||
foreach (int index in mMainWin.CodeDisplayList.SelectedIndices) {
|
||||
int offset = CodeListGen[index].FileOffset;
|
||||
|
||||
// Mark every byte of an instruction or multi-byte data item --
|
||||
// everything that is represented by the line the user selected.
|
||||
int len;
|
||||
if (offset >= 0) {
|
||||
len = mProject.GetAnattrib(offset).Length;
|
||||
} else {
|
||||
// header area
|
||||
len = 1;
|
||||
}
|
||||
Debug.Assert(len > 0);
|
||||
for (int i = offset; i < offset + len; i++) {
|
||||
rs.Add(i);
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
#endregion Main window UI event handlers
|
||||
}
|
||||
}
|
||||
|
@ -210,6 +210,8 @@ namespace SourceGenWPF.ProjWin {
|
||||
}
|
||||
|
||||
private void CodeListView_SelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
//DateTime startWhen = DateTime.Now;
|
||||
|
||||
// Update the selected-item bitmap.
|
||||
CodeDisplayList.SelectedIndices.SelectionChanged(e);
|
||||
|
||||
@ -218,6 +220,9 @@ namespace SourceGenWPF.ProjWin {
|
||||
|
||||
Debug.Assert(CodeDisplayList.SelectedIndices.DebugValidateSelectionCount(
|
||||
codeListView.SelectedItems.Count));
|
||||
|
||||
//Debug.WriteLine("SelectionChanged took " +
|
||||
// (DateTime.Now - startWhen).TotalMilliseconds + " ms");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -341,18 +346,22 @@ namespace SourceGenWPF.ProjWin {
|
||||
|
||||
private void HintAsCodeEntryPoint_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
Debug.WriteLine("hint as code entry point");
|
||||
mMainCtrl.MarkAsType(CodeAnalysis.TypeHint.Code, true);
|
||||
}
|
||||
|
||||
private void HintAsDataStart_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
Debug.WriteLine("hint as data start");
|
||||
mMainCtrl.MarkAsType(CodeAnalysis.TypeHint.Data, true);
|
||||
}
|
||||
|
||||
private void HintAsInlineData_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
Debug.WriteLine("hint as inline data");
|
||||
mMainCtrl.MarkAsType(CodeAnalysis.TypeHint.InlineData, false);
|
||||
}
|
||||
|
||||
private void RemoveHints_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
Debug.WriteLine("remove hints");
|
||||
mMainCtrl.MarkAsType(CodeAnalysis.TypeHint.NoHint, false);
|
||||
}
|
||||
|
||||
private void SelectAllCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
|
Loading…
Reference in New Issue
Block a user