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

547 lines
16 KiB
C#
Raw Normal View History

2020-04-11 17:43:20 +00:00
using AppLauncher.Models;
using AppLauncher.Windows.Forms;
using Newtonsoft.Json;
2020-05-15 22:34:31 +00:00
using RyzStudio.Windows.Forms;
2020-03-28 02:54:08 +00:00
using System;
2020-03-27 23:16:34 +00:00
using System.Collections.Generic;
2020-05-18 00:37:54 +00:00
using System.ComponentModel;
2020-05-10 10:03:55 +00:00
using System.Drawing;
2020-04-11 17:43:20 +00:00
using System.IO;
2020-05-18 19:45:25 +00:00
using System.Runtime.InteropServices;
2020-03-27 23:16:34 +00:00
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AppLauncher
{
2020-10-21 01:17:24 +00:00
public partial class MainForm : TForm
2020-03-27 23:16:34 +00:00
{
2020-05-18 19:45:25 +00:00
[DllImport("user32.dll")]
protected static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
protected static extern bool UnregisterHotKey(IntPtr hWnd, int id);
//protected const int MOD_ALT = 0x1;
//protected const int MOD_CONTROL = 0x2;
//protected const int MOD_SHIFT = 0x4;
//protected const int MOD_WIN = 0x8;
2020-05-18 19:45:25 +00:00
protected const int WM_HOTKEY = 0x312;
2020-05-18 23:17:22 +00:00
protected OptionsForm optionsForm = null;
protected string sessionFilename = null;
2020-03-27 23:16:34 +00:00
2020-03-28 02:54:08 +00:00
public MainForm() : base()
2020-03-27 23:16:34 +00:00
{
InitializeComponent();
2020-05-10 10:03:55 +00:00
2020-10-22 00:45:54 +00:00
this.AppIcon = Properties.Resources.app_icon_32;
this.StartPosition = FormStartPosition.WindowsDefaultBounds;
2020-05-10 10:03:55 +00:00
}
2020-05-20 00:24:07 +00:00
protected override void OnLoad(EventArgs e)
2020-05-18 19:45:25 +00:00
{
2020-05-20 00:24:07 +00:00
ThreadControl.SetVisible(this, false);
2020-05-18 19:45:25 +00:00
base.OnLoad(e);
2020-05-20 00:24:07 +00:00
}
protected async override void OnShown(EventArgs e)
{
base.OnShown(e);
2020-05-18 19:45:25 +00:00
string jsonfigFilename = Path.ChangeExtension(Application.ExecutablePath, "jsonfig");
if (File.Exists(jsonfigFilename))
{
await loadFile(jsonfigFilename);
}
else
{
this.CurrentSession = new LauncherSession();
ThreadControl.SetVisible(this, true);
}
2020-03-30 10:48:24 +00:00
}
2020-05-18 00:37:54 +00:00
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
2020-05-20 22:46:36 +00:00
if (this.CurrentSession == null) this.CurrentSession = new LauncherSession();
2020-05-18 00:37:54 +00:00
if (string.IsNullOrWhiteSpace(sessionFilename))
{
// do nothing
}
else
{
2020-05-20 22:46:36 +00:00
if (this.CurrentSession.AutoSave == LauncherSession.AutoSaveOption.Prompt)
2020-05-18 00:37:54 +00:00
{
2020-05-20 22:46:36 +00:00
DialogResult dr = MessageBox.Show("Save existing session?", "Exit", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
{
bool rv = saveFile(sessionFilename, false);
if (!rv)
{
e.Cancel = true;
}
}
else if (dr == DialogResult.No)
{
// do nothing
}
else if (dr == DialogResult.Cancel)
2020-05-18 00:37:54 +00:00
{
e.Cancel = true;
}
}
2020-05-20 22:46:36 +00:00
else if (this.CurrentSession.AutoSave == LauncherSession.AutoSaveOption.Yes)
2020-05-18 00:37:54 +00:00
{
2020-05-20 22:46:36 +00:00
saveFile(sessionFilename, false);
2020-05-18 00:37:54 +00:00
}
}
if (this.CurrentSession.HotKey != null)
{
if (this.CurrentSession.HotKey.KeyCode != Keys.None)
{
UnregisterHotKey((IntPtr)Handle, 1);
}
}
2020-05-18 00:37:54 +00:00
}
2020-05-18 19:45:25 +00:00
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg != WM_HOTKEY) return;
switch (m.WParam.ToInt32())
{
case 1:
this.Visible = !this.Visible;
break;
default: break;
}
}
public LauncherSession CurrentSession { get; set; } = null;
2020-05-18 23:17:22 +00:00
private void toolStripMenuItem5_Click(object sender, EventArgs e)
2020-05-03 14:53:15 +00:00
{
if (string.IsNullOrWhiteSpace(sessionFilename))
2020-05-03 14:53:15 +00:00
{
newSession();
2020-05-03 14:53:15 +00:00
}
else
2020-05-03 14:53:15 +00:00
{
DialogResult dr = MessageBox.Show("Save existing session?", "New session", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
{
bool rv = saveFile(sessionFilename, false);
if (rv)
{
newSession();
sessionFilename = null;
}
}
else if (dr == DialogResult.No)
{
newSession();
sessionFilename = null;
}
else if (dr == DialogResult.Cancel)
{
return;
}
2020-05-03 14:53:15 +00:00
}
}
2020-05-03 14:53:15 +00:00
2020-05-20 22:46:36 +00:00
private async void toolStripMenuItem7_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(sessionFilename))
2020-05-03 14:53:15 +00:00
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
2020-05-20 22:46:36 +00:00
await loadFile(openFileDialog1.FileName);
}
2020-05-03 14:53:15 +00:00
}
else
{
DialogResult dr = MessageBox.Show("Save existing session?", "Open session", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
{
bool rv = saveFile(sessionFilename, false);
if (rv)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
2020-05-20 22:46:36 +00:00
await loadFile(openFileDialog1.FileName);
}
}
}
else if (dr == DialogResult.No)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
2020-05-20 22:46:36 +00:00
await loadFile(openFileDialog1.FileName);
}
}
else if (dr == DialogResult.Cancel)
{
return;
}
}
}
2020-05-03 14:53:15 +00:00
private void toolStripMenuItem8_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(sessionFilename))
2020-05-03 14:53:15 +00:00
{
flowLayoutPanel1.Controls.Clear();
}
else
{
DialogResult dr = MessageBox.Show("Save existing session?", "Close session", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
2020-05-03 14:53:15 +00:00
{
bool rv = saveFile(sessionFilename, false);
if (rv)
{
flowLayoutPanel1.Controls.Clear();
sessionFilename = null;
}
2020-05-03 14:53:15 +00:00
}
else if (dr == DialogResult.No)
{
flowLayoutPanel1.Controls.Clear();
2020-05-03 14:53:15 +00:00
sessionFilename = null;
}
else if (dr == DialogResult.Cancel)
{
return;
}
2020-05-03 14:53:15 +00:00
}
}
2020-05-03 14:53:15 +00:00
private void toolStripMenuItem6_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(sessionFilename))
2020-05-03 14:53:15 +00:00
{
saveAsFile();
2020-05-03 14:53:15 +00:00
}
else
2020-05-03 14:53:15 +00:00
{
saveFile(sessionFilename, true);
2020-05-03 14:53:15 +00:00
}
}
private void toolStripMenuItem2_Click(object sender, EventArgs e) => saveAsFile();
private void toolStripMenuItem1_Click(object sender, EventArgs e) => this.TopMost = !this.TopMost;
2020-05-03 14:53:15 +00:00
private void exitToolStripMenuItem_Click(object sender, EventArgs e) => this.Close();
2020-05-03 14:53:15 +00:00
2020-05-18 23:17:22 +00:00
private void optionToolStripMenuItem_Click(object sender, EventArgs e)
{
if (optionsForm == null) optionsForm = new OptionsForm(this);
optionsForm.ShowDialog();
invalidateHotKey();
2020-05-18 23:17:22 +00:00
}
2020-05-20 00:42:51 +00:00
protected override void imageBox3_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (this.CurrentSession == null)
{
this.Close();
}
else
{
if (this.CurrentSession.HideOnClose)
{
this.Visible = !this.Visible;
}
else
{
this.Close();
}
}
}
}
2020-04-12 00:12:21 +00:00
protected async Task collapseWindow(int width, int increment = 6)
2020-04-05 00:32:49 +00:00
{
await Task.Run(() =>
{
while (this.Width > width)
{
2020-05-15 22:34:31 +00:00
ThreadControl.SetWidth(this, (this.Width - increment));
2020-04-05 00:32:49 +00:00
Application.DoEvents();
}
2020-05-15 22:34:31 +00:00
ThreadControl.SetWidth(this, width);
2020-04-05 00:32:49 +00:00
});
}
2020-03-27 23:16:34 +00:00
2020-04-05 00:32:49 +00:00
protected async Task expandWindow(int width, int increment = 8)
{
await Task.Run(() =>
{
while (this.Width < width)
{
2020-05-15 22:34:31 +00:00
ThreadControl.SetWidth(this, (this.Width + increment));
2020-03-27 23:16:34 +00:00
2020-04-05 00:32:49 +00:00
Application.DoEvents();
}
2020-05-15 22:34:31 +00:00
ThreadControl.SetWidth(this, width);
2020-04-05 00:32:49 +00:00
});
}
2020-03-27 23:16:34 +00:00
protected void invalidateHotKey()
2020-04-11 17:43:20 +00:00
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(() =>
{
UnregisterHotKey((IntPtr)Handle, 1);
}));
}
else
{
UnregisterHotKey((IntPtr)Handle, 1);
}
if (this.CurrentSession.HotKey != null)
{
if (this.CurrentSession.HotKey.KeyCode != Keys.None)
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(() =>
{
RegisterHotKey((IntPtr)Handle, 1, this.CurrentSession.HotKey.ModifierCode, this.CurrentSession.HotKey.Key);
}));
}
else
{
RegisterHotKey((IntPtr)Handle, 1, this.CurrentSession.HotKey.ModifierCode, this.CurrentSession.HotKey.Key);
}
}
}
}
protected async Task loadFile(string filename)
{
await Task.Run(() =>
{
if (isBusy)
{
return;
}
if (string.IsNullOrWhiteSpace(filename))
{
return;
}
if (!File.Exists(filename))
{
return;
}
2020-04-11 17:43:20 +00:00
string sourceCode = null;
2020-04-11 17:43:20 +00:00
try
{
sessionFilename = filename;
2020-03-27 23:16:34 +00:00
sourceCode = File.ReadAllText(sessionFilename);
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Load session");
return;
}
2020-05-02 16:17:10 +00:00
if (string.IsNullOrWhiteSpace(sourceCode))
{
return;
}
2020-04-11 17:43:20 +00:00
LauncherSession loadedSession = JsonConvert.DeserializeObject<LauncherSession>(sourceCode);
if (loadedSession == null)
{
return;
}
2020-05-18 23:17:22 +00:00
// load options
this.CurrentSession = loadedSession.ToSimple();
2020-05-18 23:17:22 +00:00
// load tiles
int maxWidth = 0;
ThreadControl.Clear(flowLayoutPanel1);
2020-05-18 23:17:22 +00:00
if (loadedSession.Groups != null)
{
foreach (TileGroupModel item in loadedSession.Groups)
{
TTilePanelLayout panel = new TTilePanelLayout(item);
maxWidth = Math.Max(maxWidth, panel.Width);
2020-06-20 12:21:11 +00:00
ThreadControl.Add(flowLayoutPanel1, panel);
}
}
// ui
ThreadControl.SetSize(this, (maxWidth + SystemInformation.VerticalScrollBarWidth + 20 + flowLayoutPanel1.Left), this.CurrentSession.DefaultHeight);
//
ThreadControl.SetTopMost(this, this.CurrentSession.AlwaysOnTop);
2020-05-20 00:24:07 +00:00
ThreadControl.SetVisible(this, true);
2020-05-20 20:29:51 +00:00
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(() => {
this.Focus();
}));
}
else
{
this.Focus();
}
// hotkey
invalidateHotKey();
});
}
protected void newSession()
{
int maxWidth = 0;
flowLayoutPanel1.Controls.Clear();
TTilePanelLayout panel = new TTilePanelLayout(new TileGroupModel()
{
Title = "New Group",
IsExpanded = true,
GridSize = new Size(8, 1)
});
maxWidth = Math.Max(maxWidth, panel.Width);
flowLayoutPanel1.Controls.Add(panel);
2020-05-07 22:31:03 +00:00
this.Width = maxWidth + SystemInformation.VerticalScrollBarWidth + 20 + flowLayoutPanel1.Left;
}
protected bool saveFile(string filename, bool showNotices = true)
{
if (isBusy)
{
return false;
}
if (string.IsNullOrWhiteSpace(filename))
{
return false;
}
if (flowLayoutPanel1.Controls.Count <= 0)
{
return true;
}
isBusy = true;
// update session
this.CurrentSession.DefaultHeight = this.Height;
this.CurrentSession.AlwaysOnTop = this.TopMost;
// save
LauncherSession saveSession = this.CurrentSession.ToSimple();
saveSession.Groups = new List<TileGroupModel>();
for (int i = 0; i < flowLayoutPanel1.Controls.Count; i++)
{
if (flowLayoutPanel1.Controls[i].GetType() != typeof(TTilePanelLayout))
{
continue;
}
TTilePanelLayout container = flowLayoutPanel1.Controls[i] as TTilePanelLayout;
saveSession.Groups.Add(container.Model);
}
try
{
File.WriteAllText(filename, JsonConvert.SerializeObject(saveSession));
if (showNotices)
{
MessageBox.Show("Session saved!", "Save session", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Save session");
return false;
}
isBusy = false;
return true;
}
protected bool saveAsFile()
{
if (isBusy)
{
return false;
}
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
bool rv = saveFile(saveFileDialog1.FileName);
if (rv)
{
sessionFilename = saveFileDialog1.FileName;
}
return rv;
}
return false;
}
private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e)
{
toolStripMenuItem1.Checked = this.TopMost;
toolStripMenuItem6.Enabled = !string.IsNullOrWhiteSpace(sessionFilename);
2020-04-11 17:43:20 +00:00
}
2020-03-27 23:16:34 +00:00
2020-05-20 22:46:36 +00:00
private void viewHelpToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
System.Diagnostics.Process.Start("https://www.hiimray.co.uk/software-fizzy-launcher");
}
catch
{
// do nothing
}
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e) => MessageBox.Show(Application.ProductName + " v" + Application.ProductVersion, "About", MessageBoxButtons.OK, MessageBoxIcon.Information);
2020-03-27 23:16:34 +00:00
}
}