mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-10 18:31:20 +00:00
Initial layout of Edit Data Operand dialog
This commit is contained in:
parent
d2fe11e82c
commit
300b2a4bca
@ -1451,9 +1451,9 @@ namespace SourceGenWPF {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool CanEditOperand() {
|
public bool CanEditOperand() {
|
||||||
if (SelectionAnalysis.mNumItemsSelected != 1) {
|
if (SelectionAnalysis.mNumItemsSelected == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (SelectionAnalysis.mNumItemsSelected == 1) {
|
||||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||||
int selOffset = CodeLineList[selIndex].FileOffset;
|
int selOffset = CodeLineList[selIndex].FileOffset;
|
||||||
|
|
||||||
@ -1461,6 +1461,13 @@ namespace SourceGenWPF {
|
|||||||
mProject.GetAnattrib(selOffset).IsInstructionWithOperand);
|
mProject.GetAnattrib(selOffset).IsInstructionWithOperand);
|
||||||
bool editData = (CodeLineList[selIndex].LineType == LineListGen.Line.Type.Data);
|
bool editData = (CodeLineList[selIndex].LineType == LineListGen.Line.Type.Data);
|
||||||
return editInstr || editData;
|
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() {
|
public void EditOperand() {
|
||||||
@ -1549,7 +1556,46 @@ namespace SourceGenWPF {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void EditDataOperand(int offset) {
|
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() {
|
public bool CanEditStatusFlags() {
|
||||||
@ -2174,6 +2220,92 @@ namespace SourceGenWPF {
|
|||||||
ApplyUndoableChanges(new ChangeSet(uc));
|
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
|
#endregion Main window UI event handlers
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,6 +84,9 @@
|
|||||||
<Compile Include="WpfGui\EditAppSettings.xaml.cs">
|
<Compile Include="WpfGui\EditAppSettings.xaml.cs">
|
||||||
<DependentUpon>EditAppSettings.xaml</DependentUpon>
|
<DependentUpon>EditAppSettings.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="WpfGui\EditDataOperand.xaml.cs">
|
||||||
|
<DependentUpon>EditDataOperand.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="WpfGui\EditDefSymbol.xaml.cs">
|
<Compile Include="WpfGui\EditDefSymbol.xaml.cs">
|
||||||
<DependentUpon>EditDefSymbol.xaml</DependentUpon>
|
<DependentUpon>EditDefSymbol.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -211,6 +214,10 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="WpfGui\EditDataOperand.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="WpfGui\EditDefSymbol.xaml">
|
<Page Include="WpfGui\EditDefSymbol.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<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.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
using Asm65;
|
using Asm65;
|
||||||
|
|
||||||
namespace SourceGenWPF.WpfGui {
|
namespace SourceGenWPF.WpfGui {
|
||||||
@ -28,7 +29,7 @@ namespace SourceGenWPF.WpfGui {
|
|||||||
///
|
///
|
||||||
/// This is a pretty direct port from WinForms.
|
/// This is a pretty direct port from WinForms.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class EditInstructionOperand : Window, INotifyPropertyChanged {
|
public partial class EditInstructionOperand : Window {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// In/out. May be null on entry if the offset doesn't have a format descriptor
|
/// 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.
|
/// specified. Will be null on exit if "default" is selected.
|
||||||
@ -124,12 +125,6 @@ namespace SourceGenWPF.WpfGui {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool mIsSymbolAuto;
|
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,
|
public EditInstructionOperand(Window owner, int offset, DisasmProject project,
|
||||||
Asm65.Formatter formatter) {
|
Asm65.Formatter formatter) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user