mirror of
https://github.com/fadden/6502bench.git
synced 2025-04-11 11:37:11 +00:00
Add Edit Address
Pretty simple dialog, but it took a while to figure out the best way to deal with input validation. Works from the various menus as well as double-clicking on .ORG and address column entries. Also, moved some stuff around to places that made more sense.
This commit is contained in:
parent
d3230ef0d6
commit
61ecb28d60
@ -18,13 +18,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
using Asm65;
|
||||
using CommonUtil;
|
||||
using SourceGenWPF.ProjWin;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Text;
|
||||
|
||||
namespace SourceGenWPF {
|
||||
/// <summary>
|
||||
@ -57,7 +57,7 @@ namespace SourceGenWPF {
|
||||
/// <summary>
|
||||
/// Data backing the code list.
|
||||
/// </summary>
|
||||
public LineListGen CodeListGen { get; private set; }
|
||||
public LineListGen CodeLineList { get; private set; }
|
||||
|
||||
#endregion Project state
|
||||
|
||||
@ -73,6 +73,11 @@ namespace SourceGenWPF {
|
||||
private List<string> mRecentProjectPaths = new List<string>(MAX_RECENT_PROJECTS);
|
||||
public const int MAX_RECENT_PROJECTS = 6;
|
||||
|
||||
/// <summary>
|
||||
/// Analyzed selection state, updated whenever the selection changes.
|
||||
/// </summary>
|
||||
public SelectionState SelectionAnalysis { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Activity log generated by the code and data analyzers. Displayed in window.
|
||||
/// </summary>
|
||||
@ -139,6 +144,10 @@ namespace SourceGenWPF {
|
||||
/// </summary>
|
||||
private bool mUseMainAppDomainForPlugins = false;
|
||||
|
||||
private enum ColumnIndex {
|
||||
Offset = 0, Address, Bytes, Flags, Attributes, Label, Opcode, Operand, Comment
|
||||
}
|
||||
|
||||
|
||||
#region Init and settings
|
||||
|
||||
@ -303,7 +312,7 @@ namespace SourceGenWPF {
|
||||
#endif
|
||||
|
||||
// Finally, update the display list generator with all the fancy settings.
|
||||
if (CodeListGen != null) {
|
||||
if (CodeLineList != null) {
|
||||
// Regenerate the display list with the latest formatter config and
|
||||
// pseudo-op definition. (These are set as part of the refresh.)
|
||||
UndoableChange uc =
|
||||
@ -398,7 +407,7 @@ namespace SourceGenWPF {
|
||||
dlg.ShowDialog();
|
||||
}
|
||||
|
||||
CodeListGen = new LineListGen(mProject, mMainWin.CodeDisplayList,
|
||||
CodeLineList = new LineListGen(mProject, mMainWin.CodeDisplayList,
|
||||
mOutputFormatter, mPseudoOpNames);
|
||||
|
||||
RefreshProject(UndoableChange.ReanalysisScope.CodeAndData);
|
||||
@ -481,9 +490,12 @@ namespace SourceGenWPF {
|
||||
mReanalysisTimer.StartTask("Save selection");
|
||||
int topItemIndex = mMainWin.CodeListView_GetTopIndex();
|
||||
LineListGen.SavedSelection savedSel = LineListGen.SavedSelection.Generate(
|
||||
CodeListGen, mMainWin.CodeDisplayList.SelectedIndices,
|
||||
CodeListGen[topItemIndex].FileOffset);
|
||||
CodeLineList, mMainWin.CodeDisplayList.SelectedIndices,
|
||||
CodeLineList[topItemIndex].FileOffset);
|
||||
//savedSel.DebugDump();
|
||||
|
||||
// Clear this so we don't try to fiddle with it later.
|
||||
mTargetHighlightIndex = -1;
|
||||
mReanalysisTimer.EndTask("Save selection");
|
||||
|
||||
mReanalysisTimer.StartTask("Apply changes");
|
||||
@ -503,7 +515,7 @@ namespace SourceGenWPF {
|
||||
}
|
||||
mReanalysisTimer.EndTask(refreshTaskStr);
|
||||
|
||||
DisplayListSelection newSel = savedSel.Restore(CodeListGen, out topItemIndex);
|
||||
DisplayListSelection newSel = savedSel.Restore(CodeLineList, out topItemIndex);
|
||||
//newSel.DebugDump();
|
||||
|
||||
// Restore the selection. The selection-changed event will cause updates to the
|
||||
@ -556,8 +568,8 @@ namespace SourceGenWPF {
|
||||
Debug.WriteLine("CpuDef has changed, resetting formatter (now " +
|
||||
mProject.CpuDef + ")");
|
||||
mOutputFormatter = new Formatter(mFormatterConfig);
|
||||
CodeListGen.SetFormatter(mOutputFormatter);
|
||||
CodeListGen.SetPseudoOpNames(mPseudoOpNames);
|
||||
CodeLineList.SetFormatter(mOutputFormatter);
|
||||
CodeLineList.SetPseudoOpNames(mPseudoOpNames);
|
||||
mOutputFormatterCpuDef = mProject.CpuDef;
|
||||
}
|
||||
|
||||
@ -605,7 +617,7 @@ namespace SourceGenWPF {
|
||||
IEnumerator<RangeSet.Range> iter = offsetSet.RangeListIterator;
|
||||
while (iter.MoveNext()) {
|
||||
RangeSet.Range range = iter.Current;
|
||||
CodeListGen.GenerateRange(range.Low, range.High);
|
||||
CodeLineList.GenerateRange(range.Low, range.High);
|
||||
}
|
||||
}
|
||||
|
||||
@ -633,7 +645,7 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
mReanalysisTimer.StartTask("Generate DisplayList");
|
||||
CodeListGen.GenerateAll();
|
||||
CodeLineList.GenerateAll();
|
||||
mReanalysisTimer.EndTask("Generate DisplayList");
|
||||
}
|
||||
|
||||
@ -955,6 +967,185 @@ namespace SourceGenWPF {
|
||||
|
||||
public void HandleCodeListDoubleClick(int row, int col) {
|
||||
Debug.WriteLine("DCLICK: row=" + row + " col=" + col);
|
||||
|
||||
// Clicking on some types of lines, such as ORG directives, results in
|
||||
// specific behavior regardless of which column you click in. We're just
|
||||
// checking the clicked-on line to decide what action to take. If it doesn't
|
||||
// make sense to do for a multi-line selection, the action will have been
|
||||
// disabled.
|
||||
LineListGen.Line line = CodeLineList[row];
|
||||
switch (line.LineType) {
|
||||
case LineListGen.Line.Type.EquDirective:
|
||||
// Currently only does something for project symbols; platform symbols
|
||||
// do nothing.
|
||||
#if false
|
||||
if (editProjectSymbolToolStripMenuItem.Enabled) {
|
||||
EditProjectSymbol_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case LineListGen.Line.Type.OrgDirective:
|
||||
if (CanEditAddress()) {
|
||||
EditAddress();
|
||||
}
|
||||
break;
|
||||
case LineListGen.Line.Type.RegWidthDirective:
|
||||
#if false
|
||||
if (overrideStatusFlagsToolStripMenuItem.Enabled) {
|
||||
EditStatusFlags_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case LineListGen.Line.Type.LongComment:
|
||||
#if false
|
||||
if (editLongCommentToolStripMenuItem.Enabled) {
|
||||
EditLongComment_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case LineListGen.Line.Type.Note:
|
||||
#if false
|
||||
if (editNoteToolStripMenuItem.Enabled) {
|
||||
EditNote_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LineListGen.Line.Type.Code:
|
||||
case LineListGen.Line.Type.Data:
|
||||
// For code and data, we have to break it down by column.
|
||||
switch ((ColumnIndex)col) {
|
||||
case ColumnIndex.Offset:
|
||||
// does nothing
|
||||
break;
|
||||
case ColumnIndex.Address:
|
||||
// edit address
|
||||
if (CanEditAddress()) {
|
||||
EditAddress();
|
||||
}
|
||||
break;
|
||||
case ColumnIndex.Bytes:
|
||||
#if false
|
||||
if (showHexDumpToolStripMenuItem.Enabled) {
|
||||
ShowHexDump_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ColumnIndex.Flags:
|
||||
#if false
|
||||
if (overrideStatusFlagsToolStripMenuItem.Enabled) {
|
||||
EditStatusFlags_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ColumnIndex.Attributes:
|
||||
// does nothing
|
||||
break;
|
||||
case ColumnIndex.Label:
|
||||
#if false
|
||||
if (editLabelToolStripMenuItem.Enabled) {
|
||||
EditLabel_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ColumnIndex.Opcode:
|
||||
// File offset should always be valid, since we excluded the EQU
|
||||
// statements and header comment earlier.
|
||||
if (line.FileOffset >= 0) {
|
||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||
FormatDescriptor dfd = attr.DataDescriptor;
|
||||
|
||||
// Does this have an operand with an in-file target offset?
|
||||
// (Resolve it as a numeric reference.)
|
||||
if (attr.OperandOffset >= 0) {
|
||||
// Yup, find the line for that offset and jump to it.
|
||||
GoToOffset(attr.OperandOffset, false, true);
|
||||
} else if (dfd != null && dfd.HasSymbol) {
|
||||
// Operand has a symbol, do a symbol lookup.
|
||||
int labelOffset = mProject.FindLabelOffsetByName(
|
||||
dfd.SymbolRef.Label);
|
||||
if (labelOffset >= 0) {
|
||||
GoToOffset(labelOffset, false, true);
|
||||
}
|
||||
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
|
||||
// If it's an Address or Symbol, we can try to resolve
|
||||
// the value. (Symbols should have been resolved by the
|
||||
// previous clause, but Address entries would not have been.)
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(
|
||||
mProject, line.FileOffset);
|
||||
if (operandOffset >= 0) {
|
||||
GoToOffset(operandOffset, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ColumnIndex.Operand:
|
||||
#if false
|
||||
if (editOperandToolStripMenuItem.Enabled) {
|
||||
EditInstrDataOperand_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ColumnIndex.Comment:
|
||||
#if false
|
||||
if (editCommentToolStripMenuItem.Enabled) {
|
||||
EditComment_Click(sender, e);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.WriteLine("Double-click: unhandled line type " + line.LineType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanEditAddress() {
|
||||
if (SelectionAnalysis.mNumItemsSelected != 1) {
|
||||
return false;
|
||||
}
|
||||
EntityCounts counts = SelectionAnalysis.mEntityCounts;
|
||||
// Line must be code, data, or an ORG directive.
|
||||
return (counts.mDataLines > 0 || counts.mCodeLines > 0) ||
|
||||
(SelectionAnalysis.mLineType == LineListGen.Line.Type.OrgDirective);
|
||||
}
|
||||
|
||||
public void EditAddress() {
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
int offset = CodeLineList[selIndex].FileOffset;
|
||||
Anattrib attr = mProject.GetAnattrib(offset);
|
||||
|
||||
EditAddress dlg = new EditAddress(attr.Address, mProject.CpuDef.MaxAddressValue);
|
||||
dlg.Owner = mMainWin;
|
||||
bool? ok = dlg.ShowDialog();
|
||||
if (ok != true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset == 0 && dlg.Address < 0) {
|
||||
// Not allowed. The AddressMap will just put it back, which confuses
|
||||
// the undo operation.
|
||||
Debug.WriteLine("EditAddress: not allowed to remove address at offset +000000");
|
||||
} else if (attr.Address != dlg.Address) {
|
||||
Debug.WriteLine("EditAddress: changing addr at offset +" + offset.ToString("x6") +
|
||||
" to " + dlg.Address);
|
||||
|
||||
AddressMap addrMap = mProject.AddrMap;
|
||||
// Get the previous address map entry for this exact offset, if one
|
||||
// exists. This may be different from the value used as the default
|
||||
// (attr.Address), which is the address assigned to the offset, in
|
||||
// the case where no previous mapping existed.
|
||||
int prevAddress = addrMap.Get(offset);
|
||||
UndoableChange uc = UndoableChange.CreateAddressChange(offset,
|
||||
prevAddress, dlg.Address);
|
||||
ChangeSet cs = new ChangeSet(uc);
|
||||
ApplyUndoableChanges(cs);
|
||||
} else {
|
||||
Debug.WriteLine("EditAddress: no change");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -966,7 +1157,7 @@ namespace SourceGenWPF {
|
||||
public void GoToOffset(int gotoOffset, bool jumpToNote, bool doPush) {
|
||||
int curSelIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
|
||||
int topLineIndex = CodeListGen.FindLineIndexByOffset(gotoOffset);
|
||||
int topLineIndex = CodeLineList.FindLineIndexByOffset(gotoOffset);
|
||||
if (topLineIndex < 0) {
|
||||
Debug.Assert(false, "failed goto offset +" + gotoOffset.ToString("x6"));
|
||||
return;
|
||||
@ -974,13 +1165,13 @@ namespace SourceGenWPF {
|
||||
int lastLineIndex;
|
||||
if (jumpToNote) {
|
||||
// Select all note lines, disregard the rest.
|
||||
while (CodeListGen[topLineIndex].LineType != LineListGen.Line.Type.Note) {
|
||||
while (CodeLineList[topLineIndex].LineType != LineListGen.Line.Type.Note) {
|
||||
topLineIndex++;
|
||||
Debug.Assert(CodeListGen[topLineIndex].FileOffset == gotoOffset);
|
||||
Debug.Assert(CodeLineList[topLineIndex].FileOffset == gotoOffset);
|
||||
}
|
||||
lastLineIndex = topLineIndex + 1;
|
||||
while (lastLineIndex < CodeListGen.Count &&
|
||||
CodeListGen[lastLineIndex].LineType == LineListGen.Line.Type.Note) {
|
||||
while (lastLineIndex < CodeLineList.Count &&
|
||||
CodeLineList[lastLineIndex].LineType == LineListGen.Line.Type.Note) {
|
||||
lastLineIndex++;
|
||||
}
|
||||
} else if (gotoOffset < 0) {
|
||||
@ -988,8 +1179,8 @@ namespace SourceGenWPF {
|
||||
lastLineIndex = topLineIndex + 1;
|
||||
} else {
|
||||
// Advance to the code or data line.
|
||||
while (CodeListGen[topLineIndex].LineType != LineListGen.Line.Type.Code &&
|
||||
CodeListGen[topLineIndex].LineType != LineListGen.Line.Type.Data) {
|
||||
while (CodeLineList[topLineIndex].LineType != LineListGen.Line.Type.Code &&
|
||||
CodeLineList[topLineIndex].LineType != LineListGen.Line.Type.Data) {
|
||||
topLineIndex++;
|
||||
}
|
||||
lastLineIndex = topLineIndex + 1;
|
||||
@ -1006,7 +1197,7 @@ namespace SourceGenWPF {
|
||||
if (doPush) {
|
||||
if (curSelIndex >= 0) {
|
||||
// Update the back stack and associated controls.
|
||||
mNavStack.Push(CodeListGen[curSelIndex].FileOffset, gotoOffset);
|
||||
mNavStack.Push(CodeLineList[curSelIndex].FileOffset, gotoOffset);
|
||||
#if false
|
||||
UpdateMenuItemsAndTitle();
|
||||
#endif
|
||||
@ -1052,8 +1243,8 @@ namespace SourceGenWPF {
|
||||
GoToOffset(fwdOff, false, false);
|
||||
}
|
||||
|
||||
public void SelectionChanged(out SelectionState newState) {
|
||||
newState = UpdateSelectionState();
|
||||
public void SelectionChanged() {
|
||||
SelectionAnalysis = UpdateSelectionState();
|
||||
|
||||
UpdateReferencesPanel();
|
||||
UpdateInfoPanel();
|
||||
@ -1069,21 +1260,22 @@ namespace SourceGenWPF {
|
||||
// 0 if no lines are selected
|
||||
// 1 if a single *item* is selected (regardless of number of lines)
|
||||
// >1 if more than one item is selected (exact value not specified)
|
||||
public int mNumSelected;
|
||||
public int mNumItemsSelected;
|
||||
|
||||
// Single selection: the type of line selected.
|
||||
// Single selection: the type of line selected. (Multi-sel: Unclassified)
|
||||
public LineListGen.Line.Type mLineType;
|
||||
|
||||
// Single selection: is line an instruction with an operand.
|
||||
// Single selection: is line an instruction with an operand. (Multi-sel: False)
|
||||
public bool mIsInstructionWithOperand;
|
||||
|
||||
// Single selection: is line an EQU directive for a project symbol.
|
||||
// Single selection: is line an EQU directive for a project symbol. (Multi-sel: False)
|
||||
public bool mIsProjectSymbolEqu;
|
||||
|
||||
// Some totals.
|
||||
public EntityCounts mEntityCounts;
|
||||
|
||||
public SelectionState() {
|
||||
mLineType = LineListGen.Line.Type.Unclassified;
|
||||
mEntityCounts = new EntityCounts();
|
||||
}
|
||||
}
|
||||
@ -1106,9 +1298,9 @@ namespace SourceGenWPF {
|
||||
state.mEntityCounts = new EntityCounts();
|
||||
} else if (IsSingleItemSelected()) {
|
||||
int firstIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
state.mNumSelected = 1;
|
||||
state.mNumItemsSelected = 1;
|
||||
state.mEntityCounts = GatherEntityCounts(firstIndex);
|
||||
LineListGen.Line line = CodeListGen[firstIndex];
|
||||
LineListGen.Line line = CodeLineList[firstIndex];
|
||||
state.mLineType = line.LineType;
|
||||
|
||||
state.mIsInstructionWithOperand = (line.LineType == LineListGen.Line.Type.Code &&
|
||||
@ -1120,7 +1312,7 @@ namespace SourceGenWPF {
|
||||
state.mIsProjectSymbolEqu = (defSym.SymbolSource == Symbol.Source.Project);
|
||||
}
|
||||
} else {
|
||||
state.mNumSelected = 2;
|
||||
state.mNumItemsSelected = 2;
|
||||
state.mEntityCounts = GatherEntityCounts(-1);
|
||||
}
|
||||
|
||||
@ -1168,7 +1360,7 @@ namespace SourceGenWPF {
|
||||
// not selected, ignore
|
||||
continue;
|
||||
}
|
||||
LineListGen.Line line = CodeListGen[i];
|
||||
LineListGen.Line line = CodeLineList[i];
|
||||
switch (line.LineType) {
|
||||
case LineListGen.Line.Type.Code:
|
||||
codeLines++;
|
||||
@ -1248,8 +1440,8 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
// Just check the first and last entries to see if they're the same.
|
||||
LineListGen.Line firstItem = CodeListGen[firstIndex];
|
||||
LineListGen.Line lastItem = CodeListGen[lastIndex];
|
||||
LineListGen.Line firstItem = CodeLineList[firstIndex];
|
||||
LineListGen.Line lastItem = CodeLineList[lastIndex];
|
||||
if (firstItem.FileOffset == lastItem.FileOffset &&
|
||||
firstItem.LineType == lastItem.LineType) {
|
||||
return true;
|
||||
@ -1279,7 +1471,7 @@ namespace SourceGenWPF {
|
||||
return -1;
|
||||
}
|
||||
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
LineListGen.Line line = CodeListGen[selIndex];
|
||||
LineListGen.Line line = CodeLineList[selIndex];
|
||||
if (!line.IsCodeOrData) {
|
||||
return -1;
|
||||
}
|
||||
@ -1288,13 +1480,13 @@ namespace SourceGenWPF {
|
||||
// Does this have an operand with an in-file target offset?
|
||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||
if (attr.OperandOffset >= 0) {
|
||||
return CodeListGen.FindCodeDataIndexByOffset(attr.OperandOffset);
|
||||
return CodeLineList.FindCodeDataIndexByOffset(attr.OperandOffset);
|
||||
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
|
||||
// If it's an Address or Symbol, we can try to resolve
|
||||
// the value.
|
||||
int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset);
|
||||
if (operandOffset >= 0) {
|
||||
return CodeListGen.FindCodeDataIndexByOffset(operandOffset);
|
||||
return CodeLineList.FindCodeDataIndexByOffset(operandOffset);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@ -1359,7 +1551,7 @@ namespace SourceGenWPF {
|
||||
if (firstByteOnly) {
|
||||
sel = new RangeSet();
|
||||
foreach (int index in mMainWin.CodeDisplayList.SelectedIndices) {
|
||||
int offset = CodeListGen[index].FileOffset;
|
||||
int offset = CodeLineList[index].FileOffset;
|
||||
if (offset >= 0) {
|
||||
// Not interested in the header stuff for hinting.
|
||||
sel.Add(offset);
|
||||
@ -1408,7 +1600,7 @@ namespace SourceGenWPF {
|
||||
RangeSet rs = new RangeSet();
|
||||
|
||||
foreach (int index in mMainWin.CodeDisplayList.SelectedIndices) {
|
||||
int offset = CodeListGen[index].FileOffset;
|
||||
int offset = CodeLineList[index].FileOffset;
|
||||
|
||||
// Mark every byte of an instruction or multi-byte data item --
|
||||
// everything that is represented by the line the user selected.
|
||||
@ -1436,6 +1628,7 @@ namespace SourceGenWPF {
|
||||
|
||||
#endregion Main window UI event handlers
|
||||
|
||||
|
||||
#region References panel
|
||||
|
||||
/// <summary>
|
||||
@ -1453,7 +1646,7 @@ namespace SourceGenWPF {
|
||||
return;
|
||||
}
|
||||
int lineIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
LineListGen.Line.Type type = CodeListGen[lineIndex].LineType;
|
||||
LineListGen.Line.Type type = CodeLineList[lineIndex].LineType;
|
||||
if (type != LineListGen.Line.Type.Code &&
|
||||
type != LineListGen.Line.Type.Data &&
|
||||
type != LineListGen.Line.Type.EquDirective) {
|
||||
@ -1462,7 +1655,7 @@ namespace SourceGenWPF {
|
||||
}
|
||||
|
||||
// Find the appropriate xref set.
|
||||
int offset = CodeListGen[lineIndex].FileOffset;
|
||||
int offset = CodeLineList[lineIndex].FileOffset;
|
||||
XrefSet xrefs;
|
||||
if (offset < 0) {
|
||||
int index = LineListGen.DefSymIndexFromOffset(offset);
|
||||
@ -1582,7 +1775,7 @@ namespace SourceGenWPF {
|
||||
return;
|
||||
}
|
||||
int lineIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
|
||||
LineListGen.Line line = CodeListGen[lineIndex];
|
||||
LineListGen.Line line = CodeLineList[lineIndex];
|
||||
StringBuilder sb = new StringBuilder(250);
|
||||
|
||||
// TODO(someday): this should be made easier to localize
|
||||
|
@ -1,5 +1,6 @@
|
||||
<!--
|
||||
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
|
||||
@ -153,13 +154,18 @@ See also https://github.com/fadden/DisasmUiTest
|
||||
</Style>
|
||||
|
||||
<!-- Highlighting for individual cells. -->
|
||||
<LinearGradientBrush x:Key="HighlightedCellFill" EndPoint="0,1" StartPoint="0,0">
|
||||
<GradientStop Color="#FFD9Fff4" Offset="0"/>
|
||||
<GradientStop Color="#FF9Bfbdd" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<DataTemplate x:Key="addrHighlightTemplate">
|
||||
<TextBlock>
|
||||
<TextBlock.Style>
|
||||
<Style>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=HasAddrLabelHighlight}" Value="True">
|
||||
<Setter Property="TextBlock.Background" Value="{StaticResource ListItemSelectedFill}"/>
|
||||
<Setter Property="TextBlock.Background" Value="{StaticResource HighlightedCellFill}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
@ -175,7 +181,7 @@ See also https://github.com/fadden/DisasmUiTest
|
||||
<Style>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=HasAddrLabelHighlight}" Value="True">
|
||||
<Setter Property="TextBlock.Background" Value="{StaticResource ListItemSelectedFill}"/>
|
||||
<Setter Property="TextBlock.Background" Value="{StaticResource HighlightedCellFill}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
@ -1,4 +1,20 @@
|
||||
<Window x:Class="SourceGenWPF.ProjWin.DataFileLoadIssue"
|
||||
<!--
|
||||
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.ProjWin.DataFileLoadIssue"
|
||||
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"
|
||||
|
@ -1,12 +1,29 @@
|
||||
<Window x:Class="SourceGenWPF.ProjWin.DiscardChanges"
|
||||
<!--
|
||||
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.ProjWin.DiscardChanges"
|
||||
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.ProjWin"
|
||||
mc:Ignorable="d"
|
||||
Title="Discard Changes?" ShowInTaskbar="False"
|
||||
Width="398" Height="125" ResizeMode="NoResize" WindowStartupLocation="CenterOwner">
|
||||
Title="Discard Changes?"
|
||||
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner">
|
||||
<StackPanel Margin="8">
|
||||
<TextBlock Text="You have unsaved changes that will be lost if you continue."/>
|
||||
<TextBlock Margin="0,8,0,0" Text="How do you wish to proceed?"/>
|
||||
|
55
SourceGenWPF/ProjWin/EditAddress.xaml
Normal file
55
SourceGenWPF/ProjWin/EditAddress.xaml
Normal file
@ -0,0 +1,55 @@
|
||||
<!--
|
||||
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.ProjWin.EditAddress"
|
||||
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.ProjWin"
|
||||
mc:Ignorable="d"
|
||||
Title="Set Address"
|
||||
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
||||
Loaded="Window_Loaded">
|
||||
|
||||
<StackPanel Margin="8">
|
||||
<TextBlock Text="Enter 16-bit or 24-bit address in hexadecimal, e.g. $1000 or 00/be00."/>
|
||||
<TextBlock Text="Leave the field blank to remove the address override."/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<TextBlock Text="Address:"/>
|
||||
<TextBox Name="addrTextBox" Width="100" Margin="4,0,0,0"
|
||||
FontFamily="{StaticResource GeneralMonoFont}"
|
||||
Text="{Binding Path=AddressText, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsInactiveSelectionHighlightEnabled="True"
|
||||
TextChanged="TextBox_TextChanged">
|
||||
<TextBox.Resources>
|
||||
<!-- default non-focus highlight color is nearly invisible -->
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
|
||||
Color="LightBlue"/>
|
||||
</TextBox.Resources>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0">
|
||||
<Button Name="okButton" Content="OK" IsDefault="True"
|
||||
Width="70" Click="OkButton_Click"/>
|
||||
<Button Name="cancelButton" Content="Cancel" IsCancel="True"
|
||||
Width="70" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
121
SourceGenWPF/ProjWin/EditAddress.xaml.cs
Normal file
121
SourceGenWPF/ProjWin/EditAddress.xaml.cs
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SourceGenWPF.ProjWin {
|
||||
/// <summary>
|
||||
/// Edit Address dialog.
|
||||
/// </summary>
|
||||
public partial class EditAddress : Window {
|
||||
/// <summary>
|
||||
/// Address typed by user. Only valid after the dialog returns OK. Will be set to -1
|
||||
/// if the user is attempting to delete the address.
|
||||
/// </summary>
|
||||
public int Address { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum allowed address value.
|
||||
/// </summary>
|
||||
private int mMaxAddressValue;
|
||||
|
||||
/// <summary>
|
||||
/// Bound two-way property.
|
||||
/// </summary>
|
||||
public string AddressText { get; set; }
|
||||
|
||||
|
||||
public EditAddress(int initialAddr, int maxAddressValue) {
|
||||
// Set the property before initializing the window -- we don't have a property
|
||||
// change notifier.
|
||||
Address = -2;
|
||||
mMaxAddressValue = maxAddressValue;
|
||||
AddressText = Asm65.Address.AddressToString(initialAddr, false);
|
||||
|
||||
this.DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e) {
|
||||
if (AddressText.Length == 0) {
|
||||
Address = -1;
|
||||
} else {
|
||||
Asm65.Address.ParseAddress(AddressText, mMaxAddressValue, out int addr);
|
||||
Address = addr;
|
||||
}
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a TextChanged event on the address text box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Must have UpdateSourceTrigger=PropertyChanged set for this to work. The default
|
||||
/// for TextBox is LostFocus.
|
||||
/// </remarks>
|
||||
private void TextBox_TextChanged(object sender, TextChangedEventArgs e) {
|
||||
if (IsLoaded) {
|
||||
UpdateOkEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateOkEnabled() {
|
||||
string text = AddressText;
|
||||
okButton.IsEnabled = (text.Length == 0) ||
|
||||
Asm65.Address.ParseAddress(text, mMaxAddressValue, out int unused);
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
addrTextBox.SelectAll();
|
||||
addrTextBox.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// I briefly played with the validation rules. However, they're primarily designed for
|
||||
// form entry, which means they fire when focus leaves the text box. [note: not sure if
|
||||
// this would change with UpdateSourceTrigger=PropertyChanged] I want the OK button to be
|
||||
// kept constantly up to date as the user types, so this didn't really work. It's also a
|
||||
// lot bigger and uglier than just handling an event.
|
||||
//
|
||||
// It's also sort of awkward to pass parameters, like MaxAddressValue, into the
|
||||
// validation rule.
|
||||
// https://social.technet.microsoft.com/wiki/contents/articles/31422.wpf-passing-a-data-bound-value-to-a-validation-rule.aspx
|
||||
//
|
||||
// Speaking of awkward, updating the OK button enable/disable through validation
|
||||
// is possible via MultiDataTrigger.
|
||||
|
||||
|
||||
//public class AddressValidationRule : ValidationRule {
|
||||
// public int MaxAddress { get; set; }
|
||||
|
||||
// public override ValidationResult Validate(object value, CultureInfo cultureInfo) {
|
||||
// string text = value.ToString();
|
||||
// Debug.WriteLine("VALIDATE " + text);
|
||||
// if ((text.Length == 0) ||
|
||||
// Asm65.Address.ParseAddress(text, MaxAddress, out int unused)) {
|
||||
// return new ValidationResult(true, null);
|
||||
// } else {
|
||||
// return new ValidationResult(false, "Invalid address");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
<!--
|
||||
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
|
||||
@ -48,6 +49,7 @@ limitations under the License.
|
||||
</RoutedUICommand.InputGestures>
|
||||
</RoutedUICommand>
|
||||
<RoutedUICommand x:Key="CloseCmd" Text="Close"/>
|
||||
<RoutedUICommand x:Key="EditAddressCmd" Text="Set Address..."/>
|
||||
<RoutedUICommand x:Key="HintAsCodeEntryPointCmd" Text="Hint As Code Entry Point"/>
|
||||
<RoutedUICommand x:Key="HintAsDataStartCmd" Text="Hint As Data Start"/>
|
||||
<RoutedUICommand x:Key="HintAsInlineDataCmd" Text="Hint As Inline Data"/>
|
||||
@ -92,6 +94,8 @@ limitations under the License.
|
||||
CanExecute="IsProjectOpen" Executed="AssembleCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource CloseCmd}"
|
||||
CanExecute="IsProjectOpen" Executed="CloseCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource EditAddressCmd}"
|
||||
CanExecute="CanEditAddress" Executed="EditAddressCmd_Executed"/>
|
||||
<CommandBinding Command="Help"
|
||||
Executed="HelpCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource HintAsCodeEntryPointCmd}"
|
||||
@ -152,7 +156,7 @@ limitations under the License.
|
||||
<MenuItem Header="Settings..."/>
|
||||
</MenuItem>
|
||||
<MenuItem Name="ActionsMenu" Header="_Actions">
|
||||
<MenuItem Header="Set Address..."/>
|
||||
<MenuItem Command="{StaticResource EditAddressCmd}"/>
|
||||
<MenuItem Header="Override Status Flags..."/>
|
||||
<MenuItem Header="Edit Label..."/>
|
||||
<MenuItem Header="Edit Operand..."/>
|
||||
|
@ -56,11 +56,6 @@ namespace SourceGenWPF.ProjWin {
|
||||
/// </summary>
|
||||
private MainController mMainCtrl;
|
||||
|
||||
/// <summary>
|
||||
/// Analyzed selection state.
|
||||
/// </summary>
|
||||
private MainController.SelectionState mSelectionState;
|
||||
|
||||
// Handle to protected ListView.SetSelectedItems() method
|
||||
private MethodInfo listViewSetSelectedItems;
|
||||
|
||||
@ -80,8 +75,6 @@ namespace SourceGenWPF.ProjWin {
|
||||
|
||||
mMainCtrl = new MainController(this);
|
||||
|
||||
mSelectionState = new MainController.SelectionState();
|
||||
|
||||
AddMultiKeyGestures();
|
||||
|
||||
//GridView gv = (GridView)codeListView.View;
|
||||
@ -258,9 +251,8 @@ namespace SourceGenWPF.ProjWin {
|
||||
// Update the selected-item bitmap.
|
||||
CodeDisplayList.SelectedIndices.SelectionChanged(e);
|
||||
|
||||
// Notify MainController that the selection has changed. This hands back an updated
|
||||
// selection summary, which is used for "can execute" methods.
|
||||
mMainCtrl.SelectionChanged(out mSelectionState);
|
||||
// Notify MainController that the selection has changed.
|
||||
mMainCtrl.SelectionChanged();
|
||||
|
||||
Debug.Assert(CodeDisplayList.SelectedIndices.DebugValidateSelectionCount(
|
||||
codeListView.SelectedItems.Count));
|
||||
@ -474,12 +466,20 @@ namespace SourceGenWPF.ProjWin {
|
||||
e.CanExecute = mMainCtrl != null && mMainCtrl.IsProjectOpen();
|
||||
}
|
||||
|
||||
private void CanEditAddress(object sender, CanExecuteRoutedEventArgs e) {
|
||||
if (mMainCtrl == null || !mMainCtrl.IsProjectOpen()) {
|
||||
e.CanExecute = false;
|
||||
return;
|
||||
}
|
||||
e.CanExecute = mMainCtrl.CanEditAddress();
|
||||
}
|
||||
|
||||
private void CanHintAsCodeEntryPoint(object sender, CanExecuteRoutedEventArgs e) {
|
||||
if (mMainCtrl == null || !mMainCtrl.IsProjectOpen()) {
|
||||
e.CanExecute = false;
|
||||
return;
|
||||
}
|
||||
MainController.EntityCounts counts = mSelectionState.mEntityCounts;
|
||||
MainController.EntityCounts counts = mMainCtrl.SelectionAnalysis.mEntityCounts;
|
||||
e.CanExecute = (counts.mDataLines > 0 || counts.mCodeLines > 0) &&
|
||||
(counts.mDataHints != 0 || counts.mInlineDataHints != 0 || counts.mNoHints != 0);
|
||||
}
|
||||
@ -488,7 +488,7 @@ namespace SourceGenWPF.ProjWin {
|
||||
e.CanExecute = false;
|
||||
return;
|
||||
}
|
||||
MainController.EntityCounts counts = mSelectionState.mEntityCounts;
|
||||
MainController.EntityCounts counts = mMainCtrl.SelectionAnalysis.mEntityCounts;
|
||||
e.CanExecute = (counts.mDataLines > 0 || counts.mCodeLines > 0) &&
|
||||
(counts.mCodeHints != 0 || counts.mInlineDataHints != 0 || counts.mNoHints != 0);
|
||||
}
|
||||
@ -497,7 +497,7 @@ namespace SourceGenWPF.ProjWin {
|
||||
e.CanExecute = false;
|
||||
return;
|
||||
}
|
||||
MainController.EntityCounts counts = mSelectionState.mEntityCounts;
|
||||
MainController.EntityCounts counts = mMainCtrl.SelectionAnalysis.mEntityCounts;
|
||||
e.CanExecute = (counts.mDataLines > 0 || counts.mCodeLines > 0) &&
|
||||
(counts.mCodeHints != 0 || counts.mDataHints != 0 || counts.mNoHints != 0);
|
||||
}
|
||||
@ -506,7 +506,7 @@ namespace SourceGenWPF.ProjWin {
|
||||
e.CanExecute = false;
|
||||
return;
|
||||
}
|
||||
MainController.EntityCounts counts = mSelectionState.mEntityCounts;
|
||||
MainController.EntityCounts counts = mMainCtrl.SelectionAnalysis.mEntityCounts;
|
||||
e.CanExecute = (counts.mDataLines > 0 || counts.mCodeLines > 0) &&
|
||||
(counts.mCodeHints != 0 || counts.mDataHints != 0 || counts.mInlineDataHints != 0);
|
||||
}
|
||||
@ -541,6 +541,10 @@ namespace SourceGenWPF.ProjWin {
|
||||
}
|
||||
}
|
||||
|
||||
private void EditAddressCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.EditAddress();
|
||||
}
|
||||
|
||||
private void HelpCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
mMainCtrl.ShowHelp();
|
||||
}
|
||||
|
@ -1,4 +1,20 @@
|
||||
<Window x:Class="SourceGenWPF.ProjWin.ProjectLoadIssues"
|
||||
<!--
|
||||
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.ProjWin.ProjectLoadIssues"
|
||||
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"
|
||||
|
@ -1,4 +1,20 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:SourceGenWPF.Res">
|
||||
|
@ -81,6 +81,9 @@
|
||||
<Compile Include="ProjWin\DiscardChanges.xaml.cs">
|
||||
<DependentUpon>DiscardChanges.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ProjWin\EditAddress.xaml.cs">
|
||||
<DependentUpon>EditAddress.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ProjWin\ProjectLoadIssue.xaml.cs">
|
||||
<DependentUpon>ProjectLoadIssue.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -161,6 +164,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ProjWin\EditAddress.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ProjWin\MainWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
Loading…
x
Reference in New Issue
Block a user