1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-27 18:29:30 +00:00

Implement second project properties tab ("Project Symbols")

Implemented the symbol list, and the Edit Symbol dialog.
This commit is contained in:
Andy McFadden 2019-07-05 14:53:45 -07:00
parent a23b048cb4
commit 3cc4307484
9 changed files with 746 additions and 18 deletions

View File

@ -19,6 +19,8 @@ limitations under the License.
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:SourceGenWPF.Res">
<system:String x:Key="str_AbbrevAddress">Addr</system:String>
<system:String x:Key="str_AbbrevConstant">Const</system:String>
<system:String x:Key="str_AsmLatestVersion">[latest version]</system:String>
<system:String x:Key="str_AsmMatchFailure">output DOES NOT match data file</system:String>
<system:String x:Key="str_AsmMatchSuccess">output matches data file</system:String>
@ -97,4 +99,7 @@ limitations under the License.
<system:String x:Key="str_SaveBeforeAsmCaption">Save Project First</system:String>
<system:String x:Key="str_SetupSystemSummaryFmt">{1} CPU @ {2} MHz</system:String>
<system:String x:Key="str_ShowCol">Show</system:String>
<system:String x:Key="str_SymbolImportCaption">Symbol Import</system:String>
<system:String x:Key="str_SymbolImportGoodFmt">Imported {0} global symbols.</system:String>
<system:String x:Key="str_SymbolImportNone">No global+export symbols were found.</system:String>
</ResourceDictionary>

View File

@ -23,6 +23,10 @@ namespace SourceGenWPF.Res {
/// resources will cause the app to fail at launch.
/// </summary>
public static class Strings {
public static string ABBREV_ADDRESS =
(string)Application.Current.FindResource("str_AbbrevAddress");
public static string ABBREV_CONSTANT =
(string)Application.Current.FindResource("str_AbbrevConstant");
public static string ASM_LATEST_VERSION =
(string)Application.Current.FindResource("str_AsmLatestVersion");
public static string ASM_MATCH_FAILURE =
@ -179,5 +183,11 @@ namespace SourceGenWPF.Res {
(string)Application.Current.FindResource("str_SetupSystemSummaryFmt");
public static string SHOW_COL =
(string)Application.Current.FindResource("str_ShowCol");
public static string SYMBOL_IMPORT_CAPTION =
(string)Application.Current.FindResource("str_SymbolImportCaption");
public static string SYMBOL_IMPORT_GOOD_FMT =
(string)Application.Current.FindResource("str_SymbolImportGoodFmt");
public static string SYMBOL_IMPORT_NONE =
(string)Application.Current.FindResource("str_SymbolImportNone");
}
}

View File

@ -76,6 +76,9 @@
<Compile Include="WpfGui\EditAppSettings.xaml.cs">
<DependentUpon>EditAppSettings.xaml</DependentUpon>
</Compile>
<Compile Include="WpfGui\EditDefSymbol.xaml.cs">
<DependentUpon>EditDefSymbol.xaml</DependentUpon>
</Compile>
<Compile Include="WpfGui\EditProjectProperties.xaml.cs">
<DependentUpon>EditProjectProperties.xaml</DependentUpon>
</Compile>
@ -105,8 +108,8 @@
<Compile Include="WpfGui\NewProject.xaml.cs">
<DependentUpon>NewProject.xaml</DependentUpon>
</Compile>
<Compile Include="WpfGui\ProjectLoadIssue.xaml.cs">
<DependentUpon>ProjectLoadIssue.xaml</DependentUpon>
<Compile Include="WpfGui\ProjectLoadIssues.xaml.cs">
<DependentUpon>ProjectLoadIssues.xaml</DependentUpon>
</Compile>
<Compile Include="PseudoOp.cs" />
<Compile Include="Res\Strings.xaml.cs" />
@ -177,6 +180,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="WpfGui\EditDefSymbol.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="WpfGui\EditProjectProperties.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -221,7 +228,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="WpfGui\ProjectLoadIssue.xaml">
<Page Include="WpfGui\ProjectLoadIssues.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

View File

@ -0,0 +1,79 @@
<!--
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.EditDefSymbol"
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:local="clr-namespace:SourceGenWPF.WpfGui"
mc:Ignorable="d"
Title="Edit Symbol"
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
Loaded="Window_Loaded">
<Grid Margin="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="Label:"/>
<StackPanel Grid.Column="1" Grid.Row="0">
<TextBox Name="labelTextBox" Margin="0,1,0,0"
FontFamily="{StaticResource GeneralMonoFont}"
TextChanged="LabelTextBox_TextChanged"/>
<TextBlock Name="labelNotesLabel" Text="• 2+ alphanumerics, starting with letter" Margin="0,4,0,0"/>
<TextBlock Name="labelUniqueLabel" Text="• Unique among project symbols" Margin="0,4,0,16"/>
</StackPanel>
<TextBlock Grid.Column="0" Grid.Row="1" Text="Value:"/>
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBox Name="valueTextBox" Margin="0,1,0,0"
FontFamily="{StaticResource GeneralMonoFont}"
TextChanged="ValueTextBox_TextChanged"/>
<TextBlock Name="valueNotesLabel" Text="• Decimal, hex ($), or binary (%)" Margin="0,4,0,16"/>
</StackPanel>
<TextBlock Grid.Column="0" Grid.Row="2" Text="Comment:" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1" Grid.Row="2">
<TextBox Name="commentTextBox" Margin="0,1,0,0"
FontFamily="{StaticResource GeneralMonoFont}"/>
<TextBlock Text="• Optional" Margin="0,4,0,16"/>
</StackPanel>
<GroupBox Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" Header="Symbol Type" Padding="4">
<StackPanel Orientation="Horizontal">
<RadioButton Name="addressRadioButton" Content="Address"/>
<RadioButton Name="constantRadioButton" Content="Constant" Margin="24,0,0,0"/>
</StackPanel>
</GroupBox>
<StackPanel Grid.Column="1" Grid.Row="4" Margin="0,16,0,0"
Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="OK" Width="70" IsDefault="True" IsEnabled="{Binding IsValid}"
Click="OkButton_Click"/>
<Button Content="Cancel" Width="70" IsCancel="True" Margin="8,0,0,0"/>
</StackPanel>
</Grid>
</Window>

View File

@ -0,0 +1,164 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Asm65;
namespace SourceGenWPF.WpfGui {
/// <summary>
/// Symbol edit dialog.
/// </summary>
public partial class EditDefSymbol : Window, INotifyPropertyChanged {
/// <summary>
/// Set to previous value before calling; may be null if creating a new symbol.
/// Will be set to new value on OK result.
/// </summary>
public DefSymbol DefSym { get; set; }
/// <summary>
/// Set to true when all fields are valid. Controls whether the OK button is enabled.
/// </summary>
public bool IsValid {
get { return mIsValid; }
set {
mIsValid = value;
OnPropertyChanged();
}
}
private bool mIsValid;
/// <summary>
/// Format object to use when formatting addresses and constants.
/// </summary>
private Formatter mNumFormatter;
/// <summary>
/// List of existing symbols, for uniqueness check. The list will not be modified.
/// </summary>
private SortedList<string, DefSymbol> mDefSymbolList;
// Saved off at dialog load time.
private Brush mDefaultLabelColor;
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public EditDefSymbol(Window owner, Formatter formatter,
SortedList<string, DefSymbol> defList) {
InitializeComponent();
Owner = owner;
DataContext = this;
mNumFormatter = formatter;
mDefSymbolList = defList;
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
mDefaultLabelColor = labelNotesLabel.Foreground;
if (DefSym != null) {
labelTextBox.Text = DefSym.Label;
valueTextBox.Text = mNumFormatter.FormatValueInBase(DefSym.Value,
DefSym.DataDescriptor.NumBase);
commentTextBox.Text = DefSym.Comment;
if (DefSym.SymbolType == Symbol.Type.Constant) {
constantRadioButton.IsChecked = true;
} else {
addressRadioButton.IsChecked = true;
}
} else {
addressRadioButton.IsChecked = true;
}
labelTextBox.Focus();
UpdateControls();
}
private void UpdateControls() {
bool labelValid, labelUnique, valueValid;
// Label must be valid and not already exist in project symbol list. (It's okay
// if it exists elsewhere.)
labelValid = Asm65.Label.ValidateLabel(labelTextBox.Text);
if (mDefSymbolList.TryGetValue(labelTextBox.Text, out DefSymbol existing)) {
// It's okay if it's the same object.
labelUnique = (existing == DefSym);
} else {
labelUnique = true;
}
// Value must be blank, meaning "erase any earlier definition", or valid value.
// (Hmm... don't currently have a way to specify "no symbol" in DefSymbol.)
//if (!string.IsNullOrEmpty(valueTextBox.Text)) {
valueValid = ParseValue(out int unused1, out int unused2);
//} else {
// valueValid = true;
//}
// TODO(maybe): do this the XAML way, with properties and Styles
labelNotesLabel.Foreground = labelValid ? mDefaultLabelColor : Brushes.Red;
labelUniqueLabel.Foreground = labelUnique ? mDefaultLabelColor : Brushes.Red;
valueNotesLabel.Foreground = valueValid ? mDefaultLabelColor : Brushes.Red;
IsValid = labelValid && labelUnique && valueValid;
Debug.WriteLine("VALID IS " + IsValid);
}
private bool ParseValue(out int value, out int numBase) {
string str = valueTextBox.Text;
if (str.IndexOf('/') >= 0) {
// treat as address
numBase = 16;
return Asm65.Address.ParseAddress(str, (1 << 24) - 1, out value);
} else {
return Asm65.Number.TryParseInt(str, out value, out numBase);
}
}
private void OkButton_Click(object sender, RoutedEventArgs e) {
bool isConstant = (constantRadioButton.IsChecked == true);
ParseValue(out int value, out int numBase);
FormatDescriptor.SubType subType = FormatDescriptor.GetSubTypeForBase(numBase);
DefSym = new DefSymbol(labelTextBox.Text, value, Symbol.Source.Project,
isConstant ? Symbol.Type.Constant : Symbol.Type.ExternalAddr,
subType, commentTextBox.Text, string.Empty);
DialogResult = true;
}
private void LabelTextBox_TextChanged(object sender, TextChangedEventArgs e) {
UpdateControls();
}
private void ValueTextBox_TextChanged(object sender, TextChangedEventArgs e) {
UpdateControls();
}
}
}

View File

@ -120,8 +120,12 @@ limitations under the License.
<TextBlock Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"
Margin="4,0,0,0" Text="Symbols defined in project:"/>
<ListView Grid.Column="0" Grid.Row="1" Margin="4,4,4,0"
FontFamily="{StaticResource GeneralMonoFont}">
<ListView Name="projectSymbolsListView" Grid.Column="0" Grid.Row="1" Margin="4,4,4,0"
FontFamily="{StaticResource GeneralMonoFont}"
ItemsSource="{Binding ProjectSymbols}"
SnapsToDevicePixels="True" SelectionMode="Single"
SelectionChanged="ProjectSymbolsListView_SelectionChanged"
MouseDoubleClick="ProjectSymbolsListView_MouseDoubleClick">
<ListView.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
@ -129,22 +133,23 @@ limitations under the License.
</ListView.Resources>
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Name"/>
<GridViewColumn Header="Value"/>
<GridViewColumn Header="Type"/>
<GridViewColumn Header="Comment"/>
<GridViewColumn Header="Name" Width="118" DisplayMemberBinding="{Binding Label}"/>
<GridViewColumn Header="Value" Width="72" DisplayMemberBinding="{Binding Value}"/>
<GridViewColumn Header="Type" Width="45" DisplayMemberBinding="{Binding Type}"/>
<GridViewColumn Header="Comment" Width="300" DisplayMemberBinding="{Binding Comment}"/>
</GridView>
</ListView.View>
<ListView.Items>
<ListViewItem>abcdefg</ListViewItem>
</ListView.Items>
</ListView>
<StackPanel Grid.Column="1" Grid.Row="1">
<Button Name="newSymbolButton" Width="120" Margin="4" Content="_New Symbol..."/>
<Button Name="editSymbolButton" Width="120" Margin="4,4" Content="_Edit Symbol..."/>
<Button Name="removeSymbolButton" Width="120" Margin="4,4" Content="_Remove"/>
<Button Name="importSymbolsButton" Width="120" Margin="4,20,4,0" Content="_Import..."/>
<Button Name="newSymbolButton" Width="120" Margin="4" Content="_New Symbol..."
Click="NewSymbolButton_Click"/>
<Button Name="editSymbolButton" Width="120" Margin="4,4" Content="_Edit Symbol..."
Click="EditSymbolButton_Click"/>
<Button Name="removeSymbolButton" Width="120" Margin="4,4" Content="_Remove"
Click="RemoveSymbolButton_Click"/>
<Button Name="importSymbolsButton" Width="120" Margin="4,20,4,0" Content="_Import..."
Click="ImportSymbolsButton_Click"/>
</StackPanel>
</Grid>
</TabItem>

View File

@ -15,13 +15,20 @@
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Asm65;
using CommonUtil;
using CommonWPF;
using Microsoft.Win32;
namespace SourceGenWPF.WpfGui {
/// <summary>
@ -92,11 +99,9 @@ namespace SourceGenWPF.WpfGui {
private void Window_Loaded(object sender, RoutedEventArgs e) {
Loaded_General();
#if false
LoadProjectSymbols();
LoadPlatformSymbolFiles();
LoadExtensionScriptNames();
#endif
}
private void ApplyButton_Click(object sender, RoutedEventArgs e) {
@ -111,6 +116,23 @@ namespace SourceGenWPF.WpfGui {
// that nothing changed.
NewProps = new ProjectProperties(mWorkProps);
DialogResult = true;
GridView view = (GridView)projectSymbolsListView.View;
foreach (GridViewColumn header in view.Columns) {
Debug.WriteLine("WIDTH " + header.ActualWidth);
}
}
private void UpdateControls() {
//
// Project symbols tab
//
// Enable or disable the edit/remove buttons based on how many items are selected.
// (We're currently configured for single-select, so this is really just a != 0 test.)
int symSelCount = projectSymbolsListView.SelectedItems.Count;
removeSymbolButton.IsEnabled = (symSelCount == 1);
editSymbolButton.IsEnabled = (symSelCount == 1);
}
#region General
@ -289,5 +311,441 @@ namespace SourceGenWPF.WpfGui {
}
#endregion General
#region Project Symbols
// Item for the project symbol list view.
public class FormattedSymbol {
public string Label { get; private set; }
public string Value { get; private set; }
public string Type { get; private set; }
public string Comment { get; private set; }
public FormattedSymbol(string label, string value, string type, string comment) {
Label = label;
Value = value;
Type = type;
Comment = comment;
}
}
public ObservableCollection<FormattedSymbol> ProjectSymbols { get; private set; } =
new ObservableCollection<FormattedSymbol>();
/// <summary>
/// Prepares the project symbols ListView.
/// </summary>
private void LoadProjectSymbols() {
ProjectSymbols.Clear();
foreach (KeyValuePair<string, DefSymbol> kvp in mWorkProps.ProjectSyms) {
DefSymbol defSym = kvp.Value;
string typeStr;
if (defSym.SymbolType == Symbol.Type.Constant) {
typeStr = Res.Strings.ABBREV_CONSTANT;
} else {
typeStr = Res.Strings.ABBREV_ADDRESS;
}
FormattedSymbol fsym = new FormattedSymbol(
defSym.Label,
mFormatter.FormatValueInBase(defSym.Value, defSym.DataDescriptor.NumBase),
typeStr,
defSym.Comment);
ProjectSymbols.Add(fsym);
}
}
private void NewSymbolButton_Click(object sender, RoutedEventArgs e) {
EditDefSymbol dlg = new EditDefSymbol(this, mFormatter, mWorkProps.ProjectSyms);
dlg.ShowDialog();
if (dlg.DialogResult == true) {
Debug.WriteLine("ADD: " + dlg.DefSym);
mWorkProps.ProjectSyms[dlg.DefSym.Label] = dlg.DefSym;
IsDirty = true;
// Reload the contents. This loses the selection, but that shouldn't be an
// issue when adding new symbols. To do this incrementally we'd need to add
// the symbol at the correct sorted position.
LoadProjectSymbols();
UpdateControls();
}
}
private void EditSymbolButton_Click(object sender, EventArgs e) {
// Single-select list view, button dimmed when no selection.
Debug.Assert(projectSymbolsListView.SelectedItems.Count == 1);
FormattedSymbol item = (FormattedSymbol)projectSymbolsListView.SelectedItems[0];
DefSymbol defSym = mWorkProps.ProjectSyms[item.Label];
DoEditSymbol(defSym);
}
private void ProjectSymbolsListView_MouseDoubleClick(object sender,
MouseButtonEventArgs e) {
ListViewItem lvi = projectSymbolsListView.GetClickedItem(e);
if (lvi == null) {
return;
}
FormattedSymbol item = (FormattedSymbol)lvi.Content;
DefSymbol defSym = mWorkProps.ProjectSyms[item.Label];
DoEditSymbol(defSym);
}
private void DoEditSymbol(DefSymbol defSym) {
EditDefSymbol dlg = new EditDefSymbol(this, mFormatter, mWorkProps.ProjectSyms);
dlg.DefSym = defSym;
dlg.ShowDialog();
if (dlg.DialogResult == true) {
// Label might have changed, so remove old before adding new.
mWorkProps.ProjectSyms.Remove(defSym.Label);
mWorkProps.ProjectSyms[dlg.DefSym.Label] = dlg.DefSym;
IsDirty = true;
LoadProjectSymbols();
UpdateControls();
}
}
private void RemoveSymbolButton_Click(object sender, RoutedEventArgs e) {
// Single-select list view, button dimmed when no selection.
Debug.Assert(projectSymbolsListView.SelectedItems.Count == 1);
int selectionIndex = projectSymbolsListView.SelectedIndex;
FormattedSymbol item = (FormattedSymbol)projectSymbolsListView.SelectedItems[0];
DefSymbol defSym = mWorkProps.ProjectSyms[item.Label];
mWorkProps.ProjectSyms.Remove(defSym.Label);
IsDirty = true;
LoadProjectSymbols();
UpdateControls();
// Restore selection to the item that used to come after the one we just deleted,
// so you can hit "Remove" repeatedly to delete multiple items.
int newCount = projectSymbolsListView.Items.Count;
if (selectionIndex >= newCount) {
selectionIndex = newCount - 1;
}
if (selectionIndex >= 0) {
projectSymbolsListView.SelectedIndex = selectionIndex;
removeSymbolButton.Focus();
}
}
private void ImportSymbolsButton_Click(object sender, RoutedEventArgs e) {
OpenFileDialog fileDlg = new OpenFileDialog() {
Filter = ProjectFile.FILENAME_FILTER + "|" + Res.Strings.FILE_FILTER_ALL,
FilterIndex = 1
};
if (fileDlg.ShowDialog() != true) {
return;
}
string projPathName = Path.GetFullPath(fileDlg.FileName);
DisasmProject newProject = new DisasmProject();
if (!ProjectFile.DeserializeFromFile(projPathName, newProject,
out FileLoadReport report)) {
// Unable to open project file. Report error and bail.
ProjectLoadIssues dlg = new ProjectLoadIssues(this, report.Format(),
ProjectLoadIssues.Buttons.Cancel);
dlg.ShowDialog();
// ignore dlg.DialogResult
return;
}
// Import all user labels that were marked as "global export". These become
// external-address project symbols.
int foundCount = 0;
foreach (KeyValuePair<int, Symbol> kvp in newProject.UserLabels) {
if (kvp.Value.SymbolType == Symbol.Type.GlobalAddrExport) {
Symbol sym = kvp.Value;
DefSymbol defSym = new DefSymbol(sym.Label, sym.Value, Symbol.Source.Project,
Symbol.Type.ExternalAddr, FormatDescriptor.SubType.None,
string.Empty, string.Empty);
mWorkProps.ProjectSyms[defSym.Label] = defSym;
foundCount++;
}
}
if (foundCount != 0) {
IsDirty = true;
LoadProjectSymbols();
UpdateControls();
}
newProject.Cleanup();
// Tell the user we did something. Might be nice to tell them how many weren't
// already present.
string msg;
if (foundCount == 0) {
msg = Res.Strings.SYMBOL_IMPORT_NONE;
} else {
msg = string.Format(Res.Strings.SYMBOL_IMPORT_GOOD_FMT, foundCount);
}
MessageBox.Show(msg, Res.Strings.SYMBOL_IMPORT_CAPTION,
MessageBoxButton.OK, MessageBoxImage.Information);
}
#endregion Project Symbols
#region Platform symbol files
/// <summary>
/// Loads the platform symbol file names into the list control.
/// </summary>
private void LoadPlatformSymbolFiles() {
#if false
symbolFilesListBox.BeginUpdate();
symbolFilesListBox.Items.Clear();
foreach (string fileName in mWorkProps.PlatformSymbolFileIdentifiers) {
symbolFilesListBox.Items.Add(fileName);
}
symbolFilesListBox.EndUpdate();
#endif
}
private void ProjectSymbolsListView_SelectionChanged(object sender,
SelectionChangedEventArgs e) {
// Enable/disable buttons as the selection changes.
UpdateControls();
}
#if false
private void addSymbolFilesButton_Click(object sender, EventArgs e) {
OpenFileDialog fileDlg = new OpenFileDialog() {
Filter = PlatformSymbols.FILENAME_FILTER,
Multiselect = true,
InitialDirectory = RuntimeDataAccess.GetDirectory(),
RestoreDirectory = true // doesn't seem to work?
};
if (fileDlg.ShowDialog() != DialogResult.OK) {
return;
}
foreach (string pathName in fileDlg.FileNames) {
// I'm assuming the full names got the Path.GetFullPath() canonicalization and
// don't need further processing. Also, I'm assuming that all files live in
// the same directory, so if one is in an invalid location then they all are.
ExternalFile ef = ExternalFile.CreateFromPath(pathName, mProjectDir);
if (ef == null) {
// Files not found in runtime or project directory.
string projDir = mProjectDir;
if (string.IsNullOrEmpty(projDir)) {
projDir = Properties.Resources.UNSET;
}
string msg = string.Format(Properties.Resources.EXTERNAL_FILE_BAD_DIR,
RuntimeDataAccess.GetDirectory(), projDir, pathName);
MessageBox.Show(this, msg, Properties.Resources.EXTERNAL_FILE_BAD_DIR_CAPTION,
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string ident = ef.Identifier;
if (mWorkProps.PlatformSymbolFileIdentifiers.Contains(ident)) {
Debug.WriteLine("Already present: " + ident);
continue;
}
Debug.WriteLine("Adding symbol file: " + ident);
mWorkProps.PlatformSymbolFileIdentifiers.Add(ident);
mDirty = true;
}
if (mDirty) {
LoadPlatformSymbolFiles();
UpdateControls();
}
}
private void symbolFileUpButton_Click(object sender, EventArgs e) {
Debug.Assert(symbolFilesListBox.SelectedIndices.Count == 1);
int selIndex = symbolFilesListBox.SelectedIndices[0];
Debug.Assert(selIndex > 0);
MoveSingleItem(selIndex, symbolFilesListBox.SelectedItem, -1);
}
private void symbolFileDownButton_Click(object sender, EventArgs e) {
Debug.Assert(symbolFilesListBox.SelectedIndices.Count == 1);
int selIndex = symbolFilesListBox.SelectedIndices[0];
Debug.Assert(selIndex < symbolFilesListBox.Items.Count - 1);
MoveSingleItem(selIndex, symbolFilesListBox.SelectedItem, +1);
}
private void MoveSingleItem(int selIndex, object selectedItem, int adj) {
object selected = symbolFilesListBox.SelectedItem;
symbolFilesListBox.Items.Remove(selected);
symbolFilesListBox.Items.Insert(selIndex + adj, selected);
symbolFilesListBox.SetSelected(selIndex + adj, true);
// do the same operation in the file name list
string str = mWorkProps.PlatformSymbolFileIdentifiers[selIndex];
mWorkProps.PlatformSymbolFileIdentifiers.RemoveAt(selIndex);
mWorkProps.PlatformSymbolFileIdentifiers.Insert(selIndex + adj, str);
mDirty = true;
UpdateControls();
}
private void symbolFileRemoveButton_Click(object sender, EventArgs e) {
Debug.Assert(symbolFilesListBox.SelectedIndices.Count > 0);
for (int i = symbolFilesListBox.SelectedIndices.Count - 1; i >= 0; i--) {
int index = symbolFilesListBox.SelectedIndices[i];
symbolFilesListBox.Items.RemoveAt(index);
mWorkProps.PlatformSymbolFileIdentifiers.RemoveAt(index);
}
mDirty = true;
UpdateControls();
}
private void importSymbolsButton_Click(object sender, EventArgs e) {
OpenFileDialog fileDlg = new OpenFileDialog() {
Filter = ProjectFile.FILENAME_FILTER + "|" + Properties.Resources.FILE_FILTER_ALL,
FilterIndex = 1
};
if (fileDlg.ShowDialog() != DialogResult.OK) {
return;
}
string projPathName = Path.GetFullPath(fileDlg.FileName);
DisasmProject newProject = new DisasmProject();
if (!ProjectFile.DeserializeFromFile(projPathName, newProject,
out FileLoadReport report)) {
// Unable to open project file. Report error and bail.
ProjectLoadIssues dlg = new ProjectLoadIssues(report.Format(),
ProjectLoadIssues.Buttons.Cancel);
dlg.ShowDialog();
// ignore dlg.DialogResult
dlg.Dispose();
return;
}
// Import all user labels that were marked as "global export". These become
// external-address project symbols.
int foundCount = 0;
foreach (KeyValuePair<int, Symbol> kvp in newProject.UserLabels) {
if (kvp.Value.SymbolType == Symbol.Type.GlobalAddrExport) {
Symbol sym = kvp.Value;
DefSymbol defSym = new DefSymbol(sym.Label, sym.Value, Symbol.Source.Project,
Symbol.Type.ExternalAddr, FormatDescriptor.SubType.None,
string.Empty, string.Empty);
mWorkProps.ProjectSyms[defSym.Label] = defSym;
foundCount++;
}
}
if (foundCount != 0) {
mDirty = true;
LoadProjectSymbols();
UpdateControls();
}
newProject.Cleanup();
// Tell the user we did something. Might be nice to tell them how many weren't
// already present.
string msg;
if (foundCount == 0) {
msg = Properties.Resources.SYMBOL_IMPORT_NONE;
} else {
msg = string.Format(Properties.Resources.SYMBOL_IMPORT_GOOD, foundCount);
}
MessageBox.Show(this, msg, Properties.Resources.SYMBOL_IMPORT_CAPTION,
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#endif
#endregion Platform symbol files
#region Extension scripts
/// <summary>
/// Loads the extension script file names into the list control.
/// </summary>
private void LoadExtensionScriptNames() {
#if false
extensionScriptsListBox.BeginUpdate();
extensionScriptsListBox.Items.Clear();
foreach (string fileName in mWorkProps.ExtensionScriptFileIdentifiers) {
extensionScriptsListBox.Items.Add(fileName);
}
extensionScriptsListBox.EndUpdate();
#endif
}
#if false
private void extensionScriptsListBox_SelectedIndexChanged(object sender, EventArgs e) {
// Enable/disable buttons as the selection changes.
UpdateControls();
}
private void addExtensionScriptsButton_Click(object sender, EventArgs e) {
OpenFileDialog fileDlg = new OpenFileDialog() {
Filter = Sandbox.ScriptManager.FILENAME_FILTER,
Multiselect = true,
InitialDirectory = RuntimeDataAccess.GetDirectory(),
RestoreDirectory = true // doesn't seem to work?
};
if (fileDlg.ShowDialog() != DialogResult.OK) {
return;
}
foreach (string pathName in fileDlg.FileNames) {
// I'm assuming the full names got the Path.GetFullPath() canonicalization and
// don't need further processing. Also, I'm assuming that all files live in
// the same directory, so if one is in an invalid location then they all are.
ExternalFile ef = ExternalFile.CreateFromPath(pathName, mProjectDir);
if (ef == null) {
// Files not found in runtime or project directory.
string projDir = mProjectDir;
if (string.IsNullOrEmpty(projDir)) {
projDir = Properties.Resources.UNSET;
}
string msg = string.Format(Properties.Resources.EXTERNAL_FILE_BAD_DIR,
RuntimeDataAccess.GetDirectory(), projDir, pathName);
MessageBox.Show(this, msg, Properties.Resources.EXTERNAL_FILE_BAD_DIR_CAPTION,
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string ident = ef.Identifier;
if (mWorkProps.ExtensionScriptFileIdentifiers.Contains(ident)) {
Debug.WriteLine("Already present: " + ident);
continue;
}
Debug.WriteLine("Adding extension script: " + ident);
mWorkProps.ExtensionScriptFileIdentifiers.Add(ident);
mDirty = true;
}
if (mDirty) {
LoadExtensionScriptNames();
UpdateControls();
}
}
private void extensionScriptRemoveButton_Click(object sender, EventArgs e) {
Debug.Assert(extensionScriptsListBox.SelectedIndices.Count > 0);
for (int i = extensionScriptsListBox.SelectedIndices.Count - 1; i >= 0; i--) {
int index = extensionScriptsListBox.SelectedIndices[i];
extensionScriptsListBox.Items.RemoveAt(index);
mWorkProps.ExtensionScriptFileIdentifiers.RemoveAt(index);
}
mDirty = true;
UpdateControls();
}
#endif
#endregion Extension scripts
}
}