1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-09-29 16:54:50 +00:00

Implement "recents" feature

Add the list of recent projects to File > Recent Projects when the
sub-menu opens.  Make the buttons on the launch panel work correctly.
This commit is contained in:
Andy McFadden 2019-06-22 14:41:09 -07:00
parent 7d2fe51b41
commit 6b29ce98f9
5 changed files with 151 additions and 76 deletions

View File

@ -66,7 +66,7 @@ namespace SourceGenWPF {
/// <summary> /// <summary>
/// List of recently-opened projects. /// List of recently-opened projects.
/// </summary> /// </summary>
private List<string> mRecentProjectPaths = new List<string>(MAX_RECENT_PROJECTS); public List<string> RecentProjectPaths = new List<string>(MAX_RECENT_PROJECTS);
public const int MAX_RECENT_PROJECTS = 6; public const int MAX_RECENT_PROJECTS = 6;
/// <summary> /// <summary>
@ -195,8 +195,8 @@ namespace SourceGenWPF {
#if false #if false
UpdateMenuItemsAndTitle(); UpdateMenuItemsAndTitle();
UpdateRecentLinks();
#endif #endif
mMainWin.UpdateRecentLinks();
ProcessCommandLine(); ProcessCommandLine();
} }
@ -405,10 +405,12 @@ namespace SourceGenWPF {
Debug.WriteLine("Font convert failed: " + ex.Message); Debug.WriteLine("Font convert failed: " + ex.Message);
} }
} }
#endif
// Unpack the recent-project list. // Unpack the recent-project list.
UnpackRecentProjectList(); UnpackRecentProjectList();
#if false
// Enable the DEBUG menu if configured. // Enable the DEBUG menu if configured.
bool showDebugMenu = AppSettings.Global.GetBool(AppSettings.DEBUG_MENU_ENABLED, false); bool showDebugMenu = AppSettings.Global.GetBool(AppSettings.DEBUG_MENU_ENABLED, false);
if (dEBUGToolStripMenuItem.Visible != showDebugMenu) { if (dEBUGToolStripMenuItem.Visible != showDebugMenu) {
@ -427,6 +429,24 @@ namespace SourceGenWPF {
} }
} }
private void UnpackRecentProjectList() {
RecentProjectPaths.Clear();
string cereal = AppSettings.Global.GetString(
AppSettings.PRVW_RECENT_PROJECT_LIST, null);
if (string.IsNullOrEmpty(cereal)) {
return;
}
try {
JavaScriptSerializer ser = new JavaScriptSerializer();
RecentProjectPaths = ser.Deserialize<List<string>>(cereal);
} catch (Exception ex) {
Debug.WriteLine("Failed deserializing recent projects: " + ex.Message);
return;
}
}
/// <summary> /// <summary>
/// Ensures that the named project is at the top of the list. If it's elsewhere /// Ensures that the named project is at the top of the list. If it's elsewhere
/// in the list, move it to the top. Excess items are removed. /// in the list, move it to the top. Excess items are removed.
@ -438,32 +458,30 @@ namespace SourceGenWPF {
// without having saved it. // without having saved it.
return; return;
} }
int index = mRecentProjectPaths.IndexOf(projectPath); int index = RecentProjectPaths.IndexOf(projectPath);
if (index == 0) { if (index == 0) {
// Already in the list, nothing changes. No need to update anything else. // Already in the list, nothing changes. No need to update anything else.
return; return;
} }
if (index > 0) { if (index > 0) {
mRecentProjectPaths.RemoveAt(index); RecentProjectPaths.RemoveAt(index);
} }
mRecentProjectPaths.Insert(0, projectPath); RecentProjectPaths.Insert(0, projectPath);
// Trim the list to the max allowed. // Trim the list to the max allowed.
while (mRecentProjectPaths.Count > MAX_RECENT_PROJECTS) { while (RecentProjectPaths.Count > MAX_RECENT_PROJECTS) {
Debug.WriteLine("Recent projects: dropping " + Debug.WriteLine("Recent projects: dropping " +
mRecentProjectPaths[MAX_RECENT_PROJECTS]); RecentProjectPaths[MAX_RECENT_PROJECTS]);
mRecentProjectPaths.RemoveAt(MAX_RECENT_PROJECTS); RecentProjectPaths.RemoveAt(MAX_RECENT_PROJECTS);
} }
// Store updated list in app settings. JSON-in-JSON is ugly and inefficient, // Store updated list in app settings. JSON-in-JSON is ugly and inefficient,
// but it'll do for now. // but it'll do for now.
JavaScriptSerializer ser = new JavaScriptSerializer(); JavaScriptSerializer ser = new JavaScriptSerializer();
string cereal = ser.Serialize(mRecentProjectPaths); string cereal = ser.Serialize(RecentProjectPaths);
AppSettings.Global.SetString(AppSettings.PRVW_RECENT_PROJECT_LIST, cereal); AppSettings.Global.SetString(AppSettings.PRVW_RECENT_PROJECT_LIST, cereal);
#if false mMainWin.UpdateRecentLinks();
UpdateRecentLinks();
#endif
} }
#endregion Init and settings #endregion Init and settings
@ -761,12 +779,7 @@ namespace SourceGenWPF {
if (!CloseProject()) { if (!CloseProject()) {
return; return;
} }
//DoOpenFile(mRecentProjectPaths[projIndex]); DoOpenFile(RecentProjectPaths[projIndex]);
if (projIndex == 0) {
DoOpenFile(@"C:\Src\6502bench\EXTRA\ZIPPY#ff2000.dis65");
} else {
DoOpenFile(@"C:\Src\6502bench\EXTRA\CRYLLAN.MISSION#b30100.dis65");
}
} }
/// <summary> /// <summary>
@ -1027,7 +1040,7 @@ namespace SourceGenWPF {
/// </summary> /// </summary>
/// <returns>True if the project was closed, false if the user chose to cancel.</returns> /// <returns>True if the project was closed, false if the user chose to cancel.</returns>
public bool CloseProject() { public bool CloseProject() {
Debug.WriteLine("ProjectView.DoClose() - dirty=" + Debug.WriteLine("CloseProject() - dirty=" +
(mProject == null ? "N/A" : mProject.IsDirty.ToString())); (mProject == null ? "N/A" : mProject.IsDirty.ToString()));
if (mProject != null && mProject.IsDirty) { if (mProject != null && mProject.IsDirty) {
DiscardChanges dlg = new DiscardChanges(mMainWin); DiscardChanges dlg = new DiscardChanges(mMainWin);
@ -1065,13 +1078,11 @@ namespace SourceGenWPF {
mDataPathName = null; mDataPathName = null;
mProjectPathName = null; mProjectPathName = null;
mTargetHighlightIndex = -1; mTargetHighlightIndex = -1;
#if false
mSymbolSubset = new SymbolTableSubset(new SymbolTable());
#endif
// Clear this to release the memory. // Clear this to release the memory.
mMainWin.CodeDisplayList.Clear(); mMainWin.CodeDisplayList.Clear();
mMainWin.InfoPanelContents = String.Empty; mMainWin.InfoPanelContents = string.Empty;
mMainWin.ShowCodeListView = false; mMainWin.ShowCodeListView = false;
mGenerationLog = null; mGenerationLog = null;

View File

@ -73,6 +73,7 @@ limitations under the License.
<system:String x:Key="str_ProjectFieldTypeHint">type hint</system:String> <system:String x:Key="str_ProjectFieldTypeHint">type hint</system:String>
<system:String x:Key="str_ProjectFieldUserLabel">user-defined label</system:String> <system:String x:Key="str_ProjectFieldUserLabel">user-defined label</system:String>
<system:String x:Key="str_ProjectFromNewerApp">This project was created by a newer version of SourceGen. It may contain data that will be lost if the project is edited.</system:String> <system:String x:Key="str_ProjectFromNewerApp">This project was created by a newer version of SourceGen. It may contain data that will be lost if the project is edited.</system:String>
<!--<system:String x:Key="str_RecentProjectLinkFmt">#{0}: {1}</system:String>-->
<system:String x:Key="str_RuntimeDirNotFound">The RuntimeData directory was not found. It should be in the same directory as the executable.</system:String> <system:String x:Key="str_RuntimeDirNotFound">The RuntimeData directory was not found. It should be in the same directory as the executable.</system:String>
<system:String x:Key="str_RuntimeDirNotFoundCaption">RuntimeData Not Found</system:String> <system:String x:Key="str_RuntimeDirNotFoundCaption">RuntimeData Not Found</system:String>
<system:String x:Key="str_SetupSystemSummaryFmt">{1} CPU @ {2} MHz</system:String> <system:String x:Key="str_SetupSystemSummaryFmt">{1} CPU @ {2} MHz</system:String>

View File

@ -126,6 +126,8 @@ namespace SourceGenWPF.Res {
(string)Application.Current.FindResource("str_ProjectFieldUserLabel"); (string)Application.Current.FindResource("str_ProjectFieldUserLabel");
public static string PROJECT_FROM_NEWER_APP = public static string PROJECT_FROM_NEWER_APP =
(string)Application.Current.FindResource("str_ProjectFromNewerApp"); (string)Application.Current.FindResource("str_ProjectFromNewerApp");
//public static string RECENT_PROJECT_LINK_FMT =
// (string)Application.Current.FindResource("str_RecentProjectLinkFmt");
public static string RUNTIME_DIR_NOT_FOUND = public static string RUNTIME_DIR_NOT_FOUND =
(string)Application.Current.FindResource("str_RuntimeDirNotFound"); (string)Application.Current.FindResource("str_RuntimeDirNotFound");
public static string RUNTIME_DIR_NOT_FOUND_CAPTION = public static string RUNTIME_DIR_NOT_FOUND_CAPTION =

View File

@ -123,7 +123,7 @@ limitations under the License.
Executed="OpenCmd_Executed"/> Executed="OpenCmd_Executed"/>
<CommandBinding Command="{StaticResource RemoveHintsCmd}" <CommandBinding Command="{StaticResource RemoveHintsCmd}"
CanExecute="CanRemoveHints" Executed="RemoveHintsCmd_Executed"/> CanExecute="CanRemoveHints" Executed="RemoveHintsCmd_Executed"/>
<CommandBinding Command="{StaticResource RecentProjectCmd}" <CommandBinding Command="{StaticResource RecentProjectCmd}" x:Name="recentProjectCmd"
Executed="RecentProjectCmd_Executed"/> Executed="RecentProjectCmd_Executed"/>
<CommandBinding Command="{StaticResource RedoCmd}" <CommandBinding Command="{StaticResource RedoCmd}"
CanExecute="CanRedo" Executed="RedoCmd_Executed"/> CanExecute="CanRedo" Executed="RedoCmd_Executed"/>
@ -150,7 +150,7 @@ limitations under the License.
<MenuItem Command="{StaticResource AssembleCmd}"/> <MenuItem Command="{StaticResource AssembleCmd}"/>
<MenuItem Command="Print"/> <MenuItem Command="Print"/>
<Separator/> <Separator/>
<MenuItem Header="Recent Projects"> <MenuItem Name="recentProjectsMenu" Header="Recent Projects" SubmenuOpened="RecentProjectsMenu_SubmenuOpened">
<MenuItem Header="(none)"/> <MenuItem Header="(none)"/>
</MenuItem> </MenuItem>
<Separator/> <Separator/>
@ -173,7 +173,7 @@ limitations under the License.
<Separator/> <Separator/>
<MenuItem Header="Settings..."/> <MenuItem Header="Settings..."/>
</MenuItem> </MenuItem>
<MenuItem Name="ActionsMenu" Header="_Actions"> <MenuItem Name="actionsMenu" Header="_Actions">
<MenuItem Command="{StaticResource EditAddressCmd}"/> <MenuItem Command="{StaticResource EditAddressCmd}"/>
<MenuItem Command="{StaticResource EditStatusFlagsCmd}"/> <MenuItem Command="{StaticResource EditStatusFlagsCmd}"/>
<MenuItem Header="Edit Label..."/> <MenuItem Header="Edit Label..."/>
@ -351,14 +351,27 @@ limitations under the License.
</StackPanel> </StackPanel>
<StackPanel Grid.Row="1" HorizontalAlignment="Left"> <StackPanel Grid.Row="1" HorizontalAlignment="Left">
<Button Content="Start new project" Width="200" Height="50" Margin="10,30,10,10"/> <Button Content="Start new project" Width="240" Height="50" Margin="10,30,10,10"/>
<Button Content="Open existing project" Width="200" Height="50" Margin="10"/> <Button Content="Open existing project" Width="240" Height="50" Margin="10"
<Button Content="Recent project #1" Width="200" Height="50" Margin="10" Command="{StaticResource OpenCmd}"/>
CommandParameter="0" <Button Name="recentProjectButton1" Width="240" Height="50" Margin="10"
Command="{DynamicResource RecentProjectCmd}"/> Command="{DynamicResource RecentProjectCmd}" CommandParameter="0">
<Button Content="Recent project #2" Width="200" Height="50" Margin="10" <Button.Content>
CommandParameter="1" <StackPanel>
Command="{DynamicResource RecentProjectCmd}"/> <TextBlock HorizontalAlignment="Center">Recent project #1</TextBlock>
<TextBlock Name="recentProjectName1" HorizontalAlignment="Center">???</TextBlock>
</StackPanel>
</Button.Content>
</Button>
<Button Name="recentProjectButton2" Width="240" Height="50" Margin="10"
Command="{DynamicResource RecentProjectCmd}" CommandParameter="1">
<Button.Content>
<StackPanel>
<TextBlock HorizontalAlignment="Center">Recent project #2</TextBlock>
<TextBlock Name="recentProjectName2" HorizontalAlignment="Center">???</TextBlock>
</StackPanel>
</Button.Content>
</Button>
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@ -19,6 +19,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
@ -142,20 +143,19 @@ namespace SourceGenWPF.WpfGui {
} }
private void CreateCodeListContextMenu() { private void CreateCodeListContextMenu() {
// Find Actions menu. //// Find Actions menu.
ItemCollection mainItems = this.appMenu.Items; //ItemCollection mainItems = this.appMenu.Items;
MenuItem actionsMenu = null; //foreach (object obj in mainItems) {
foreach (object obj in mainItems) { // if (!(obj is MenuItem)) {
if (!(obj is MenuItem)) { // continue;
continue; // }
} // MenuItem mi = (MenuItem)obj;
MenuItem mi = (MenuItem)obj; // if (mi.Name.Equals("actionsMenu")) {
if (mi.Name.Equals("ActionsMenu")) { // actionsMenu = mi;
actionsMenu = mi; // break;
break; // }
} //}
} //Debug.Assert(actionsMenu != null);
Debug.Assert(actionsMenu != null);
// Clone the Actions menu into the codeListView context menu. // Clone the Actions menu into the codeListView context menu.
ContextMenu ctxt = this.codeListView.ContextMenu; ContextMenu ctxt = this.codeListView.ContextMenu;
@ -335,6 +335,8 @@ namespace SourceGenWPF.WpfGui {
#endregion Window placement #endregion Window placement
#region Column widths
/// <summary> /// <summary>
/// Grabs the widths of the columns of the various grids and saves them in the /// Grabs the widths of the columns of the various grids and saves them in the
/// global AppSettings. /// global AppSettings.
@ -416,32 +418,7 @@ namespace SourceGenWPF.WpfGui {
} }
} }
/// <summary> #endregion Column widths
/// Sets the focus on the code list.
/// </summary>
//public void CodeListView_Focus() {
// codeListView.Focus();
//}
/// <summary>
/// Handles a double-click on the code list. We have to figure out which row and
/// column were clicked, which is not easy in WPF.
/// </summary>
private void CodeListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
Debug.Assert(sender == codeListView);
ListViewItem lvi = codeListView.GetClickedItem(e);
if (lvi == null) {
return;
}
DisplayList.FormattedParts parts = (DisplayList.FormattedParts)lvi.Content;
int row = parts.ListIndex;
int col = codeListView.GetClickEventColumn(e);
if (col < 0) {
return;
}
mMainCtrl.HandleCodeListDoubleClick(row, col);
}
#region Selection management #region Selection management
@ -658,6 +635,7 @@ namespace SourceGenWPF.WpfGui {
#endregion Selection management #endregion Selection management
#region Can-execute handlers #region Can-execute handlers
/// <summary> /// <summary>
@ -829,8 +807,15 @@ namespace SourceGenWPF.WpfGui {
} }
private void RecentProjectCmd_Executed(object sender, ExecutedRoutedEventArgs e) { private void RecentProjectCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
if (!int.TryParse((string)e.Parameter, out int recentIndex) || int recentIndex;
recentIndex < 0 || recentIndex >= MainController.MAX_RECENT_PROJECTS) { if (e.Parameter is int) {
recentIndex = (int)e.Parameter;
} else if (e.Parameter is string) {
recentIndex = int.Parse((string)e.Parameter);
} else {
throw new Exception("Bad parameter: " + e.Parameter);
}
if (recentIndex < 0 || recentIndex >= MainController.MAX_RECENT_PROJECTS) {
throw new Exception("Bad parameter: " + e.Parameter); throw new Exception("Bad parameter: " + e.Parameter);
} }
@ -844,6 +829,69 @@ namespace SourceGenWPF.WpfGui {
#endregion Command handlers #endregion Command handlers
#region Misc
/// <summary>
/// Handles a double-click on the code list. We have to figure out which row and
/// column were clicked, which is not easy in WPF.
/// </summary>
private void CodeListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
Debug.Assert(sender == codeListView);
ListViewItem lvi = codeListView.GetClickedItem(e);
if (lvi == null) {
return;
}
DisplayList.FormattedParts parts = (DisplayList.FormattedParts)lvi.Content;
int row = parts.ListIndex;
int col = codeListView.GetClickEventColumn(e);
if (col < 0) {
return;
}
mMainCtrl.HandleCodeListDoubleClick(row, col);
}
private void RecentProjectsMenu_SubmenuOpened(object sender, RoutedEventArgs e) {
MenuItem recents = (MenuItem)sender;
recents.Items.Clear();
Debug.WriteLine("COUNT is " + mMainCtrl.RecentProjectPaths.Count);
if (mMainCtrl.RecentProjectPaths.Count == 0) {
MenuItem mi = new MenuItem();
mi.Header = "(none)";
recents.Items.Add(mi);
} else {
for (int i = 0; i < mMainCtrl.RecentProjectPaths.Count; i++) {
MenuItem mi = new MenuItem();
mi.Header = string.Format("{0}: {1}", i + 1, mMainCtrl.RecentProjectPaths[i]);
mi.Command = recentProjectCmd.Command;
mi.CommandParameter = i;
recents.Items.Add(mi);
}
}
}
public void UpdateRecentLinks() {
List<string> pathList = mMainCtrl.RecentProjectPaths;
if (pathList.Count >= 1) {
recentProjectName1.Text = Path.GetFileName(pathList[0]);
recentProjectButton1.Visibility = Visibility.Visible;
} else {
recentProjectName1.Text = string.Empty;
recentProjectButton1.Visibility = Visibility.Collapsed;
}
if (pathList.Count >= 2) {
recentProjectName2.Text = Path.GetFileName(pathList[1]);
recentProjectButton2.Visibility = Visibility.Visible;
} else {
recentProjectName2.Text = string.Empty;
recentProjectButton2.Visibility = Visibility.Collapsed;
}
}
#endregion Misc
#region References panel #region References panel