topmostfriend/TopMostFriend/FirstRunWindow.cs
2022-08-26 02:01:04 +02:00

357 lines
14 KiB
C#

using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace TopMostFriend {
public class FirstRunWindow : Form {
public static void Display() {
using(FirstRunWindow firstRun = new FirstRunWindow())
firstRun.ShowDialog();
}
private bool CanClose = false;
private bool IsClosing = false;
private bool IsSizing = false;
private Button NextBtn { get; }
private Button PrevBtn { get; }
private Action NextAct = null;
private Action PrevAct = null;
private bool NextVisible { get => NextBtn.Visible; set => NextBtn.Visible = value; }
private bool PrevVisible { get => PrevBtn.Visible; set => PrevBtn.Visible = value; }
private Panel WorkArea { get; }
public FirstRunWindow() {
Text = Program.TITLE + @" v" + Application.ProductVersion.Substring(0, Application.ProductVersion.Length - 2);
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
StartPosition = FormStartPosition.CenterScreen;
FormBorderStyle = FormBorderStyle.FixedSingle;
AutoScaleMode = AutoScaleMode.Dpi;
MaximizeBox = MinimizeBox = false;
TopMost = true;
ClientSize = new Size(410, 80);
Controls.Add(new PictureBox {
Image = Properties.Resources.firstrun,
Size = Properties.Resources.firstrun.Size,
Location = new Point(0, 0),
});
NextBtn = new Button {
Text = Locale.String(@"FirstRunNext"),
Anchor = AnchorStyles.Right | AnchorStyles.Bottom,
Visible = false,
Location = new Point(ClientSize.Width - 81, ClientSize.Height - 29),
};
NextBtn.Click += NextBtn_Click;
Controls.Add(NextBtn);
PrevBtn = new Button {
Text = Locale.String(@"FirstRunPrev"),
Anchor = AnchorStyles.Left | AnchorStyles.Bottom,
Visible = false,
Location = new Point(6, ClientSize.Height - 29),
};
PrevBtn.Click += PrevBtn_Click;
Controls.Add(PrevBtn);
WorkArea = new Panel {
Dock = DockStyle.Fill,
};
Controls.Add(WorkArea);
}
private void PrevBtn_Click(object sender, EventArgs e) {
if(!PrevVisible)
return;
WorkArea.Controls.Clear();
if(PrevAct == null)
Close();
else
Invoke(PrevAct);
}
private void NextBtn_Click(object sender, EventArgs e) {
if(!NextVisible)
return;
WorkArea.Controls.Clear();
if(NextAct == null)
Close();
else
Invoke(NextAct);
}
protected override void OnShown(EventArgs e) {
base.OnShown(e);
Update();
Thread.Sleep(500);
ShowPageIntro();
}
protected override void OnFormClosing(FormClosingEventArgs e) {
if(e.CloseReason == CloseReason.UserClosing && !CanClose) {
e.Cancel = true;
if(!IsClosing) {
IsClosing = true;
SetHeight(80, new Action(() => {
CanClose = true;
Thread.Sleep(100);
Close();
}));
}
return;
}
base.OnFormClosing(e);
}
public void SetHeight(int height, Action onFinish = null) {
if(height < 80)
throw new ArgumentException(@"target height must be more than or equal to 80.", nameof(height));
if(IsSizing)
return;
IsSizing = true;
const int timeout = 1000 / 60;
double time = 0;
double period = timeout / 400d;
int currentHeight = ClientSize.Height;
int currentY = Location.Y;
int diffHeight = height - currentHeight;
int diffY = diffHeight / 2;
Action setHeight = new Action(() => {
int newHeight = currentHeight + (int)Math.Ceiling(time * diffHeight);
int newY = currentY - (int)Math.Ceiling(time * diffY);
ClientSize = new Size(ClientSize.Width, newHeight);
Location = new Point(Location.X, newY);
});
new Thread(() => {
Stopwatch sw = new Stopwatch();
try {
do {
sw.Restart();
Invoke(setHeight);
time += period;
int delay = timeout - (int)sw.ElapsedMilliseconds;
if(delay > 1)
Thread.Sleep(delay);
} while(time < 1d + period);
} finally {
sw.Stop();
if(onFinish != null)
Invoke(onFinish);
IsSizing = false;
}
}) {
IsBackground = true,
Priority = ThreadPriority.AboveNormal,
}.Start();
}
public void ShowPageIntro() {
Text = Locale.String(@"FirstRunWelcomeTitle");
PrevVisible = false;
NextVisible = true;
NextAct = ShowPageHotKey;
SetHeight(190, new Action(() => {
WorkArea.Controls.Add(new Label {
Text = Locale.String(@"FirstRunWelcomeIntro"),
Location = new Point(10, 90),
Size = new Size(ClientSize.Width - 20, 200),
});
}));
}
public void ShowPageHotKey() {
Text = Locale.String(@"FirstRunHotKeyTitle");
PrevVisible = NextVisible = true;
PrevAct = ShowPageIntro;
NextAct = () => {
Program.SetForegroundHotKey(Settings.Get(Program.FOREGROUND_HOTKEY_SETTING, 0));
ShowPageElevation();
};
SetHeight(230, new Action(() => {
WorkArea.Controls.Add(new Label {
Text = Locale.String(@"FirstRunHotKeyExplain"),
Location = new Point(10, 90),
Size = new Size(ClientSize.Width - 20, 40),
});
SettingsWindow.CreateHotKeyInput(
WorkArea,
() => Settings.Get(Program.FOREGROUND_HOTKEY_SETTING, 0),
keyCode => Settings.Set(Program.FOREGROUND_HOTKEY_SETTING, keyCode),
0,
110
);
CheckBox flShowNotification = new CheckBox {
Text = Locale.String(@"FirstRunHotKeyNotify"),
Location = new Point(12, 170),
Checked = Settings.Get(Program.TOGGLE_BALLOON_SETTING, Program.ToggleBalloonDefault),
AutoSize = true,
TabIndex = 201,
};
flShowNotification.CheckedChanged += (s, e) => {
Settings.Set(Program.TOGGLE_BALLOON_SETTING, flShowNotification.Checked);
};
WorkArea.Controls.Add(flShowNotification);
}));
}
public void ShowPageElevation() {
Text = Locale.String(@"FirstRunAdminTitle");
PrevVisible = NextVisible = true;
PrevAct = ShowPageHotKey;
NextAct = ShowPageThanks;
SetHeight(280, () => {
WorkArea.Controls.Add(new Label {
Text = Locale.String(@"FirstRunAdminExplain"),
Location = new Point(10, 90),
Size = new Size(ClientSize.Width - 20, 40),
});
bool alwaysAdmin = Settings.Get(Program.ALWAYS_ADMIN_SETTING, false);
bool implicitAdmin = Settings.Get(Program.ALWAYS_RETRY_ELEVATED, false);
RadioButton rdAsk = new RadioButton {
Text = Locale.String(@"FirstRunAdminOptionAsk"),
Location = new Point(10, 140),
Size = new Size(ClientSize.Width - 20, 30),
Appearance = Appearance.Button,
Checked = !alwaysAdmin && !implicitAdmin,
};
rdAsk.CheckedChanged += (s, e) => {
if(rdAsk.Checked) {
Settings.Set(Program.ALWAYS_ADMIN_SETTING, false);
Settings.Set(Program.ALWAYS_RETRY_ELEVATED, false);
}
};
WorkArea.Controls.Add(rdAsk);
RadioButton rdImplicit = new RadioButton {
Text = Locale.String(@"FirstRunAdminOptionImplicit"),
Location = new Point(rdAsk.Location.X, rdAsk.Location.Y + 36),
Size = rdAsk.Size,
Appearance = rdAsk.Appearance,
Checked = implicitAdmin && !alwaysAdmin,
};
rdImplicit.CheckedChanged += (s, e) => {
if(rdImplicit.Checked) {
Settings.Set(Program.ALWAYS_ADMIN_SETTING, false);
Settings.Set(Program.ALWAYS_RETRY_ELEVATED, true);
}
};
WorkArea.Controls.Add(rdImplicit);
RadioButton rdAlways = new RadioButton {
Text = Locale.String(@"FirstRunAdminOptionAlways"),
Location = new Point(rdAsk.Location.X, rdImplicit.Location.Y + 36),
Size = rdAsk.Size,
Appearance = rdAsk.Appearance,
Checked = alwaysAdmin,
};
rdAlways.CheckedChanged += (s, e) => {
if(rdAlways.Checked) {
Settings.Set(Program.ALWAYS_ADMIN_SETTING, true);
Settings.Set(Program.ALWAYS_RETRY_ELEVATED, false);
}
};
WorkArea.Controls.Add(rdAlways);
});
}
public void ShowPageThanks() {
Text = Locale.String(@"FirstRunThanksTitle");
PrevVisible = NextVisible = true;
PrevAct = ShowPageElevation;
NextAct = CheckRestartNeeded;
SetHeight(270, () => {
Label thankYou = new Label {
Text = Locale.String(@"FirstRunThanksThank"),
Location = new Point(10, 90),
Size = new Size(ClientSize.Width - 20, 20),
};
WorkArea.Controls.Add(thankYou);
string updateLinkString = Locale.String(@"FirstRunThanksUpdate");
int websiteStart = updateLinkString.IndexOf(@"[WEB]");
updateLinkString = updateLinkString.Substring(0, websiteStart) + updateLinkString.Substring(websiteStart + 5);
int websiteEnd = updateLinkString.IndexOf(@"[/WEB]");
updateLinkString = updateLinkString.Substring(0, websiteEnd) + updateLinkString.Substring(websiteEnd + 6);
int changelogStart = updateLinkString.IndexOf(@"[CHANGELOG]");
updateLinkString = updateLinkString.Substring(0, changelogStart) + updateLinkString.Substring(changelogStart + 11);
int changelogEnd = updateLinkString.IndexOf(@"[/CHANGELOG]");
updateLinkString = updateLinkString.Substring(0, changelogEnd) + updateLinkString.Substring(changelogEnd + 12);
LinkLabel updateLink;
WorkArea.Controls.Add(updateLink = new LinkLabel {
Text = updateLinkString,
Location = new Point(10, 120),
Size = new Size(ClientSize.Width - 20, 34),
Font = thankYou.Font,
Links = {
new LinkLabel.Link(websiteStart, websiteEnd - websiteStart, @"https://flash.moe/topmostfriend"),
new LinkLabel.Link(changelogStart, changelogEnd - changelogStart, @"https://flash.moe/topmostfriend/changelog.php"),
},
});
updateLink.LinkClicked += (s, e) => {
Process.Start((string)e.Link.LinkData);
};
string settingsLinkString = Locale.String(@"FirstRunThanksSettings");
int settingsStart = settingsLinkString.IndexOf(@"[SETTINGS]");
settingsLinkString = settingsLinkString.Substring(0, settingsStart) + settingsLinkString.Substring(settingsStart + 10);
int settingsEnd = settingsLinkString.IndexOf(@"[/SETTINGS]");
settingsLinkString = settingsLinkString.Substring(0, settingsEnd) + settingsLinkString.Substring(settingsEnd + 11);
LinkLabel settingsLink;
WorkArea.Controls.Add(settingsLink = new LinkLabel {
Text = settingsLinkString,
Location = new Point(10, 160),
Size = new Size(ClientSize.Width - 20, 30),
Font = thankYou.Font,
Links = {
new LinkLabel.Link(settingsStart, settingsEnd - settingsStart),
},
});
settingsLink.LinkClicked += (s, e) => {
SettingsWindow.Display();
};
WorkArea.Controls.Add(new Label {
Text = Locale.String(@"FirstRunThanksAdmin"),
Location = new Point(10, 200),
Size = new Size(ClientSize.Width - 20, 80),
});
});
}
public void CheckRestartNeeded() {
if(Settings.Get(Program.ALWAYS_ADMIN_SETTING, false))
UAC.RestartElevated();
Close();
}
}
}