mirror of
https://github.com/fadden/6502bench.git
synced 2024-11-26 06:49:19 +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:
parent
7d2fe51b41
commit
6b29ce98f9
@ -66,7 +66,7 @@ namespace SourceGenWPF {
|
||||
/// <summary>
|
||||
/// List of recently-opened projects.
|
||||
/// </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;
|
||||
|
||||
/// <summary>
|
||||
@ -195,8 +195,8 @@ namespace SourceGenWPF {
|
||||
|
||||
#if false
|
||||
UpdateMenuItemsAndTitle();
|
||||
UpdateRecentLinks();
|
||||
#endif
|
||||
mMainWin.UpdateRecentLinks();
|
||||
|
||||
ProcessCommandLine();
|
||||
}
|
||||
@ -405,10 +405,12 @@ namespace SourceGenWPF {
|
||||
Debug.WriteLine("Font convert failed: " + ex.Message);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unpack the recent-project list.
|
||||
UnpackRecentProjectList();
|
||||
|
||||
#if false
|
||||
// Enable the DEBUG menu if configured.
|
||||
bool showDebugMenu = AppSettings.Global.GetBool(AppSettings.DEBUG_MENU_ENABLED, false);
|
||||
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>
|
||||
/// 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.
|
||||
@ -438,32 +458,30 @@ namespace SourceGenWPF {
|
||||
// without having saved it.
|
||||
return;
|
||||
}
|
||||
int index = mRecentProjectPaths.IndexOf(projectPath);
|
||||
int index = RecentProjectPaths.IndexOf(projectPath);
|
||||
if (index == 0) {
|
||||
// Already in the list, nothing changes. No need to update anything else.
|
||||
return;
|
||||
}
|
||||
if (index > 0) {
|
||||
mRecentProjectPaths.RemoveAt(index);
|
||||
RecentProjectPaths.RemoveAt(index);
|
||||
}
|
||||
mRecentProjectPaths.Insert(0, projectPath);
|
||||
RecentProjectPaths.Insert(0, projectPath);
|
||||
|
||||
// Trim the list to the max allowed.
|
||||
while (mRecentProjectPaths.Count > MAX_RECENT_PROJECTS) {
|
||||
while (RecentProjectPaths.Count > MAX_RECENT_PROJECTS) {
|
||||
Debug.WriteLine("Recent projects: dropping " +
|
||||
mRecentProjectPaths[MAX_RECENT_PROJECTS]);
|
||||
mRecentProjectPaths.RemoveAt(MAX_RECENT_PROJECTS);
|
||||
RecentProjectPaths[MAX_RECENT_PROJECTS]);
|
||||
RecentProjectPaths.RemoveAt(MAX_RECENT_PROJECTS);
|
||||
}
|
||||
|
||||
// Store updated list in app settings. JSON-in-JSON is ugly and inefficient,
|
||||
// but it'll do for now.
|
||||
JavaScriptSerializer ser = new JavaScriptSerializer();
|
||||
string cereal = ser.Serialize(mRecentProjectPaths);
|
||||
string cereal = ser.Serialize(RecentProjectPaths);
|
||||
AppSettings.Global.SetString(AppSettings.PRVW_RECENT_PROJECT_LIST, cereal);
|
||||
|
||||
#if false
|
||||
UpdateRecentLinks();
|
||||
#endif
|
||||
mMainWin.UpdateRecentLinks();
|
||||
}
|
||||
|
||||
#endregion Init and settings
|
||||
@ -761,12 +779,7 @@ namespace SourceGenWPF {
|
||||
if (!CloseProject()) {
|
||||
return;
|
||||
}
|
||||
//DoOpenFile(mRecentProjectPaths[projIndex]);
|
||||
if (projIndex == 0) {
|
||||
DoOpenFile(@"C:\Src\6502bench\EXTRA\ZIPPY#ff2000.dis65");
|
||||
} else {
|
||||
DoOpenFile(@"C:\Src\6502bench\EXTRA\CRYLLAN.MISSION#b30100.dis65");
|
||||
}
|
||||
DoOpenFile(RecentProjectPaths[projIndex]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1027,7 +1040,7 @@ namespace SourceGenWPF {
|
||||
/// </summary>
|
||||
/// <returns>True if the project was closed, false if the user chose to cancel.</returns>
|
||||
public bool CloseProject() {
|
||||
Debug.WriteLine("ProjectView.DoClose() - dirty=" +
|
||||
Debug.WriteLine("CloseProject() - dirty=" +
|
||||
(mProject == null ? "N/A" : mProject.IsDirty.ToString()));
|
||||
if (mProject != null && mProject.IsDirty) {
|
||||
DiscardChanges dlg = new DiscardChanges(mMainWin);
|
||||
@ -1065,13 +1078,11 @@ namespace SourceGenWPF {
|
||||
mDataPathName = null;
|
||||
mProjectPathName = null;
|
||||
mTargetHighlightIndex = -1;
|
||||
#if false
|
||||
mSymbolSubset = new SymbolTableSubset(new SymbolTable());
|
||||
#endif
|
||||
|
||||
// Clear this to release the memory.
|
||||
mMainWin.CodeDisplayList.Clear();
|
||||
|
||||
mMainWin.InfoPanelContents = String.Empty;
|
||||
mMainWin.InfoPanelContents = string.Empty;
|
||||
mMainWin.ShowCodeListView = false;
|
||||
|
||||
mGenerationLog = null;
|
||||
|
@ -73,6 +73,7 @@ limitations under the License.
|
||||
<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_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_RuntimeDirNotFoundCaption">RuntimeData Not Found</system:String>
|
||||
<system:String x:Key="str_SetupSystemSummaryFmt">{1} CPU @ {2} MHz</system:String>
|
||||
|
@ -126,6 +126,8 @@ namespace SourceGenWPF.Res {
|
||||
(string)Application.Current.FindResource("str_ProjectFieldUserLabel");
|
||||
public static string PROJECT_FROM_NEWER_APP =
|
||||
(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 =
|
||||
(string)Application.Current.FindResource("str_RuntimeDirNotFound");
|
||||
public static string RUNTIME_DIR_NOT_FOUND_CAPTION =
|
||||
|
@ -123,7 +123,7 @@ limitations under the License.
|
||||
Executed="OpenCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource RemoveHintsCmd}"
|
||||
CanExecute="CanRemoveHints" Executed="RemoveHintsCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource RecentProjectCmd}"
|
||||
<CommandBinding Command="{StaticResource RecentProjectCmd}" x:Name="recentProjectCmd"
|
||||
Executed="RecentProjectCmd_Executed"/>
|
||||
<CommandBinding Command="{StaticResource RedoCmd}"
|
||||
CanExecute="CanRedo" Executed="RedoCmd_Executed"/>
|
||||
@ -150,7 +150,7 @@ limitations under the License.
|
||||
<MenuItem Command="{StaticResource AssembleCmd}"/>
|
||||
<MenuItem Command="Print"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Recent Projects">
|
||||
<MenuItem Name="recentProjectsMenu" Header="Recent Projects" SubmenuOpened="RecentProjectsMenu_SubmenuOpened">
|
||||
<MenuItem Header="(none)"/>
|
||||
</MenuItem>
|
||||
<Separator/>
|
||||
@ -173,7 +173,7 @@ limitations under the License.
|
||||
<Separator/>
|
||||
<MenuItem Header="Settings..."/>
|
||||
</MenuItem>
|
||||
<MenuItem Name="ActionsMenu" Header="_Actions">
|
||||
<MenuItem Name="actionsMenu" Header="_Actions">
|
||||
<MenuItem Command="{StaticResource EditAddressCmd}"/>
|
||||
<MenuItem Command="{StaticResource EditStatusFlagsCmd}"/>
|
||||
<MenuItem Header="Edit Label..."/>
|
||||
@ -351,14 +351,27 @@ limitations under the License.
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" HorizontalAlignment="Left">
|
||||
<Button Content="Start new project" Width="200" Height="50" Margin="10,30,10,10"/>
|
||||
<Button Content="Open existing project" Width="200" Height="50" Margin="10"/>
|
||||
<Button Content="Recent project #1" Width="200" Height="50" Margin="10"
|
||||
CommandParameter="0"
|
||||
Command="{DynamicResource RecentProjectCmd}"/>
|
||||
<Button Content="Recent project #2" Width="200" Height="50" Margin="10"
|
||||
CommandParameter="1"
|
||||
Command="{DynamicResource RecentProjectCmd}"/>
|
||||
<Button Content="Start new project" Width="240" Height="50" Margin="10,30,10,10"/>
|
||||
<Button Content="Open existing project" Width="240" Height="50" Margin="10"
|
||||
Command="{StaticResource OpenCmd}"/>
|
||||
<Button Name="recentProjectButton1" Width="240" Height="50" Margin="10"
|
||||
Command="{DynamicResource RecentProjectCmd}" CommandParameter="0">
|
||||
<Button.Content>
|
||||
<StackPanel>
|
||||
<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>
|
||||
</Grid>
|
||||
|
||||
|
@ -19,6 +19,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
@ -142,20 +143,19 @@ namespace SourceGenWPF.WpfGui {
|
||||
}
|
||||
|
||||
private void CreateCodeListContextMenu() {
|
||||
// Find Actions menu.
|
||||
ItemCollection mainItems = this.appMenu.Items;
|
||||
MenuItem actionsMenu = null;
|
||||
foreach (object obj in mainItems) {
|
||||
if (!(obj is MenuItem)) {
|
||||
continue;
|
||||
}
|
||||
MenuItem mi = (MenuItem)obj;
|
||||
if (mi.Name.Equals("ActionsMenu")) {
|
||||
actionsMenu = mi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Debug.Assert(actionsMenu != null);
|
||||
//// Find Actions menu.
|
||||
//ItemCollection mainItems = this.appMenu.Items;
|
||||
//foreach (object obj in mainItems) {
|
||||
// if (!(obj is MenuItem)) {
|
||||
// continue;
|
||||
// }
|
||||
// MenuItem mi = (MenuItem)obj;
|
||||
// if (mi.Name.Equals("actionsMenu")) {
|
||||
// actionsMenu = mi;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//Debug.Assert(actionsMenu != null);
|
||||
|
||||
// Clone the Actions menu into the codeListView context menu.
|
||||
ContextMenu ctxt = this.codeListView.ContextMenu;
|
||||
@ -335,6 +335,8 @@ namespace SourceGenWPF.WpfGui {
|
||||
|
||||
#endregion Window placement
|
||||
|
||||
#region Column widths
|
||||
|
||||
/// <summary>
|
||||
/// Grabs the widths of the columns of the various grids and saves them in the
|
||||
/// global AppSettings.
|
||||
@ -416,32 +418,7 @@ namespace SourceGenWPF.WpfGui {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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);
|
||||
}
|
||||
#endregion Column widths
|
||||
|
||||
|
||||
#region Selection management
|
||||
@ -658,6 +635,7 @@ namespace SourceGenWPF.WpfGui {
|
||||
|
||||
#endregion Selection management
|
||||
|
||||
|
||||
#region Can-execute handlers
|
||||
|
||||
/// <summary>
|
||||
@ -829,8 +807,15 @@ namespace SourceGenWPF.WpfGui {
|
||||
}
|
||||
|
||||
private void RecentProjectCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||
if (!int.TryParse((string)e.Parameter, out int recentIndex) ||
|
||||
recentIndex < 0 || recentIndex >= MainController.MAX_RECENT_PROJECTS) {
|
||||
int recentIndex;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -844,6 +829,69 @@ namespace SourceGenWPF.WpfGui {
|
||||
|
||||
#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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user