1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-25 05:29:31 +00:00

Initial layout of Edit Data Operand dialog

This commit is contained in:
Andy McFadden 2019-07-08 17:02:25 -07:00
parent d2fe11e82c
commit 300b2a4bca
5 changed files with 1256 additions and 16 deletions

View File

@ -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

View File

@ -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>

View 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>

File diff suppressed because it is too large Load Diff

View File

@ -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) {