/* * 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.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using Asm65; using CommonWPF; namespace SourceGen.WpfGui { /// /// Edit a LocalVariableTable. /// public partial class EditLocalVariableTable : Window { /// /// Result. Will be null if the table was deleted, or if cancel was hit while /// creating a new table. /// public LocalVariableTable NewTable { get; private set; } // Item for the symbol list view ItemsSource. public class FormattedSymbol { public string Label { get; private set; } public string Value { get; private set; } public string Type { get; private set; } public string Width { get; private set; } public string Comment { get; private set; } public FormattedSymbol(string label, string value, string type, string width, string comment) { Label = label; Value = value; Type = type; Width = width; Comment = comment; } } public ObservableCollection Variables { get; private set; } = new ObservableCollection(); public bool ClearPrevious { get { return mWorkTable.ClearPrevious; } set { mWorkTable.ClearPrevious = value; OnPropertyChanged(); } } /// /// Working set. Used internally to hold state. /// private LocalVariableTable mWorkTable; /// /// Symbol table for uniqueness check. /// private SymbolTable mSymbolTable; /// /// Format object to use when formatting addresses and constants. /// private Formatter mFormatter; // INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public EditLocalVariableTable(Window owner, SymbolTable symbolTable, Formatter formatter, LocalVariableTable lvt) { InitializeComponent(); Owner = owner; DataContext = this; mSymbolTable = symbolTable; mFormatter = formatter; if (lvt != null) { mWorkTable = new LocalVariableTable(lvt); } else { mWorkTable = new LocalVariableTable(); } LoadVariables(); } public void Window_Loaded(object sender, RoutedEventArgs e) { UpdateControls(); } /// /// Loads entries from the work table into the items source. /// private void LoadVariables() { Variables.Clear(); foreach (KeyValuePair kvp in mWorkTable.Variables) { 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.Width == DefSymbol.NO_WIDTH ? string.Empty : defSym.Width.ToString(), defSym.Comment); Variables.Add(fsym); } } private void UpdateControls() { // 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 = symbolsListView.SelectedItems.Count; removeSymbolButton.IsEnabled = (symSelCount == 1); editSymbolButton.IsEnabled = (symSelCount == 1); } private void OkButton_Click(object sender, RoutedEventArgs e) { NewTable = mWorkTable; DialogResult = true; } private void DeleteTableButton_Click(object sender, RoutedEventArgs e) { // TODO - get confirmation, then set result=true with LvTable=null } private void SymbolsListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { UpdateControls(); } private void SymbolsListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ListViewItem lvi = symbolsListView.GetClickedItem(e); if (lvi == null) { return; } FormattedSymbol item = (FormattedSymbol)lvi.Content; DefSymbol defSym = mWorkTable.Variables[item.Label]; DoEditSymbol(defSym); } private void NewSymbolButton_Click(object sender, RoutedEventArgs e) { EditDefSymbol dlg = new EditDefSymbol(this, mFormatter, mWorkTable.Variables, null, mSymbolTable); dlg.ShowDialog(); if (dlg.DialogResult == true) { Debug.WriteLine("ADD: " + dlg.NewSym); mWorkTable.Variables[dlg.NewSym.Label] = dlg.NewSym; // 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. LoadVariables(); UpdateControls(); } } private void EditSymbolButton_Click(object sender, EventArgs e) { // Single-select list view, button dimmed when no selection. Debug.Assert(symbolsListView.SelectedItems.Count == 1); FormattedSymbol item = (FormattedSymbol)symbolsListView.SelectedItems[0]; DefSymbol defSym = mWorkTable.Variables[item.Label]; DoEditSymbol(defSym); } private void DoEditSymbol(DefSymbol defSym) { EditDefSymbol dlg = new EditDefSymbol(this, mFormatter, mWorkTable.Variables, defSym, mSymbolTable); dlg.ShowDialog(); if (dlg.DialogResult == true) { // Label might have changed, so remove old before adding new. mWorkTable.Variables.Remove(defSym.Label); mWorkTable.Variables[dlg.NewSym.Label] = dlg.NewSym; LoadVariables(); UpdateControls(); } } private void RemoveSymbolButton_Click(object sender, RoutedEventArgs e) { // Single-select list view, button dimmed when no selection. Debug.Assert(symbolsListView.SelectedItems.Count == 1); int selectionIndex = symbolsListView.SelectedIndex; FormattedSymbol item = (FormattedSymbol)symbolsListView.SelectedItems[0]; DefSymbol defSym = mWorkTable.Variables[item.Label]; mWorkTable.Variables.Remove(defSym.Label); LoadVariables(); 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 = symbolsListView.Items.Count; if (selectionIndex >= newCount) { selectionIndex = newCount - 1; } if (selectionIndex >= 0) { symbolsListView.SelectedIndex = selectionIndex; removeSymbolButton.Focus(); } } } }