bookmark-manager-r4/MainForm.cs

1045 lines
31 KiB
C#

using BookmarkManager;
using bzit.bomg.Models;
using FizzyLauncher.Models;
using Newtonsoft.Json;
using RyzStudio.Windows.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FizzyLauncher
{
public partial class MainForm : Form
{
public enum AppMode
{
Clear = 0,
Open,
New
}
protected OptionsForm optionsForm = null;
protected FindForm findForm = null;
protected AppMode appMode = AppMode.Clear;
protected string sessionFilename = null;
protected string sessionPassword = null;
protected bool isBusy = false;
protected readonly string jsonfigFilename;
public MainForm()
{
InitializeComponent();
this.AutoScaleMode = AutoScaleMode.None;
this.StartPosition = FormStartPosition.WindowsDefaultLocation;
this.ClientSize = new System.Drawing.Size(300, 580);
//this.Visible = false;
jsonfigFilename = Path.ChangeExtension(Application.ExecutablePath, "jsonfig");
treeView1.RootContextMenu = rootContextMenu;
treeView1.FolderContextMenu = folderContextMenu;
treeView1.PageContextMenu = pageContextMenu;
treeView1.NodeMouseDoubleClick += treeView1_NodeMouseDoubleClick;
treeView1.OnNodeChanged += treeView1_OnNodeChanged;
treeView1.PreviewKeyDown += treeView1_PreviewKeyDown;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
//ThreadControl.SetVisible(this, false);
ThreadControl.SetSize(this, 300, 580);
ApplicationMode = AppMode.Clear;
}
protected async override void OnShown(EventArgs e)
{
base.OnShown(e);
//ThreadControl.SetVisible(this, false);
await LoadAppSession(jsonfigFilename);
InvalidateAppSession();
newToolStripMenuItem_Click(null, null);
}
protected async override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
if (this.IsBusy)
{
return;
}
this.IsBusy = true;
Result result = await CloseFile();
if (!result.IsSuccess)
{
if (!string.IsNullOrWhiteSpace(result.Message))
{
MessageBox.Show(result.Message, "Close", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.IsBusy = false;
e.Cancel = true;
return;
}
sessionFilename = null;
sessionPassword = null;
treeView1.Clear();
ApplicationMode = AppMode.Clear;
this.IsBusy = false;
Application.Exit();
}
public AppSession CurrentSession { get; set; } = null;
public bool IsBusy
{
get => isBusy;
set
{
treeView1.Enabled = !value;
}
}
protected AppMode ApplicationMode
{
get => appMode;
set
{
appMode = value;
switch (value)
{
case AppMode.Clear:
ThreadControl.SetText(this, AppResource.app_name);
ThreadControl.SetEnable(closeToolStripMenuItem, false);
ThreadControl.SetEnable(saveToolStripMenuItem, false);
ThreadControl.SetEnable(saveAsToolStripMenuItem, false);
ThreadControl.SetEnable(findToolStripMenuItem, false);
ThreadControl.SetEnable(expandAllToolStripMenuItem, false);
ThreadControl.SetEnable(collapseAllToolStripMenuItem, false);
break;
case AppMode.Open:
ThreadControl.SetEnable(closeToolStripMenuItem, true);
ThreadControl.SetEnable(saveToolStripMenuItem, true);
ThreadControl.SetEnable(saveAsToolStripMenuItem, true);
ThreadControl.SetEnable(findToolStripMenuItem, true);
ThreadControl.SetEnable(expandAllToolStripMenuItem, true);
ThreadControl.SetEnable(collapseAllToolStripMenuItem, true);
break;
case AppMode.New:
ThreadControl.SetText(this, AppResource.app_name);
ThreadControl.SetEnable(closeToolStripMenuItem, true);
ThreadControl.SetEnable(saveToolStripMenuItem, false);
ThreadControl.SetEnable(saveAsToolStripMenuItem, true);
ThreadControl.SetEnable(findToolStripMenuItem, true);
ThreadControl.SetEnable(expandAllToolStripMenuItem, true);
ThreadControl.SetEnable(collapseAllToolStripMenuItem, true);
break;
default: break;
}
}
}
#region main menu
/// <summary>
/// New
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void newToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
this.IsBusy = true;
Result result = await CloseFile();
if (!result.IsSuccess)
{
if (!string.IsNullOrWhiteSpace(result.Message))
{
MessageBox.Show(result.Message, "New Session", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.IsBusy = false;
return;
}
sessionFilename = null;
sessionPassword = null;
treeView1.Clear("Untitled");
ApplicationMode = AppMode.New;
this.IsBusy = false;
}
/// <summary>
/// Open file
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
this.IsBusy = true;
Result result = await CloseFile();
if (!result.IsSuccess)
{
if (!string.IsNullOrWhiteSpace(result.Message))
{
MessageBox.Show(result.Message, "Open File", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.IsBusy = false;
return;
}
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
result = await LoadFile(openFileDialog1.FileName);
if (result.IsSuccess)
{
ThreadControl.SetText(this, Path.GetFileNameWithoutExtension(openFileDialog1.FileName) + " - " + AppResource.app_name);
}
else
{
MessageBox.Show(result.Message, "Open File", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
this.IsBusy = false;
}
/// <summary>
/// Close
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void closeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
this.IsBusy = true;
Result result = await CloseFile();
if (!result.IsSuccess)
{
if (!string.IsNullOrWhiteSpace(result.Message))
{
MessageBox.Show(result.Message, "Close File", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.IsBusy = false;
return;
}
sessionFilename = null;
sessionPassword = null;
treeView1.Clear();
ApplicationMode = AppMode.Clear;
this.IsBusy = false;
}
/// <summary>
/// Save
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
if (ApplicationMode == AppMode.Clear)
{
return;
}
this.IsBusy = true;
Result result = await SaveFile(sessionFilename, sessionPassword);
if (result.IsSuccess)
{
MessageBox.Show("File saved!", "Save File", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show(result.Message, "Save File", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.IsBusy = false;
}
/// <summary>
/// Save As
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
if (ApplicationMode == AppMode.Clear)
{
return;
}
this.IsBusy = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
Result result = await SaveAsFile(saveFileDialog1.FileName);
if (result.IsSuccess)
{
MessageBox.Show("File saved!", "Save As File", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show(result.Message, "Save As File", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
this.IsBusy = false;
}
/// <summary>
/// Exit
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
this.Close();
}
/// <summary>
/// Find
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void findToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
if (findForm == null) findForm = new FindForm(this, treeView1);
findForm.Show();
}
/// <summary>
/// Expand all
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void expandAllToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy) return;
if (ApplicationMode == AppMode.Clear) return;
if (treeView1.SelectedNode == null)
{
treeView1.ExpandAll();
}
else
{
treeView1.SelectedNode.ExpandAll();
}
}
/// <summary>
/// Collapse all
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy) return;
if (ApplicationMode == AppMode.Clear) return;
if (treeView1.SelectedNode == null)
{
treeView1.CollapseAll();
}
else
{
treeView1.SelectedNode.Collapse(false);
}
}
/// <summary>
/// Always on top
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void alwaysOnTopToolStripMenuItem_Click(object sender, EventArgs e)
{
this.TopMost = !this.TopMost;
alwaysOnTopToolStripMenuItem.Checked = this.TopMost;
}
/// <summary>
/// Options
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void optionsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
if (optionsForm == null) optionsForm = new OptionsForm(this);
if (optionsForm.ShowDialog() == DialogResult.OK)
{
await SaveAppSession(jsonfigFilename);
}
InvalidateAppSession();
}
/// <summary>
/// View help
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void viewHelpToolStripMenuItem1_Click(object sender, EventArgs e)
{
try
{
System.Diagnostics.Process.Start("https://www.hiimray.co.uk/software-bookmark-manager");
}
catch
{
// do nothing
}
}
/// <summary>
/// About
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
MessageBox.Show(Application.ProductName + " v" + Application.ProductVersion, "About", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#endregion
#region context menu
/// <summary>
/// Add page
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addPageToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
//treeView1.AddItem(.AddFolder("New Folder");
}
/// <summary>
/// Add folder
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addFolderToolStripMenuItem_Click(object sender, EventArgs e) => treeView1.AddFolder("New Folder");
/// <summary>
/// Edit root node
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void editToolStripMenuItem_Click(object sender, EventArgs e) => treeView1.EditNode();
/// <summary>
/// Sort
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sortToolStripMenuItem_Click(object sender, EventArgs e) => treeView1.Sort();
/// <summary>
/// Add page
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addPageToolStripMenuItem1_Click(object sender, EventArgs e)
{
}
/// <summary>
/// Add folder
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addFolderToolStripMenuItem1_Click(object sender, EventArgs e) => treeView1.AddFolder("New Folder");
/// <summary>
/// Open all pages
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void openAllToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.IsBusy)
{
return;
}
if (treeView1.SelectedNode == null)
{
return;
}
if (treeView1.SelectedNode.Nodes.Count <= 0)
{
return;
}
foreach (TreeNode item in treeView1.SelectedNode.Nodes)
{
await OpenBookmark(item);
}
}
/// <summary>
/// Edit folder name
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void editToolStripMenuItem1_Click(object sender, EventArgs e) => treeView1.EditNode();
/// <summary>
/// Delete folder and contents
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void deleteToolStripMenuItem_Click(object sender, EventArgs e) => treeView1.DeleteNode();
/// <summary>
/// Sort children
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sortToolStripMenuItem1_Click(object sender, EventArgs e) => treeView1.Sort();
/// <summary>
/// Move up
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void moveUpToolStripMenuItem_Click(object sender, EventArgs e) => treeView1.MoveUp();
/// <summary>
/// Move down
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void moveDownToolStripMenuItem_Click(object sender, EventArgs e) => treeView1.MoveDown();
/// <summary>
/// Open page
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void openToolStripMenuItem1_Click(object sender, EventArgs e) => await OpenBookmark(treeView1.SelectedNode);
/// <summary>
/// Edit page
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void editToolStripMenuItem2_Click(object sender, EventArgs e)
{
}
/// <summary>
/// Delete page
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void deleteToolStripMenuItem1_Click(object sender, EventArgs e) => treeView1.DeleteNode();
/// <summary>
/// Move up
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void moveUpToolStripMenuItem1_Click(object sender, EventArgs e) => treeView1.MoveUp();
/// <summary>
/// Move down
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void moveDownToolStripMenuItem1_Click(object sender, EventArgs e) => treeView1.MoveDown();
#endregion
private async void treeView1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
TreeNode tn = treeView1.SelectedNode;
if (tn == null)
{
return;
}
BookmarkTreeView.NodeType nodeType = treeView1.GetNodeType();
switch (e.KeyCode)
{
case Keys.Enter:
await OpenBookmark(tn);
break;
case Keys.F2:
if (nodeType == BookmarkTreeView.NodeType.Page)
{
//(new BookmarkEditForm(treeView1)).ShowDialog();
}
break;
case Keys.Insert:
if (e.Modifiers != Keys.Shift)
{
if ((nodeType == BookmarkTreeView.NodeType.Root) || (nodeType == BookmarkTreeView.NodeType.Folder))
{
//(new BookmarkEditForm(treeView1)).ShowDialog();
}
else if (nodeType == BookmarkTreeView.NodeType.Page)
{
treeView1.SelectedNode = tn.Parent;
//(new BookmarkEditForm(treeView1)).ShowDialog();
}
}
break;
default: break;
}
}
private async void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) => await OpenBookmark(e.Node);
private void treeView1_OnNodeChanged(object sender, EventArgs e)
{
ThreadControl.SetEnable(saveToolStripMenuItem, (treeView1.HasChanged && ApplicationMode == AppMode.Open));
}
protected async Task<Result> CloseFile()
{
return await Task.Run<Result>(async () =>
{
if (this.ApplicationMode == AppMode.Clear)
{
return Result.Create(true);
}
if (!treeView1.HasChanged)
{
return Result.Create(true);
}
if (this.ApplicationMode == AppMode.New)
{
DialogResult response = MessageBox.Show("Save bookmarks", "Save?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (response == DialogResult.Yes)
{
Result result = await SaveAsFile(sessionFilename);
if (!result.IsSuccess)
{
return Result.Create(false, result.Message);
}
}
else if (response == DialogResult.Cancel)
{
return Result.Create(false, "");
}
}
else if (this.ApplicationMode == AppMode.Open)
{
DialogResult response = MessageBox.Show("Save changes to open bookmarks", "Save?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (response == DialogResult.Yes)
{
Result result = await SaveFile(sessionFilename, sessionPassword);
if (!result.IsSuccess)
{
return Result.Create(false, result.Message);
}
}
else if (response == DialogResult.Cancel)
{
return Result.Create(false, "");
}
}
return Result.Create(true);
});
}
protected SupportedFileBase GetSupportedFileHandler(string filename)
{
SupportedFileBase rs = null;
List<Type> typeList = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsSubclassOf(typeof(SupportedFileBase))).ToList();
foreach (Type t in typeList)
{
rs = (SupportedFileBase)Activator.CreateInstance(t);
if (rs == null)
{
continue;
}
if (rs.IsSupported(filename))
{
break;
}
rs = null;
}
return rs;
}
protected void InvalidateAppSession()
{
if (CurrentSession == null) CurrentSession = new AppSession();
if (CurrentSession.EnableAutoPosition)
{
this.Height = Screen.PrimaryScreen.WorkingArea.Height;
this.Location = Screen.PrimaryScreen.WorkingArea.Location;
}
this.TopMost = CurrentSession.AlwaysOnTop;
}
protected async Task<bool> LoadAppSession(string filename)
{
return await Task.Run(() =>
{
if (File.Exists(filename))
{
string sourceCode = null;
try
{
sourceCode = File.ReadAllText(filename);
}
catch (Exception)
{
// do nothing
}
if (string.IsNullOrWhiteSpace(sourceCode))
{
this.CurrentSession = new AppSession();
return false;
}
try
{
this.CurrentSession = JsonConvert.DeserializeObject<AppSession>(sourceCode);
}
catch (Exception)
{
this.CurrentSession = null;
}
if (this.CurrentSession == null)
{
this.CurrentSession = new AppSession();
return false;
}
}
else
{
this.CurrentSession = new AppSession();
try
{
File.WriteAllText(filename, JsonConvert.SerializeObject(this.CurrentSession));
}
catch (Exception)
{
// do nothing
}
}
return true;
});
}
protected async Task<Result> LoadFile(string filename)
{
return await Task.Run(() =>
{
sessionFilename = null;
sessionPassword = null;
ApplicationMode = AppMode.Clear;
treeView1.Clear();
if (string.IsNullOrWhiteSpace(filename))
{
return Result.Create(false, "Filename is empty");
}
if (!File.Exists(filename))
{
return Result.Create(false, "File not found");
}
sessionFilename = filename;
SupportedFileBase fileHandler = GetSupportedFileHandler(sessionFilename);
if (fileHandler == null)
{
return Result.Create(false, "Handler not found for this file type");
}
if (fileHandler.IsEncrypted(sessionFilename))
{
PasswordForm passwordForm = new PasswordForm(this);
if (passwordForm.ShowDialog() == DialogResult.OK)
{
sessionPassword = passwordForm.Password;
}
}
Result result = fileHandler.Load(treeView1, sessionFilename, sessionPassword);
if (!result.IsSuccess)
{
return result;
}
if (treeView1.Nodes.Count > 0)
{
ThreadControl.Expand(treeView1.Nodes[0]);
}
ApplicationMode = AppMode.Open;
if (result.IsSuccess)
{
treeView1.SetNoChanges();
}
ThreadControl.SetFocus(treeView1);
return result;
});
}
protected async Task OpenBookmark(TreeNode node)
{
await Task.Run(() =>
{
if (BookmarkTreeView.GetNodeType(node) != BookmarkTreeView.NodeType.Page)
{
return;
}
BookmarkItemViewModel viewModel = (BookmarkItemViewModel)node.Tag;
if (viewModel == null)
{
return;
}
if (string.IsNullOrWhiteSpace(viewModel.SiteAddress))
{
return;
}
string cmd = (string.IsNullOrWhiteSpace(CurrentSession.RunCommand) ? viewModel.SiteAddress : CurrentSession.RunCommand.Replace("{0}", viewModel.SiteAddress));
try
{
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo
{
FileName = cmd,
UseShellExecute = true
};
System.Diagnostics.Process.Start(psi);
}
catch (Exception exc)
{
#if DEBUG
MessageBox.Show(exc.Message);
#endif
}
});
}
protected async Task<Result> SaveFile(string filename, string password = null)
{
return await Task.Run(() =>
{
if (string.IsNullOrWhiteSpace(filename))
{
return Result.Create(false, "Filename is empty");
}
SupportedFileBase fileHandler = GetSupportedFileHandler(filename);
if (fileHandler == null)
{
return Result.Create(false, "Handler not found for this file type");
}
Result result = fileHandler.Save(treeView1, filename, password);
if (result.IsSuccess)
{
treeView1.SetNoChanges();
}
return result;
});
}
protected async Task<bool> SaveAppSession(string filename)
{
return await Task.Run(() =>
{
if (this.CurrentSession == null) this.CurrentSession = new AppSession();
try
{
File.WriteAllText(filename, JsonConvert.SerializeObject(this.CurrentSession));
}
catch (Exception)
{
return false;
}
return true;
});
}
protected async Task<Result> SaveAsFile(string filename)
{
return await Task.Run(() =>
{
if (string.IsNullOrWhiteSpace(filename))
{
return Result.Create(false, "Filename is empty");
}
SupportedFileBase fileHandler = GetSupportedFileHandler(filename);
if (fileHandler == null)
{
return Result.Create(false, "Handler not found for this file type");
}
string password = null;
if (fileHandler.IsEncryptionSupported)
{
PasswordForm passwordForm = new PasswordForm(this);
if (passwordForm.ShowDialog() == DialogResult.OK)
{
if (!string.IsNullOrWhiteSpace(passwordForm.Password))
{
password = passwordForm.Password;
}
}
}
Result result = fileHandler.Save(treeView1, filename, password);
if (result.IsSuccess)
{
treeView1.SetNoChanges();
}
return result;
});
}
}
}