mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-08 20:30:47 +00:00
Initial layout of Edit Data Operand dialog
This commit is contained in:
parent
d2fe11e82c
commit
300b2a4bca
@ -1451,16 +1451,23 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
public bool CanEditOperand() {
|
||||
if (SelectionAnalysis.mNumItemsSelected != 1) {
|
||||
if (SelectionAnalysis.mNumItemsSelected == 0) {
|
||||
return false;
|
||||
}
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
int selOffset = CodeLineList[selIndex].FileOffset;
|
||||
} else if (SelectionAnalysis.mNumItemsSelected == 1) {
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
int selOffset = CodeLineList[selIndex].FileOffset;
|
||||
|
||||
bool editInstr = (CodeLineList[selIndex].LineType == LineListGen.Line.Type.Code &&
|
||||
mProject.GetAnattrib(selOffset).IsInstructionWithOperand);
|
||||
bool editData = (CodeLineList[selIndex].LineType == LineListGen.Line.Type.Data);
|
||||
return editInstr || editData;
|
||||
bool editInstr = (CodeLineList[selIndex].LineType == LineListGen.Line.Type.Code &&
|
||||
mProject.GetAnattrib(selOffset).IsInstructionWithOperand);
|
||||
bool editData = (CodeLineList[selIndex].LineType == LineListGen.Line.Type.Data);
|
||||
return editInstr || editData;
|
||||
} else {
|
||||
// Data operands are one of the few things we can edit in bulk. It's okay
|
||||
// if meta-data like ORGs and Notes are selected, but we don't allow it if
|
||||
// any code is selected.
|
||||
EntityCounts counts = SelectionAnalysis.mEntityCounts;
|
||||
return (counts.mDataLines > 0 && counts.mCodeLines == 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void EditOperand() {
|
||||
@ -1549,7 +1556,46 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
private void EditDataOperand(int offset) {
|
||||
// TODO
|
||||
Debug.Assert(mMainWin.CodeListView_GetSelectionCount() > 0);
|
||||
|
||||
TypedRangeSet trs = GroupedOffsetSetFromSelected();
|
||||
if (trs.Count == 0) {
|
||||
Debug.Assert(false, "EditDataOperand found nothing to edit"); // shouldn't happen
|
||||
return;
|
||||
}
|
||||
|
||||
// If the first offset has a FormatDescriptor, pass that in as a recommendation
|
||||
// for the default value in the dialog. This allows single-item editing to work
|
||||
// as expected. If the format can't be applied to the full selection (which
|
||||
// would disable that radio button), the dialog will have to pick something
|
||||
// that does work.
|
||||
//
|
||||
// We could pull this out of Anattribs, which would let the dialog reflect the
|
||||
// auto-format that the user was just looking at. However, I think it's better
|
||||
// if the dialog shows what's actually there, i.e. no formatting at all.
|
||||
IEnumerator<TypedRangeSet.Tuple> iter =
|
||||
(IEnumerator<TypedRangeSet.Tuple>)trs.GetEnumerator();
|
||||
iter.MoveNext();
|
||||
TypedRangeSet.Tuple firstOffset = iter.Current;
|
||||
mProject.OperandFormats.TryGetValue(firstOffset.Value, out FormatDescriptor dfd);
|
||||
|
||||
EditDataOperand dlg = new EditDataOperand(mMainWin, mProject.FileData,
|
||||
mProject.SymbolTable, mOutputFormatter, trs, dfd);
|
||||
dlg.ShowDialog();
|
||||
if (dlg.DialogResult == true) {
|
||||
// Merge the changes into the OperandFormats list. We need to remove all
|
||||
// FormatDescriptors that overlap the selected region. We don't need to
|
||||
// pass the selection set in, because the dlg.Results list spans the exact
|
||||
// set of ranges.
|
||||
//
|
||||
// If nothing actually changed, don't generate an undo record.
|
||||
ChangeSet cs = mProject.GenerateFormatMergeSet(dlg.Results);
|
||||
if (cs.Count != 0) {
|
||||
ApplyUndoableChanges(cs);
|
||||
} else {
|
||||
Debug.WriteLine("No change to data formats");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanEditStatusFlags() {
|
||||
@ -2174,6 +2220,92 @@ namespace SourceGenWPF {
|
||||
ApplyUndoableChanges(new ChangeSet(uc));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the ListView's 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.
|
||||
///
|
||||
/// Contiguous regions with user labels or address changes are split into
|
||||
/// independent regions by using a serial number for the range type. Same for
|
||||
/// long comments and notes.
|
||||
///
|
||||
/// We don't split based on existing data format items. That would make it impossible
|
||||
/// to convert from (say) a collection of single bytes to a collection of double bytes
|
||||
/// or a string. It should not be possible to select part of a formatted section,
|
||||
/// unless the user has been playing weird games with type hints to get overlapping
|
||||
/// format descriptors.
|
||||
/// </summary>
|
||||
/// <returns>TypedRangeSet with all offsets.</returns>
|
||||
private TypedRangeSet GroupedOffsetSetFromSelected() {
|
||||
TypedRangeSet rs = new TypedRangeSet();
|
||||
int groupNum = 0;
|
||||
int expectedAddr = -1;
|
||||
|
||||
DateTime startWhen = DateTime.Now;
|
||||
int prevOffset = -1;
|
||||
foreach (int index in mMainWin.CodeDisplayList.SelectedIndices) {
|
||||
// Don't add an offset to the set if the only part of it that is selected
|
||||
// is a directive or blank line. We only care about file offsets, so skip
|
||||
// anything that isn't code or data.
|
||||
if (!CodeLineList[index].IsCodeOrData) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int offset = CodeLineList[index].FileOffset;
|
||||
if (offset == prevOffset) {
|
||||
// This is a continuation of a multi-line item like a string. We've
|
||||
// already accounted for all bytes associated with this offset.
|
||||
continue;
|
||||
}
|
||||
Anattrib attr = mProject.GetAnattrib(offset);
|
||||
|
||||
if (expectedAddr == -1) {
|
||||
expectedAddr = attr.Address;
|
||||
}
|
||||
// Check for user labels.
|
||||
if (mProject.UserLabels.ContainsKey(offset)) {
|
||||
//if (mProject.GetAnattrib(offset).Symbol != null) {
|
||||
// We consider auto labels when splitting regions for the data analysis,
|
||||
// but I don't think we want to take them into account here. The specific
|
||||
// example that threw me was loading a 16-bit value from an address table.
|
||||
// The code does "LDA table,X / STA / LDA table+1,X / STA", which puts auto
|
||||
// labels at the first two addresses -- splitting the region. That's good
|
||||
// for the uncategorized data analyzer, but very annoying if you want to
|
||||
// slap a 16-bit numeric format on all entries in a table.
|
||||
groupNum++;
|
||||
} else if (mProject.HasCommentOrNote(offset)) {
|
||||
// Don't carry across a long comment or note.
|
||||
groupNum++;
|
||||
} else if (attr.Address != expectedAddr) {
|
||||
// For a contiguous selection, this should only happen if there's a .ORG
|
||||
// address change. For non-contiguous selection this is expected. In the
|
||||
// latter case, incrementing the group number is unnecessary but harmless.
|
||||
Debug.WriteLine("Address break: " + attr.Address + " vs. " + expectedAddr);
|
||||
//Debug.Assert(mProject.AddrMap.Get(offset) >= 0);
|
||||
|
||||
expectedAddr = attr.Address;
|
||||
groupNum++;
|
||||
}
|
||||
|
||||
// Mark every byte of an instruction or multi-byte data item --
|
||||
// everything that is represented by the line the user selected. Control
|
||||
// statements and blank lines aren't relevant here, as we only care about
|
||||
// file offsets.
|
||||
int len = CodeLineList[index].OffsetSpan; // attr.Length;
|
||||
Debug.Assert(len > 0);
|
||||
for (int i = offset; i < offset + len; i++) {
|
||||
rs.Add(i, groupNum);
|
||||
}
|
||||
// Advance the address.
|
||||
expectedAddr += len;
|
||||
|
||||
prevOffset = offset;
|
||||
}
|
||||
Debug.WriteLine("Offset selection conv took " +
|
||||
(DateTime.Now - startWhen).TotalMilliseconds + " ms");
|
||||
return rs;
|
||||
}
|
||||
|
||||
#endregion Main window UI event handlers
|
||||
|
||||
|
||||
|
@ -84,6 +84,9 @@
|
||||
<Compile Include="WpfGui\EditAppSettings.xaml.cs">
|
||||
<DependentUpon>EditAppSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WpfGui\EditDataOperand.xaml.cs">
|
||||
<DependentUpon>EditDataOperand.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WpfGui\EditDefSymbol.xaml.cs">
|
||||
<DependentUpon>EditDefSymbol.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -211,6 +214,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WpfGui\EditDataOperand.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WpfGui\EditDefSymbol.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
101
SourceGenWPF/WpfGui/EditDataOperand.xaml
Normal file
101
SourceGenWPF/WpfGui/EditDataOperand.xaml
Normal file
@ -0,0 +1,101 @@
|
||||
<!--
|
||||
Copyright 2019 faddenSoft
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<Window x:Class="SourceGenWPF.WpfGui.EditDataOperand"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:SourceGenWPF.WpfGui"
|
||||
mc:Ignorable="d"
|
||||
Title="Edit Data Operand"
|
||||
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
||||
Loaded="Window_Loaded"
|
||||
ContentRendered="Window_ContentRendered">
|
||||
|
||||
<Window.Resources>
|
||||
<system:String x:Key="str_SingleGroup">Select data format ({0} byte(s) selected):</system:String>
|
||||
<system:String x:Key="str_MultiGroup">Select data format ({0} bytes selected in {1} groups):</system:String>
|
||||
</Window.Resources>
|
||||
|
||||
<StackPanel Margin="8">
|
||||
<TextBlock Text="Select data format (TODO):"/>
|
||||
<RadioButton GroupName="Main" Content="_Default" Margin="0,4,0,0"/>
|
||||
|
||||
<TextBlock Text="Simple Data" Margin="0,12,0,0"/>
|
||||
<Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="2"/>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<RadioButton GroupName="Main" Content="Single _bytes" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="16-bit words, little-endian" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="16-bit words, big-endian" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="24-bit words, little-endian" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="32-bit words, little-endian" Margin="0,4,0,0"/>
|
||||
</StackPanel>
|
||||
<GroupBox Grid.Column="1" Header="Display As..." Margin="16,0,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<RadioButton GroupName="Display" Content="Hex" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Display" Content="Decimal" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Display" Content="Binary" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Display" Content="ASCII" Margin="0,4,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1">
|
||||
<RadioButton GroupName="Display" Content="_Address" Margin="12,4,0,0"/>
|
||||
<RadioButton GroupName="Display" Content="_Symbolic reference" Margin="12,4,0,0"/>
|
||||
<TextBox Name="symbolEntryTextBox" Margin="32,4,0,0"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="32,4,0,0">
|
||||
<RadioButton GroupName="Part" Content="Low"/>
|
||||
<RadioButton GroupName="Part" Content="High" Margin="8,0,0,0"/>
|
||||
<RadioButton GroupName="Part" Content="Bank" Margin="8,0,8,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="Bulk Data" Margin="0,12,0,0"/>
|
||||
<Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="2"/>
|
||||
<RadioButton GroupName="Main" Content="Densely-_packed bytes" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="_Fill with value" Margin="0,4,0,0"/>
|
||||
|
||||
<TextBlock Text="String" Margin="0,12,0,0"/>
|
||||
<Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="2"/>
|
||||
<RadioButton GroupName="Main" Content="Mixed ASCII (TODO)" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="Reversed ASCII (TODO)" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="Null-terminated strings (TODO)" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="Strings prefixed with 8-bit length (TODO)" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="String prefixed with 16-bit length (TODO)" Margin="0,4,0,0"/>
|
||||
<RadioButton GroupName="Main" Content="Dextral character inverted (TODO)" Margin="0,4,0,0"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0">
|
||||
<Button Name="okButton" Content="OK" IsDefault="True" Width="70"
|
||||
IsEnabled="{Binding IsValid}" Click="OkButton_Click"/>
|
||||
<Button Name="cancelButton" Content="Cancel" IsCancel="True"
|
||||
Width="70" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
1005
SourceGenWPF/WpfGui/EditDataOperand.xaml.cs
Normal file
1005
SourceGenWPF/WpfGui/EditDataOperand.xaml.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using Asm65;
|
||||
|
||||
namespace SourceGenWPF.WpfGui {
|
||||
@ -28,7 +29,7 @@ namespace SourceGenWPF.WpfGui {
|
||||
///
|
||||
/// This is a pretty direct port from WinForms.
|
||||
/// </summary>
|
||||
public partial class EditInstructionOperand : Window, INotifyPropertyChanged {
|
||||
public partial class EditInstructionOperand : Window {
|
||||
/// <summary>
|
||||
/// In/out. May be null on entry if the offset doesn't have a format descriptor
|
||||
/// specified. Will be null on exit if "default" is selected.
|
||||
@ -124,12 +125,6 @@ namespace SourceGenWPF.WpfGui {
|
||||
/// </summary>
|
||||
private bool mIsSymbolAuto;
|
||||
|
||||
// INotifyPropertyChanged implementation
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
|
||||
public EditInstructionOperand(Window owner, int offset, DisasmProject project,
|
||||
Asm65.Formatter formatter) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user