mirror of
https://github.com/fadden/6502bench.git
synced 2024-11-26 06:49:19 +00:00
Open damaged projects in read-only mode
If we detect a problem that requires intervention during loading, e.g. we find unknown elements because we're loading a file created by a newer version, default to read-only mode. Read only mode (1) refuses to apply changes, (2) refuses to add changes to the undo/redo list, and (3) disables Save/SaveAs. The mode is indicated in the title bar. Also, flipped the order of items in the title bar so that "6502bench SourceGen" comes last. This allows you to read the project name in short window title snippets. (Visual Studio, Notepad, and others do it this way as well.)
This commit is contained in:
parent
6344ea59bb
commit
d99eec0d4f
@ -120,6 +120,11 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public CpuDef CpuDef { get; private set; }
|
public CpuDef CpuDef { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If set, changes are ignored.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsReadOnly { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, plugins will execute in the main application's AppDomain instead of
|
/// If true, plugins will execute in the main application's AppDomain instead of
|
||||||
/// the sandbox. Must be set before calling Initialize().
|
/// the sandbox. Must be set before calling Initialize().
|
||||||
@ -1785,6 +1790,9 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="changeSet">Set to push.</param>
|
/// <param name="changeSet">Set to push.</param>
|
||||||
public void PushChangeSet(ChangeSet changeSet) {
|
public void PushChangeSet(ChangeSet changeSet) {
|
||||||
|
if (IsReadOnly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Debug.WriteLine("PushChangeSet: adding " + changeSet);
|
Debug.WriteLine("PushChangeSet: adding " + changeSet);
|
||||||
|
|
||||||
// Remove all of the "redo" entries from the current position to the end.
|
// Remove all of the "redo" entries from the current position to the end.
|
||||||
@ -1850,6 +1858,9 @@ namespace SourceGen {
|
|||||||
public UndoableChange.ReanalysisScope ApplyChanges(ChangeSet cs, bool backward,
|
public UndoableChange.ReanalysisScope ApplyChanges(ChangeSet cs, bool backward,
|
||||||
out RangeSet affectedOffsets) {
|
out RangeSet affectedOffsets) {
|
||||||
affectedOffsets = new RangeSet();
|
affectedOffsets = new RangeSet();
|
||||||
|
if (IsReadOnly) {
|
||||||
|
return UndoableChange.ReanalysisScope.None;
|
||||||
|
}
|
||||||
|
|
||||||
UndoableChange.ReanalysisScope needReanalysis = UndoableChange.ReanalysisScope.None;
|
UndoableChange.ReanalysisScope needReanalysis = UndoableChange.ReanalysisScope.None;
|
||||||
|
|
||||||
|
@ -626,9 +626,7 @@ namespace SourceGen {
|
|||||||
private void UpdateTitle() {
|
private void UpdateTitle() {
|
||||||
// Update main window title.
|
// Update main window title.
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.Append(Res.Strings.TITLE_BASE);
|
|
||||||
if (mProject != null) {
|
if (mProject != null) {
|
||||||
sb.Append(" - ");
|
|
||||||
if (string.IsNullOrEmpty(mProjectPathName)) {
|
if (string.IsNullOrEmpty(mProjectPathName)) {
|
||||||
sb.Append(Res.Strings.TITLE_NEW_PROJECT);
|
sb.Append(Res.Strings.TITLE_NEW_PROJECT);
|
||||||
} else {
|
} else {
|
||||||
@ -639,7 +637,14 @@ namespace SourceGen {
|
|||||||
sb.Append(" ");
|
sb.Append(" ");
|
||||||
sb.Append(Res.Strings.TITLE_MODIFIED);
|
sb.Append(Res.Strings.TITLE_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mProject.IsReadOnly) {
|
||||||
|
sb.Append(" ");
|
||||||
|
sb.Append(Res.Strings.TITLE_READ_ONLY);
|
||||||
|
}
|
||||||
|
sb.Append(" - ");
|
||||||
}
|
}
|
||||||
|
sb.Append(Res.Strings.TITLE_BASE);
|
||||||
mMainWin.Title = sb.ToString();
|
mMainWin.Title = sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,6 +1087,8 @@ namespace SourceGen {
|
|||||||
if (ok != true) {
|
if (ok != true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newProject.IsReadOnly = dlg.WantReadOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
mProject = newProject;
|
mProject = newProject;
|
||||||
@ -1175,6 +1182,7 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True on success, false if the save attempt failed or was canceled.</returns>
|
/// <returns>True on success, false if the save attempt failed or was canceled.</returns>
|
||||||
public bool SaveProjectAs() {
|
public bool SaveProjectAs() {
|
||||||
|
Debug.Assert(!mProject.IsReadOnly);
|
||||||
SaveFileDialog fileDlg = new SaveFileDialog() {
|
SaveFileDialog fileDlg = new SaveFileDialog() {
|
||||||
Filter = ProjectFile.FILENAME_FILTER + "|" + Res.Strings.FILE_FILTER_ALL,
|
Filter = ProjectFile.FILENAME_FILTER + "|" + Res.Strings.FILE_FILTER_ALL,
|
||||||
FilterIndex = 1,
|
FilterIndex = 1,
|
||||||
@ -1205,6 +1213,7 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True on success, false if the save attempt failed.</returns>
|
/// <returns>True on success, false if the save attempt failed.</returns>
|
||||||
public bool SaveProject() {
|
public bool SaveProject() {
|
||||||
|
Debug.Assert(!mProject.IsReadOnly);
|
||||||
if (string.IsNullOrEmpty(mProjectPathName)) {
|
if (string.IsNullOrEmpty(mProjectPathName)) {
|
||||||
return SaveProjectAs();
|
return SaveProjectAs();
|
||||||
}
|
}
|
||||||
@ -1317,8 +1326,11 @@ namespace SourceGen {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsProjectOpen() {
|
public bool IsProjectOpen {
|
||||||
return mProject != null;
|
get { return mProject != null; }
|
||||||
|
}
|
||||||
|
public bool IsProjectReadOnly {
|
||||||
|
get { return mProject != null && mProject.IsReadOnly; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AssembleProject() {
|
public void AssembleProject() {
|
||||||
|
@ -53,7 +53,7 @@ limitations under the License.
|
|||||||
<system:String x:Key="str_ErrBadSymbolSt">Unknown Source or Type in symbol</system:String>
|
<system:String x:Key="str_ErrBadSymbolSt">Unknown Source or Type in symbol</system:String>
|
||||||
<system:String x:Key="str_ErrBadSymrefPart">Bad symbol reference part</system:String>
|
<system:String x:Key="str_ErrBadSymrefPart">Bad symbol reference part</system:String>
|
||||||
<system:String x:Key="str_ErrBadTypeHint">Type hint not recognized</system:String>
|
<system:String x:Key="str_ErrBadTypeHint">Type hint not recognized</system:String>
|
||||||
<system:String x:Key="str_ErrDuplicateLabelFmt">Removing duplicate label '{0}' (offset +{1:x6})</system:String>
|
<system:String x:Key="str_ErrDuplicateLabelFmt">Removed duplicate label '{0}' (offset +{1:x6})</system:String>
|
||||||
<system:String x:Key="str_ErrFileCopyFailedFmt">Failed copying {0} to {1}: {2}.</system:String>
|
<system:String x:Key="str_ErrFileCopyFailedFmt">Failed copying {0} to {1}: {2}.</system:String>
|
||||||
<system:String x:Key="str_ErrFileExistsNotDirFmt">The file {0} exists, but is not a directory.</system:String>
|
<system:String x:Key="str_ErrFileExistsNotDirFmt">The file {0} exists, but is not a directory.</system:String>
|
||||||
<system:String x:Key="str_ErrFileGenericCaption">File Error</system:String>
|
<system:String x:Key="str_ErrFileGenericCaption">File Error</system:String>
|
||||||
@ -164,5 +164,6 @@ limitations under the License.
|
|||||||
<system:String x:Key="str_TitleBase">6502bench SourceGen</system:String>
|
<system:String x:Key="str_TitleBase">6502bench SourceGen</system:String>
|
||||||
<system:String x:Key="str_TitleModified">(save needed)</system:String>
|
<system:String x:Key="str_TitleModified">(save needed)</system:String>
|
||||||
<system:String x:Key="str_TitleNewProject">[new project]</system:String>
|
<system:String x:Key="str_TitleNewProject">[new project]</system:String>
|
||||||
|
<system:String x:Key="str_TitleReadOnly">*READ-ONLY*</system:String>
|
||||||
<system:String x:Key="str_Unset">[unset]</system:String>
|
<system:String x:Key="str_Unset">[unset]</system:String>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
@ -309,6 +309,8 @@ namespace SourceGen.Res {
|
|||||||
(string)Application.Current.FindResource("str_TitleModified");
|
(string)Application.Current.FindResource("str_TitleModified");
|
||||||
public static string TITLE_NEW_PROJECT =
|
public static string TITLE_NEW_PROJECT =
|
||||||
(string)Application.Current.FindResource("str_TitleNewProject");
|
(string)Application.Current.FindResource("str_TitleNewProject");
|
||||||
|
public static string TITLE_READ_ONLY =
|
||||||
|
(string)Application.Current.FindResource("str_TitleReadOnly");
|
||||||
public static string UNSET =
|
public static string UNSET =
|
||||||
(string)Application.Current.FindResource("str_Unset");
|
(string)Application.Current.FindResource("str_Unset");
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,9 @@ shown. If it's something simple, like a missing .sym65 or extension
|
|||||||
script file, you'll be notified. If it's something more complicated,
|
script file, you'll be notified. If it's something more complicated,
|
||||||
e.g. the project has a comment on an offset that doesn't exist, you
|
e.g. the project has a comment on an offset that doesn't exist, you
|
||||||
will be warned that the problematic data has been deleted, and will be
|
will be warned that the problematic data has been deleted, and will be
|
||||||
lost if the project is saved. You will also be given the opportunity
|
lost if the project is saved. By default, such a project will be opened
|
||||||
to cancel the loading of the project.</p>
|
in read-only mode, though you can override this in the dialog. You will
|
||||||
|
also be given the opportunity to simply cancel loading the project.</p>
|
||||||
|
|
||||||
<p>The locations of the last few projects you've worked with are saved
|
<p>The locations of the last few projects you've worked with are saved
|
||||||
in the application settings. You can access them from
|
in the application settings. You can access them from
|
||||||
|
@ -264,9 +264,9 @@ limitations under the License.
|
|||||||
<CommandBinding Command="{StaticResource RedoCmd}"
|
<CommandBinding Command="{StaticResource RedoCmd}"
|
||||||
CanExecute="CanRedo" Executed="RedoCmd_Executed"/>
|
CanExecute="CanRedo" Executed="RedoCmd_Executed"/>
|
||||||
<CommandBinding Command="Save"
|
<CommandBinding Command="Save"
|
||||||
CanExecute="IsProjectOpen" Executed="SaveCmd_Executed"/>
|
CanExecute="CanSaveProject" Executed="SaveCmd_Executed"/>
|
||||||
<CommandBinding Command="SaveAs"
|
<CommandBinding Command="SaveAs"
|
||||||
CanExecute="IsProjectOpen" Executed="SaveAsCmd_Executed"/>
|
CanExecute="CanSaveProject" Executed="SaveAsCmd_Executed"/>
|
||||||
<!-- ListView has a built-in Ctrl+A handler; this only fires when codeListView is not in focus -->
|
<!-- ListView has a built-in Ctrl+A handler; this only fires when codeListView is not in focus -->
|
||||||
<CommandBinding Command="{StaticResource SelectAllCmd}"
|
<CommandBinding Command="{StaticResource SelectAllCmd}"
|
||||||
CanExecute="IsProjectOpen" Executed="SelectAllCmd_Executed"/>
|
CanExecute="IsProjectOpen" Executed="SelectAllCmd_Executed"/>
|
||||||
|
@ -934,7 +934,7 @@ namespace SourceGen.WpfGui {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private bool IsProjectOpen() {
|
private bool IsProjectOpen() {
|
||||||
return mMainCtrl != null && mMainCtrl.IsProjectOpen();
|
return mMainCtrl != null && mMainCtrl.IsProjectOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1033,6 +1033,11 @@ namespace SourceGen.WpfGui {
|
|||||||
(counts.mCodeHints != 0 || counts.mDataHints != 0 || counts.mInlineDataHints != 0);
|
(counts.mCodeHints != 0 || counts.mDataHints != 0 || counts.mInlineDataHints != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CanSaveProject(object sender, CanExecuteRoutedEventArgs e) {
|
||||||
|
e.CanExecute = mMainCtrl != null && mMainCtrl.IsProjectOpen &&
|
||||||
|
!mMainCtrl.IsProjectReadOnly;
|
||||||
|
}
|
||||||
|
|
||||||
private void CanToggleSingleByteFormat(object sender, CanExecuteRoutedEventArgs e) {
|
private void CanToggleSingleByteFormat(object sender, CanExecuteRoutedEventArgs e) {
|
||||||
e.CanExecute = IsProjectOpen() && mMainCtrl.CanToggleSingleByteFormat();
|
e.CanExecute = IsProjectOpen() && mMainCtrl.CanToggleSingleByteFormat();
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,23 @@ limitations under the License.
|
|||||||
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
|
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
|
||||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
|
||||||
Loaded="ProjectLoadIssues_Loaded">
|
Loaded="ProjectLoadIssues_Loaded">
|
||||||
|
|
||||||
|
<Window.Resources>
|
||||||
|
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
<DockPanel LastChildFill="False" Margin="8">
|
<DockPanel LastChildFill="False" Margin="8">
|
||||||
<TextBlock DockPanel.Dock="Top">Problems were detected while loading the project file:</TextBlock>
|
<TextBlock DockPanel.Dock="Top">Problems were detected while loading the project file:</TextBlock>
|
||||||
<TextBox Name="messageTextBox" DockPanel.Dock="Top" Margin="0,8,0,0"
|
<TextBox Name="messageTextBox" DockPanel.Dock="Top" Margin="0,8,0,0"
|
||||||
Width="540" Height="110" IsReadOnly="True" TextWrapping="Wrap" Text=""
|
Width="540" Height="110" IsReadOnly="True" TextWrapping="Wrap" Text=""
|
||||||
VerticalScrollBarVisibility="Auto"/>
|
VerticalScrollBarVisibility="Auto"/>
|
||||||
<TextBlock Name="invalidDiscardLabel" DockPanel.Dock="Top" Margin="0,8,0,0" Foreground="Red">
|
<TextBlock Name="invalidDiscardLabel" DockPanel.Dock="Top" Margin="0,8,0,0" Foreground="Red"
|
||||||
|
Visibility="{Binding ShowItemWarning, Converter={StaticResource BoolToVis}}">
|
||||||
Invalid data items will be discarded when you save the project.
|
Invalid data items will be discarded when you save the project.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
<CheckBox Content="Open project in read-only mode" DockPanel.Dock="Top" Margin="0,4,0,0"
|
||||||
|
IsChecked="{Binding WantReadOnly}"
|
||||||
|
Visibility="{Binding ShowSaveWarning, Converter={StaticResource BoolToVis}}"/>
|
||||||
<StackPanel DockPanel.Dock="Bottom" Margin="0,8,0,0"
|
<StackPanel DockPanel.Dock="Bottom" Margin="0,8,0,0"
|
||||||
Orientation="Horizontal" HorizontalAlignment="Right">
|
Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
<Button Name="okButton" Width="70" Content="Continue" IsDefault="True" Click="OkButton_Click"/>
|
<Button Name="okButton" Width="70" Content="Continue" IsDefault="True" Click="OkButton_Click"/>
|
||||||
|
@ -14,13 +14,28 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace SourceGen.WpfGui {
|
namespace SourceGen.WpfGui {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Display errors and warnings generated while attempting to open a project.
|
/// Display errors and warnings generated while attempting to open a project.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ProjectLoadIssues : Window {
|
public partial class ProjectLoadIssues : Window, INotifyPropertyChanged {
|
||||||
|
public bool WantReadOnly {
|
||||||
|
get { return mWantReadOnly; }
|
||||||
|
set { mWantReadOnly = value; OnPropertyChanged(); }
|
||||||
|
}
|
||||||
|
private bool mWantReadOnly;
|
||||||
|
|
||||||
|
public bool ShowSaveWarning {
|
||||||
|
get { return mShowItemWarning; }
|
||||||
|
set { mShowItemWarning = value; OnPropertyChanged(); }
|
||||||
|
}
|
||||||
|
private bool mShowItemWarning;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multi-line message for text box.
|
/// Multi-line message for text box.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -35,10 +50,17 @@ namespace SourceGen.WpfGui {
|
|||||||
Unknown = 0, Continue, Cancel, ContinueOrCancel
|
Unknown = 0, Continue, Cancel, ContinueOrCancel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// INotifyPropertyChanged implementation
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ProjectLoadIssues(Window owner, string msgs, Buttons allowedButtons) {
|
public ProjectLoadIssues(Window owner, string msgs, Buttons allowedButtons) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
|
DataContext = this;
|
||||||
|
|
||||||
mMessages = msgs;
|
mMessages = msgs;
|
||||||
mAllowedButtons = allowedButtons;
|
mAllowedButtons = allowedButtons;
|
||||||
@ -52,14 +74,18 @@ namespace SourceGen.WpfGui {
|
|||||||
okButton.IsEnabled = false;
|
okButton.IsEnabled = false;
|
||||||
|
|
||||||
// No point warning them about invalid data if they can't continue.
|
// No point warning them about invalid data if they can't continue.
|
||||||
invalidDiscardLabel.Visibility = Visibility.Hidden;
|
ShowSaveWarning = false;
|
||||||
}
|
} else if (mAllowedButtons == Buttons.Continue) {
|
||||||
if (mAllowedButtons == Buttons.Continue) {
|
|
||||||
// Cancel not allowed.
|
// Cancel not allowed.
|
||||||
cancelButton.IsEnabled = false;
|
cancelButton.IsEnabled = false;
|
||||||
|
|
||||||
// They're stuck with the problem.
|
// Problem is outside the scope of the project (e.g. bad platform symbol file),
|
||||||
invalidDiscardLabel.Visibility = Visibility.Hidden;
|
// so saving the project won't change anything.
|
||||||
|
ShowSaveWarning = false;
|
||||||
|
} else {
|
||||||
|
Debug.Assert(mAllowedButtons == Buttons.ContinueOrCancel);
|
||||||
|
ShowSaveWarning = true;
|
||||||
|
WantReadOnly = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user