mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-28 01:29:29 +00:00
Add Navigate > Jump to Operand
If you double-click on the opcode of an instruction whose operand is an address or equate, the selection jumps to that address. This feature is now available in the Navigate menu, with the keyboard shortcut Ctrl+J. While testing the feature I noticed that the keyboard focus wasn't following the selection, so if you jumped to an address and then used the up/down arrows, you jumped back to the previous location. (This was true when double-clicking an opcode to jump; it was just less noticeable since the next action was likely mouse-based.) This has been fixed by updating the ListView item focus when we jump to a new location. See also issue #63 and issue #72.
This commit is contained in:
parent
3637bb964d
commit
bb830a29db
@ -1559,7 +1559,7 @@ namespace SourceGen {
|
||||
}
|
||||
break;
|
||||
case CodeListColumn.Opcode:
|
||||
HandleDoubleClickOnOpcode(line);
|
||||
JumpToOperandTarget(line, false);
|
||||
break;
|
||||
case CodeListColumn.Operand:
|
||||
if (CanEditOperand()) {
|
||||
@ -1581,11 +1581,17 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDoubleClickOnOpcode(LineListGen.Line line) {
|
||||
/// <summary>
|
||||
/// Jumps to the line referenced by the operand of the selected line.
|
||||
/// </summary>
|
||||
/// <param name="line">Selected line.</param>
|
||||
/// <param name="testOnly">If set, don't actually do the goto.</param>
|
||||
/// <returns>True if a jump is available for this line.</returns>
|
||||
private bool JumpToOperandTarget(LineListGen.Line line, bool testOnly) {
|
||||
if (line.FileOffset < 0) {
|
||||
// Double-click on project symbol EQUs and the file header comment are handled
|
||||
// elsewhere.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||
@ -1595,20 +1601,29 @@ namespace SourceGen {
|
||||
// (Resolve it as a numeric reference.)
|
||||
if (attr.OperandOffset >= 0) {
|
||||
// Yup, find the line for that offset and jump to it.
|
||||
GoToLocation(new NavStack.Location(attr.OperandOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
if (!testOnly) {
|
||||
GoToLocation(new NavStack.Location(attr.OperandOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
}
|
||||
return true;
|
||||
} else if (dfd != null && dfd.HasSymbol) {
|
||||
// Operand has a symbol, do a symbol lookup.
|
||||
if (dfd.SymbolRef.IsVariable) {
|
||||
GoToVarDefinition(line.FileOffset, dfd.SymbolRef, true);
|
||||
if (!testOnly) {
|
||||
GoToVarDefinition(line.FileOffset, dfd.SymbolRef, true);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (mProject.SymbolTable.TryGetValue(dfd.SymbolRef.Label, out Symbol sym)) {
|
||||
if (sym.SymbolSource == Symbol.Source.User ||
|
||||
sym.SymbolSource == Symbol.Source.Auto) {
|
||||
int labelOffset = mProject.FindLabelOffsetByName(dfd.SymbolRef.Label);
|
||||
if (labelOffset >= 0) {
|
||||
GoToLocation(new NavStack.Location(labelOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
if (!testOnly) {
|
||||
GoToLocation(new NavStack.Location(labelOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (sym.SymbolSource == Symbol.Source.Platform ||
|
||||
sym.SymbolSource == Symbol.Source.Project) {
|
||||
@ -1616,9 +1631,11 @@ namespace SourceGen {
|
||||
for (int i = 0; i < mProject.ActiveDefSymbolList.Count; i++) {
|
||||
if (mProject.ActiveDefSymbolList[i] == sym) {
|
||||
int offset = LineListGen.DefSymOffsetFromIndex(i);
|
||||
GoToLocation(new NavStack.Location(offset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
break;
|
||||
if (!testOnly) {
|
||||
GoToLocation(new NavStack.Location(offset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1635,10 +1652,15 @@ namespace SourceGen {
|
||||
// previous clause, but Address entries would not have been.)
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset);
|
||||
if (operandOffset >= 0) {
|
||||
GoToLocation(new NavStack.Location(operandOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
if (!testOnly) {
|
||||
GoToLocation(new NavStack.Location(operandOffset, 0, false),
|
||||
GoToMode.JumpToCodeData, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanDeleteMlc() {
|
||||
@ -2704,6 +2726,10 @@ namespace SourceGen {
|
||||
// Update the selection.
|
||||
mMainWin.CodeListView_SelectRange(topLineIndex, lastLineIndex - topLineIndex);
|
||||
|
||||
// Set the focus to the first selected item. The focus is used by the keyboard
|
||||
// handler to decide what the up/down arrows select next.
|
||||
mMainWin.CodeListView_SetSelectionFocus();
|
||||
|
||||
if (doPush) {
|
||||
// Update the back stack and associated controls.
|
||||
mNavStack.Push(prevLoc);
|
||||
@ -2783,6 +2809,27 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanJumpToOperand() {
|
||||
if (SelectionAnalysis.mNumItemsSelected != 1) {
|
||||
return false;
|
||||
}
|
||||
LineListGen.Line.Type lineType = SelectionAnalysis.mLineType;
|
||||
if (lineType != LineListGen.Line.Type.Code &&
|
||||
lineType != LineListGen.Line.Type.Data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
Debug.Assert(selIndex >= 0);
|
||||
return JumpToOperandTarget(CodeLineList[selIndex], true);
|
||||
}
|
||||
|
||||
public void JumpToOperand() {
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
Debug.Assert(selIndex >= 0);
|
||||
JumpToOperandTarget(CodeLineList[selIndex], false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the currently-selected location.
|
||||
/// </summary>
|
||||
|
@ -381,6 +381,10 @@ address, like "FEED", the label takes precedence. To jump to the address
|
||||
write "$FEED" instead. If you enter a non-unique label, the selection
|
||||
will jump to the nearest instance.</p>
|
||||
|
||||
<p>If an instruction or data line has an operand that references an address
|
||||
in the file, you can navigate to the operand's location with
|
||||
Navigate > Jump to Operand.</p>
|
||||
|
||||
<p>When you edit something, lines throughout the listing can change. This
|
||||
is different from a source code editor, where editing a line just changes
|
||||
that line. To allow you to watch the effects changes have, the undo/redo
|
||||
|
@ -20,6 +20,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Media;
|
||||
|
||||
using Asm65;
|
||||
using CommonUtil;
|
||||
using SourceGen.AsmGen;
|
||||
|
@ -143,6 +143,11 @@ limitations under the License.
|
||||
<RoutedUICommand x:Key="HintAsCodeEntryPointCmd" Text="Hint As Code Entry Point"/>
|
||||
<RoutedUICommand x:Key="HintAsDataStartCmd" Text="Hint As Data Start"/>
|
||||
<RoutedUICommand x:Key="HintAsInlineDataCmd" Text="Hint As Inline Data"/>
|
||||
<RoutedUICommand x:Key="JumpToOperandCmd" Text="Jump to Operand">
|
||||
<RoutedUICommand.InputGestures>
|
||||
<KeyGesture>Ctrl+J</KeyGesture>
|
||||
</RoutedUICommand.InputGestures>
|
||||
</RoutedUICommand>
|
||||
<RoutedUICommand x:Key="NavigateBackwardCmd" Text="Nav Backward">
|
||||
<RoutedUICommand.InputGestures>
|
||||
<KeyGesture>Alt+Left</KeyGesture>
|
||||
@ -274,6 +279,8 @@ limitations under the License.
|
||||
CanExecute="CanHintAsDataStart" Executed="HintAsDataStartCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource HintAsInlineDataCmd}"
|
||||
CanExecute="CanHintAsInlineData" Executed="HintAsInlineDataCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource JumpToOperandCmd}"
|
||||
CanExecute="CanJumpToOperand" Executed="JumpToOperandCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource NavigateBackwardCmd}"
|
||||
CanExecute="CanNavigateBackward" Executed="NavigateBackwardCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource NavigateForwardCmd}"
|
||||
@ -379,6 +386,7 @@ limitations under the License.
|
||||
<MenuItem Command="{StaticResource NavigateBackwardCmd}"/>
|
||||
<MenuItem Command="{StaticResource GotoCmd}"/>
|
||||
<MenuItem Command="{StaticResource GotoLastChangeCmd}"/>
|
||||
<MenuItem Command="{StaticResource JumpToOperandCmd}"/>
|
||||
<Separator/>
|
||||
<MenuItem Command="Find"/>
|
||||
<MenuItem Command="{StaticResource FindNextCmd}"/>
|
||||
|
@ -881,6 +881,10 @@ namespace SourceGen.WpfGui {
|
||||
mIsSplitterBeingDragged = false;
|
||||
}
|
||||
|
||||
public void CodeListView_SetSelectionFocus() {
|
||||
ItemContainerGenerator_StatusChanged(null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of the line that's currently at the top of the control.
|
||||
/// </summary>
|
||||
@ -1089,9 +1093,12 @@ namespace SourceGen.WpfGui {
|
||||
(counts.mCodeHints != 0 || counts.mDataHints != 0 || counts.mInlineDataHints != 0);
|
||||
}
|
||||
|
||||
private void CanJumpToOperand(object sender, CanExecuteRoutedEventArgs e) {
|
||||
e.CanExecute = IsProjectOpen() && mMainCtrl.CanJumpToOperand();
|
||||
}
|
||||
|
||||
private void CanSaveProject(object sender, CanExecuteRoutedEventArgs e) {
|
||||
e.CanExecute = mMainCtrl != null && mMainCtrl.IsProjectOpen &&
|
||||
!mMainCtrl.IsProjectReadOnly;
|
||||
e.CanExecute = IsProjectOpen() && !mMainCtrl.IsProjectReadOnly;
|
||||
}
|
||||
|
||||
private void CanToggleSingleByteFormat(object sender, CanExecuteRoutedEventArgs e) {
|
||||
@ -1258,6 +1265,10 @@ namespace SourceGen.WpfGui {
|
||||
mMainCtrl.MarkAsType(CodeAnalysis.TypeHint.InlineData, false);
|
||||
}
|
||||
|
||||
private void JumpToOperandCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.JumpToOperand();
|
||||
}
|
||||
|
||||
private void NavigateBackwardCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.NavigateBackward();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user