This repository has been archived on 2024-08-06. You can view files and clone it, but cannot push or open issues or pull requests.
linear-app-launcher/MainForm.cs

828 lines
25 KiB
C#
Raw Permalink Normal View History

using System;
2021-07-22 23:45:30 +00:00
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
2021-07-22 23:45:30 +00:00
using System.Threading.Tasks;
using System.Windows.Forms;
2024-07-06 15:30:37 +00:00
using RokettoLaunch.Models;
using RyzStudio.Windows.Forms;
using RyzStudio.Windows.ThemedForms.ButtonTextBox;
using RyzStudio.Windows.TileForms;
2021-07-22 23:45:30 +00:00
2024-07-06 15:30:37 +00:00
namespace RokettoLaunch
2021-07-22 23:45:30 +00:00
{
public partial class MainForm : Form
{
private readonly FileSessionManager _fileSessionManager;
2021-07-22 23:45:30 +00:00
private bool _isBusy = false;
private bool _requestExit = false;
public MainForm()
2021-07-22 23:45:30 +00:00
{
InitializeComponent();
this.Text = Application.ProductName;
2024-07-06 15:30:37 +00:00
_fileSessionManager = new FileSessionManager();
_fileSessionManager.OpenFileDialog = openFileDialog1;
_fileSessionManager.SaveFileDialog = saveFileDialog1;
_fileSessionManager.OnNewing += fileSessionManager_OnNewSession;
_fileSessionManager.OnLoading += fileSessionManager_OnLoadSession;
_fileSessionManager.OnSaving += fileSessionManager_OnSaveSession;
_fileSessionManager.OnClearing += fileSessionManager_OnClearSession;
_fileSessionManager.OnFilenameChanged += fileSessionManager_OnFilenameChanged;
//tileContainer1.OnColumnSizeChanged += tileContainer1_OnSizeChanged;
notifyIcon1.Text = Application.ProductName;
2021-07-22 23:45:30 +00:00
2021-07-29 18:34:42 +00:00
this.AutoScaleMode = AutoScaleMode.None;
2021-07-22 23:45:30 +00:00
}
protected async override void OnShown(EventArgs e)
{
base.OnShown(e);
2021-07-22 23:45:30 +00:00
var args = WinApplication.GetCommandLine();
2021-07-23 13:38:07 +00:00
string jsonfigFilename = args.Where(x => (x.Key.Equals("o") || x.Key.Equals("open"))).Select(x => x.Value).FirstOrDefault();
if (string.IsNullOrWhiteSpace(jsonfigFilename))
{
jsonfigFilename = Path.ChangeExtension(Application.ExecutablePath, "jsonfig");
}
2021-07-22 23:45:30 +00:00
if (!string.IsNullOrWhiteSpace(jsonfigFilename) && File.Exists(jsonfigFilename))
{
await _fileSessionManager.OpenSession(jsonfigFilename);
}
else
{
this.CurrentSession = new AppOptions();
2021-07-22 23:45:30 +00:00
InvalidateOptions();
}
2021-07-22 23:45:30 +00:00
}
protected async override void OnClosing(CancelEventArgs e)
2021-07-22 23:45:30 +00:00
{
base.OnClosing(e);
2021-07-22 23:45:30 +00:00
if (this.CurrentSession == null)
2021-07-22 23:45:30 +00:00
{
this.CurrentSession = new AppOptions();
2021-07-22 23:45:30 +00:00
}
if (this.CurrentSession.HideOnClose && !_requestExit)
2021-07-22 23:45:30 +00:00
{
this.Visible = !this.Visible;
e.Cancel = true;
return;
2021-07-22 23:45:30 +00:00
}
_requestExit = false;
2021-07-22 23:45:30 +00:00
await _fileSessionManager.CloseSession();
if ((this.CurrentSession?.ShowToggleHotkey ?? new ThKeyCodeTextBox.Results()).Key != Keys.None)
2021-07-22 23:45:30 +00:00
{
#if !DEBUG
RyzStudio.Runtime.InteropServices.User32.UnregisterHotKey((IntPtr)Handle, 1);
#endif
2021-07-22 23:45:30 +00:00
}
}
2021-07-23 13:38:07 +00:00
protected override void WndProc(ref Message m)
{
switch (m.Msg)
2021-07-22 23:45:30 +00:00
{
case RyzStudio.Runtime.InteropServices.User32.WM_HOTKEY:
if (m.WParam.ToInt32() == 1)
{
this.Visible = !this.Visible;
}
2021-07-22 23:45:30 +00:00
break;
case RyzStudio.Runtime.InteropServices.User32.WM_QUERYENDSESSION:
_requestExit = true;
Application.Exit();
2021-07-22 23:45:30 +00:00
break;
default:
break;
2021-07-22 23:45:30 +00:00
}
base.WndProc(ref m);
}
public AppOptions CurrentSession { get; set; } = null;
private void InvalidateOptions()
2021-07-22 23:45:30 +00:00
{
/// todo: big icons
#if !DEBUG
UIControl.Invoke(this, (x) =>
2021-07-22 23:45:30 +00:00
{
RyzStudio.Runtime.InteropServices.User32.UnregisterHotKey((IntPtr)Handle, 1);
});
2021-07-22 23:45:30 +00:00
if ((this.CurrentSession?.ShowToggleHotkey ?? new ThKeyCodeTextBox.Results()).Key != Keys.None)
2021-07-22 23:45:30 +00:00
{
UIControl.Invoke(this, (x) =>
2021-07-22 23:45:30 +00:00
{
2024-07-06 15:30:37 +00:00
RyzStudio.Runtime.InteropServices.User32.RegisterHotKey((IntPtr)Handle, 1, this.CurrentSession.ShowToggleHotkey.ModifierCode, this.CurrentSession.ShowToggleHotkey.KeyCode);
});
2021-07-22 23:45:30 +00:00
}
#endif
UIControl.SetTopMost(this, this.CurrentSession.AlwaysOnTop);
}
2021-07-22 23:45:30 +00:00
private void menuStrip1_MenuActivate(object sender, EventArgs e)
{
closeToolStripMenuItem.Enabled = (_fileSessionManager.SessionState != FileSessionManager.SessionStateEnum.Close);
saveToolStripMenuItem.Enabled = (_fileSessionManager.SessionState == FileSessionManager.SessionStateEnum.Open);
saveAsToolStripMenuItem.Enabled = (_fileSessionManager.SessionState != FileSessionManager.SessionStateEnum.Close);
addGroupToolStripMenuItem.Enabled = (_fileSessionManager.SessionState != FileSessionManager.SessionStateEnum.Close);
showBigIconsToolStripMenuItem.Checked = this.CurrentSession?.ShowBigIcons ?? true;
alwaysOnTopToolStripMenuItem.Checked = this.CurrentSession?.AlwaysOnTop ?? false;
2021-07-22 23:45:30 +00:00
}
#region Main Menu
2021-07-22 23:45:30 +00:00
/// <summary>
/// New
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void newToolStripMenuItem_Click(object sender, EventArgs e)
2021-07-22 23:45:30 +00:00
{
if (_isBusy)
{
return;
}
await _fileSessionManager.NewSession();
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// Open
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-07-22 23:45:30 +00:00
private async void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if (_isBusy)
{
return;
}
await _fileSessionManager.OpenSession();
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// Close
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void closeToolStripMenuItem_Click(object sender, EventArgs e)
2021-07-22 23:45:30 +00:00
{
if (_isBusy)
{
return;
}
await _fileSessionManager.CloseSession();
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// Save
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void saveToolStripMenuItem_Click(object sender, EventArgs e)
2021-07-22 23:45:30 +00:00
{
if (_isBusy)
{
return;
}
await _fileSessionManager.SaveSession();
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// Save As
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
2021-07-22 23:45:30 +00:00
{
if (_isBusy)
{
return;
}
await _fileSessionManager.SaveAsSession();
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// Exit
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-07-22 23:45:30 +00:00
private void exitToolStripMenuItem2_Click(object sender, EventArgs e)
{
if (_isBusy)
{
return;
}
_requestExit = true;
2021-07-22 23:45:30 +00:00
this.Close();
}
/// <summary>
/// Add group
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2024-07-05 23:30:02 +00:00
private async void addGroupToolStripMenuItem_Click(object sender, EventArgs e)
{
2024-07-05 23:30:02 +00:00
await AddNewTileGroup();
}
/// <summary>
/// Show big icons
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-07-22 23:45:30 +00:00
private void showBigIconsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.CurrentSession == null)
{
return;
}
this.CurrentSession.ShowBigIcons = !this.CurrentSession.ShowBigIcons;
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// Always on top
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void alwaysOnTopToolStripMenuItem_Click(object sender, EventArgs e)
2021-07-22 23:45:30 +00:00
{
if (this.CurrentSession == null)
{
return;
}
this.CurrentSession.AlwaysOnTop = !this.CurrentSession.AlwaysOnTop;
2021-07-22 23:45:30 +00:00
this.TopMost = this.CurrentSession.AlwaysOnTop;
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// Options
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-07-22 23:45:30 +00:00
private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
{
var form = new OptionsForm(this.CurrentSession);
if (form.ShowDialog() == DialogResult.OK)
{
this.CurrentSession = form.Result;
2021-07-22 23:45:30 +00:00
InvalidateOptions();
}
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// View help
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-07-22 23:45:30 +00:00
private void viewHelpToolStripMenuItem1_Click(object sender, EventArgs e)
{
RyzStudio.Diagnostics.Process.Execute(AppResource.AppHelpURL);
2021-07-22 23:45:30 +00:00
}
/// <summary>
/// About
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2021-07-22 23:45:30 +00:00
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
2024-07-06 15:30:37 +00:00
var form = new RyzStudio.Windows.ThemedForms.AboutForm();
form.ProductURL = AppResource.AppProductURL;
form.AuthorURL = AppResource.AppAuthorURL;
form.CompanyURL = AppResource.AppCompanyURL;
form.ProductCopyrightStartYear = 2020;
form.ProductLogo = AppResource.icon_64;
form.ShowDialog();
2021-07-22 23:45:30 +00:00
}
#endregion
2021-07-22 23:45:30 +00:00
#region Notification Icon
2021-07-22 23:45:30 +00:00
private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Visible = !this.Visible;
}
}
private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
{
_requestExit = true;
2021-07-22 23:45:30 +00:00
this.Close();
}
#endregion
#region File Session Manager
private async Task<bool> fileSessionManager_OnNewSession(FileSessionManager sender)
{
2024-07-05 23:30:02 +00:00
return await Task.Run(async () =>
{
var form = new NewForm();
if (form.ShowDialog() == DialogResult.OK)
{
var result = form.Result;
UIControl.Clear(flowLayoutPanel1);
2021-07-22 23:45:30 +00:00
this.CurrentSession.TilesPerRow = result.ColumnCount;
for (var i = 0; i < result.GroupCount; i++)
{
2024-07-05 23:30:02 +00:00
await AddNewTileGroup();
}
}
AutoResize();
return true;
});
}
private async Task<bool> fileSessionManager_OnLoadSession(FileSessionManager sender, string filename)
{
return await Task.Run(async () =>
{
this.CurrentSession = RyzStudio.Text.Json.JsonSerialiser.DeserialiseFile<AppOptions>(filename);
if (this.CurrentSession == null)
{
MessageBox.Show("Unable to read session", "Load session");
return false;
}
if (this.CurrentSession == null)
{
this.CurrentSession = new AppOptions();
}
// Reposition + resize
if (!this.CurrentSession.StartPosition.IsEmpty)
{
UIControl.SetLocation(this, this.CurrentSession.StartPosition);
}
if (this.CurrentSession.Height > 0)
{
UIControl.SetClientHeight(this, this.CurrentSession.Height);
}
InvalidateOptions();
// Load tiles
await LoadTileGroups(this.CurrentSession.Groups);
AutoResize();
UIControl.SetFocus(this);
return true;
});
}
private async Task<bool> fileSessionManager_OnSaveSession(FileSessionManager sender, string filename, bool showNotices)
{
if (string.IsNullOrWhiteSpace(filename))
{
return false;
}
if (!flowLayoutPanel1.Controls.OfType<TileContainer>().Any())
{
return true;
}
return await Task.Run(() =>
{
if (_isBusy)
{
return false;
}
_isBusy = true;
// update session
if (this.CurrentSession == null)
{
this.CurrentSession = new AppOptions();
}
this.CurrentSession.StartPosition = this.Location;
this.CurrentSession.Height = this.Height;
this.CurrentSession.Groups = new List<TileGroupModel>();
foreach (var container in flowLayoutPanel1.Controls.OfType<RyzStudio.Windows.TileForms.TileContainer>())
{
this.CurrentSession.Groups.Add((TileGroupModel)container.Tag);
}
var result = RyzStudio.Text.Json.JsonSerialiser.SerialiseFile(filename, this.CurrentSession);
if (result.IsSuccess)
{
if (showNotices)
{
MessageBox.Show("Session saved!", "Save session", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
{
MessageBox.Show(result.Message, "Save session");
_isBusy = false;
return false;
}
_isBusy = false;
return true;
});
}
private async Task<bool> fileSessionManager_OnClearSession(FileSessionManager sender)
{
await Task.Run(() =>
{
UIControl.Clear(flowLayoutPanel1);
});
return true;
}
private async Task fileSessionManager_OnFilenameChanged(FileSessionManager sender, string filename)
{
await Task.Run(() =>
{
switch (sender.SessionState)
{
case FileSessionManager.SessionStateEnum.New:
UIControl.SetText(this, "New Session - " + Application.ProductName);
break;
case FileSessionManager.SessionStateEnum.Open:
UIControl.SetText(this, Path.GetFileNameWithoutExtension(filename) + " - " + Application.ProductName);
break;
case FileSessionManager.SessionStateEnum.Close:
UIControl.SetText(this, Application.ProductName);
break;
default:
break;
}
});
}
2021-07-22 23:45:30 +00:00
#endregion
#region Tile Container
/// <summary>
/// Add Tile
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addGroupToolStripMenuItem1_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripMenuItem)sender);
if (container == null)
{
return;
}
var form = new EditTileForm();
if (form.ShowDialog() == DialogResult.OK)
{
var result = form.Result;
var newCoord = container.GetNextCoord();
2024-07-06 15:30:37 +00:00
var newTile = new RokettoLaunch.Windows.Forms.TilePanel();
newTile.LoadInfo(result);
container.Add(newTile, newCoord.X, newCoord.Y);
_fileSessionManager.HasChanged = true;
};
}
/// <summary>
/// Add Tile Group
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolStripMenuItem4_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripMenuItem)sender);
if (container == null)
{
return;
}
var form = new EditTileFolderForm();
if (form.ShowDialog() == DialogResult.OK)
{
var result = form.Result;
var newCoord = container.GetNextCoord();
2024-07-06 15:30:37 +00:00
var newTile = new RokettoLaunch.Windows.Forms.TilePanel();
newTile.LoadInfo(result);
container.Add(newTile, newCoord.X, newCoord.Y);
_fileSessionManager.HasChanged = true;
};
}
/// <summary>
/// Edit
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void editToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripMenuItem)sender);
if (container == null)
{
return;
}
var model = UIControl.GetTag<TileGroupModel>(container);
var form = new EditGroupForm(model);
if (form.ShowDialog() == DialogResult.OK)
{
var result = form.Result;
container.Title = result.Title;
container.Tag = result;
container.Invalidate();
_fileSessionManager.HasChanged = true;
};
}
2024-07-05 23:30:02 +00:00
/// <summary>
/// Duplicate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void toolStripMenuItem5_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripMenuItem)sender);
if (container == null)
{
return;
}
var model = UIControl.GetTag<TileGroupModel>(container);
model.IsExpanded = true;
await AddTileGroups(model);
_fileSessionManager.HasChanged = true;
}
/// <summary>
/// Row - Add Row
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addRowToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripDropDownItem)sender);
if (container == null)
{
return;
}
container.AddRow();
_fileSessionManager.HasChanged = true;
}
/// <summary>
/// Row - Remove Row
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void removeRowToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripDropDownItem)sender);
if (container == null)
{
return;
}
container.RemoveRow();
_fileSessionManager.HasChanged = true;
}
/// <summary>
/// Move Top
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void topToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripDropDownItem)sender);
if (container == null)
{
return;
}
UIControl.MoveTop(flowLayoutPanel1, container);
_fileSessionManager.HasChanged = true;
}
/// <summary>
/// Move Up
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void upToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripDropDownItem)sender);
if (container == null)
{
return;
}
UIControl.MoveUp(flowLayoutPanel1, container);
_fileSessionManager.HasChanged = true;
}
/// <summary>
/// Move Down
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void downToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripDropDownItem)sender);
if (container == null)
{
return;
}
UIControl.MoveDown(flowLayoutPanel1, container);
_fileSessionManager.HasChanged = true;
}
/// <summary>
/// Move Bottom
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bottomToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripDropDownItem)sender);
if (container == null)
{
return;
}
UIControl.MoveBottom(flowLayoutPanel1, container);
_fileSessionManager.HasChanged = true;
}
/// <summary>
/// Remove
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void removeToolStripMenuItem_Click(object sender, EventArgs e)
{
var container = UIControl.GetOwner<RyzStudio.Windows.TileForms.TileContainer>((ToolStripMenuItem)sender);
if (container == null)
{
return;
}
flowLayoutPanel1.Controls.Remove(container);
_fileSessionManager.HasChanged = true;
}
#endregion
2024-07-05 23:30:02 +00:00
private async Task AddNewTileGroup()
{
var group = new TileGroupModel();
group.Title = "New Group";
group.IsExpanded = true;
group.GridSize = new System.Drawing.Size(this.CurrentSession.TilesPerRow, 1);
2024-07-05 23:30:02 +00:00
await AddTileGroups(group);
_fileSessionManager.HasChanged = true;
}
private async Task AddTileGroups(TileGroupModel model)
{
await Task.Run(() =>
{
var panel = new RyzStudio.Windows.TileForms.TileContainer();
panel.Title = model.Title;
panel.IsOpen = model.IsExpanded;
panel.TitleContextMenuStrip = tileContainerMenu1;
panel.AutoSizeHeight = true;
panel.Tag = model;
2024-07-05 23:30:02 +00:00
panel.AutoSize(model.GridSize.Width, model.GridSize.Height);
2024-07-05 23:30:02 +00:00
UIControl.Add(flowLayoutPanel1, panel);
2024-07-05 23:30:02 +00:00
// Load tiles
foreach (var item2 in model.Items ?? new List<TileModel>())
{
2024-07-06 15:30:37 +00:00
var tile = new RokettoLaunch.Windows.Forms.TilePanel();
2024-07-05 23:30:02 +00:00
tile.LoadInfo(item2);
panel.Add(tile, item2.Position.X, item2.Position.Y);
}
});
}
private void AutoResize()
{
if (flowLayoutPanel1.Controls.Count <= 0)
{
return;
}
var width = 0;
foreach (var item in flowLayoutPanel1.Controls.OfType<TileContainer>())
{
width = Math.Max(width, item.Width);
}
UIControl.SetClientWidth(this, width + panel1.Padding.Horizontal + this.Padding.Horizontal + SystemInformation.VerticalScrollBarWidth);
}
private async Task LoadTileGroups(List<TileGroupModel> groupList)
{
2024-07-05 23:30:02 +00:00
UIControl.Clear(flowLayoutPanel1);
2024-07-05 23:30:02 +00:00
foreach (var item in groupList ?? new List<TileGroupModel>())
{
await AddTileGroups(item);
}
}
2021-07-22 23:45:30 +00:00
}
}