2022-11-20 14:42:38 +01:00
|
|
|
using System;
|
2022-11-14 11:06:03 +01:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Transactions;
|
|
|
|
|
using System.Windows.Forms.VisualStyles;
|
|
|
|
|
using System.Xml.Schema;
|
|
|
|
|
|
|
|
|
|
namespace PowerControl
|
|
|
|
|
{
|
|
|
|
|
internal class Menu
|
|
|
|
|
{
|
|
|
|
|
public static readonly String[] Helpers =
|
|
|
|
|
{
|
|
|
|
|
"<C0=008040><C1=0080C0><C2=C08080><C3=FF0000><C4=FFFFFF><C250=FF8000>",
|
|
|
|
|
"<A0=-4><A1=5><A2=-2><A5=-5><S0=-50><S1=50>",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public enum Colors : int
|
|
|
|
|
{
|
|
|
|
|
Green,
|
|
|
|
|
Blue,
|
|
|
|
|
Redish,
|
|
|
|
|
Red,
|
|
|
|
|
White
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public abstract class MenuItem
|
|
|
|
|
{
|
|
|
|
|
public String Name { get; set; }
|
|
|
|
|
public bool Visible { get; set; } = true;
|
|
|
|
|
public bool Selectable { get; set; }
|
|
|
|
|
|
|
|
|
|
protected string Color(String text, Colors index)
|
|
|
|
|
{
|
|
|
|
|
return String.Format("<C{1}>{0}<C>", text, (int)index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public abstract string Render(MenuItem selected);
|
|
|
|
|
|
|
|
|
|
public abstract void CreateMenu(ToolStripItemCollection collection);
|
|
|
|
|
public abstract void Update();
|
2022-11-18 16:14:29 +01:00
|
|
|
public abstract void Reset();
|
2022-11-14 11:06:03 +01:00
|
|
|
|
|
|
|
|
public abstract void SelectNext();
|
|
|
|
|
public abstract void SelectPrev();
|
|
|
|
|
};
|
|
|
|
|
|
2022-11-16 00:33:09 +01:00
|
|
|
public class MenuItemSeparator : MenuItem
|
|
|
|
|
{
|
2022-11-20 14:42:38 +01:00
|
|
|
private ToolStripItem toolStripItem;
|
|
|
|
|
|
2022-11-16 00:33:09 +01:00
|
|
|
public MenuItemSeparator()
|
|
|
|
|
{
|
|
|
|
|
Selectable = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void CreateMenu(ToolStripItemCollection collection)
|
|
|
|
|
{
|
2022-11-20 14:42:38 +01:00
|
|
|
if (toolStripItem != null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
toolStripItem = new ToolStripSeparator();
|
|
|
|
|
collection.Add(toolStripItem);
|
2022-11-16 00:33:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Render(MenuItem selected)
|
|
|
|
|
{
|
|
|
|
|
return Color("---", Colors.Blue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void SelectNext()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void SelectPrev()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Update()
|
|
|
|
|
{
|
|
|
|
|
}
|
2022-11-18 16:14:29 +01:00
|
|
|
|
|
|
|
|
public override void Reset()
|
|
|
|
|
{
|
|
|
|
|
}
|
2022-11-16 00:33:09 +01:00
|
|
|
}
|
|
|
|
|
|
2022-11-14 11:06:03 +01:00
|
|
|
public class MenuItemWithOptions : MenuItem
|
|
|
|
|
{
|
|
|
|
|
public delegate object CurrentValueDelegate();
|
|
|
|
|
public delegate object[] OptionsValueDelegate();
|
|
|
|
|
public delegate object ApplyValueDelegate(object selected);
|
|
|
|
|
|
|
|
|
|
public IList<Object> Options { get; set; } = new List<Object>();
|
|
|
|
|
public Object SelectedOption { get; set; }
|
|
|
|
|
public Object ActiveOption { get; set; }
|
|
|
|
|
public int ApplyDelay { get; set; }
|
2022-11-19 09:29:44 +01:00
|
|
|
public bool CycleOptions { get; set; } = true;
|
2022-11-14 11:06:03 +01:00
|
|
|
|
|
|
|
|
public CurrentValueDelegate CurrentValue { get; set; }
|
|
|
|
|
public OptionsValueDelegate OptionsValues { get; set; }
|
|
|
|
|
public ApplyValueDelegate ApplyValue { get; set; }
|
2022-11-18 16:14:29 +01:00
|
|
|
public CurrentValueDelegate ResetValue { get; set; }
|
2022-11-14 11:06:03 +01:00
|
|
|
|
|
|
|
|
private System.Windows.Forms.Timer delayTimer;
|
|
|
|
|
private ToolStripMenuItem toolStripItem;
|
|
|
|
|
|
|
|
|
|
public MenuItemWithOptions()
|
|
|
|
|
{
|
|
|
|
|
this.Selectable = true;
|
|
|
|
|
}
|
2022-11-16 00:33:09 +01:00
|
|
|
|
2022-11-18 16:14:29 +01:00
|
|
|
public override void Reset()
|
|
|
|
|
{
|
|
|
|
|
if (ResetValue == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var resetOption = ResetValue();
|
|
|
|
|
if (resetOption == null || resetOption.Equals(ActiveOption))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SelectedOption = resetOption;
|
|
|
|
|
onApply();
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-14 11:06:03 +01:00
|
|
|
public override void Update()
|
|
|
|
|
{
|
|
|
|
|
if (CurrentValue != null)
|
|
|
|
|
{
|
|
|
|
|
var result = CurrentValue();
|
|
|
|
|
if (result != null)
|
2022-11-16 00:33:09 +01:00
|
|
|
{
|
2022-11-14 11:06:03 +01:00
|
|
|
ActiveOption = result;
|
2022-11-16 00:33:09 +01:00
|
|
|
Visible = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Visible = false;
|
|
|
|
|
}
|
2022-11-14 11:06:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (OptionsValues != null)
|
|
|
|
|
{
|
|
|
|
|
var result = OptionsValues();
|
|
|
|
|
if (result != null)
|
|
|
|
|
{
|
|
|
|
|
Options = result.ToList();
|
|
|
|
|
updateOptions();
|
|
|
|
|
}
|
2022-11-18 15:20:35 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Visible = false;
|
|
|
|
|
}
|
2022-11-14 11:06:03 +01:00
|
|
|
}
|
|
|
|
|
|
2022-11-18 16:15:34 +01:00
|
|
|
if (ActiveOption == null && Options.Count > 0)
|
2022-11-14 11:06:03 +01:00
|
|
|
ActiveOption = Options.First();
|
|
|
|
|
|
|
|
|
|
onUpdateToolStrip();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void scheduleApply()
|
|
|
|
|
{
|
|
|
|
|
if (delayTimer != null)
|
|
|
|
|
delayTimer.Stop();
|
|
|
|
|
|
|
|
|
|
if (ApplyDelay == 0)
|
|
|
|
|
{
|
|
|
|
|
onApply();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delayTimer = new System.Windows.Forms.Timer();
|
|
|
|
|
delayTimer.Interval = ApplyDelay > 0 ? ApplyDelay : 1;
|
|
|
|
|
delayTimer.Tick += delegate (object? sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (delayTimer != null)
|
|
|
|
|
delayTimer.Stop();
|
|
|
|
|
|
|
|
|
|
onApply();
|
|
|
|
|
};
|
|
|
|
|
delayTimer.Enabled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onApply()
|
|
|
|
|
{
|
|
|
|
|
if (ApplyValue != null)
|
|
|
|
|
ActiveOption = ApplyValue(SelectedOption);
|
2022-11-16 12:49:35 +01:00
|
|
|
else
|
|
|
|
|
ActiveOption = SelectedOption;
|
2022-11-14 11:06:03 +01:00
|
|
|
|
2022-11-16 12:49:35 +01:00
|
|
|
SelectedOption = null;
|
2022-11-14 11:06:03 +01:00
|
|
|
|
|
|
|
|
onUpdateToolStrip();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onUpdateToolStrip()
|
|
|
|
|
{
|
|
|
|
|
if (toolStripItem == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach (ToolStripMenuItem item in toolStripItem.DropDownItems)
|
2022-11-16 12:32:09 +01:00
|
|
|
item.Checked = Object.Equals(item.Tag, SelectedOption ?? ActiveOption);
|
2022-11-14 11:06:03 +01:00
|
|
|
|
|
|
|
|
toolStripItem.Visible = Visible && Options.Count > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateOptions()
|
|
|
|
|
{
|
|
|
|
|
if (toolStripItem == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
toolStripItem.DropDownItems.Clear();
|
|
|
|
|
|
|
|
|
|
foreach (var option in Options)
|
|
|
|
|
{
|
|
|
|
|
var optionItem = new ToolStripMenuItem(option.ToString());
|
|
|
|
|
optionItem.Tag = option;
|
|
|
|
|
optionItem.Click += delegate (object? sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
SelectedOption = option;
|
|
|
|
|
onApply();
|
|
|
|
|
};
|
|
|
|
|
toolStripItem.DropDownItems.Add(optionItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void CreateMenu(ToolStripItemCollection collection)
|
|
|
|
|
{
|
|
|
|
|
if (toolStripItem != null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
toolStripItem = new ToolStripMenuItem();
|
|
|
|
|
toolStripItem.Text = Name;
|
|
|
|
|
updateOptions();
|
|
|
|
|
collection.Add(toolStripItem);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-19 09:29:44 +01:00
|
|
|
private void SelectIndex(int index)
|
|
|
|
|
{
|
|
|
|
|
if (Options.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SelectedOption = Options[Math.Clamp(index, 0, Options.Count - 1)];
|
|
|
|
|
scheduleApply();
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-14 11:06:03 +01:00
|
|
|
public override void SelectNext()
|
|
|
|
|
{
|
2022-11-16 12:49:35 +01:00
|
|
|
int index = Options.IndexOf(SelectedOption ?? ActiveOption);
|
2022-11-19 09:29:44 +01:00
|
|
|
if (index < 0)
|
|
|
|
|
SelectIndex(0); // select first
|
|
|
|
|
else if (CycleOptions)
|
|
|
|
|
SelectIndex((index + 1) % Options.Count);
|
2022-11-14 11:06:03 +01:00
|
|
|
else
|
2022-11-19 09:29:44 +01:00
|
|
|
SelectIndex(index + 1);
|
2022-11-14 11:06:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void SelectPrev()
|
|
|
|
|
{
|
2022-11-16 12:49:35 +01:00
|
|
|
int index = Options.IndexOf(SelectedOption ?? ActiveOption);
|
2022-11-19 09:29:44 +01:00
|
|
|
if (index < 0)
|
|
|
|
|
SelectIndex(Options.Count - 1); // select last
|
|
|
|
|
else if (CycleOptions)
|
|
|
|
|
SelectIndex((index - 1 + Options.Count) % Options.Count);
|
2022-11-14 11:06:03 +01:00
|
|
|
else
|
2022-11-19 09:29:44 +01:00
|
|
|
SelectIndex(index - 1);
|
2022-11-14 11:06:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String optionText(Object option)
|
|
|
|
|
{
|
|
|
|
|
String text;
|
|
|
|
|
|
|
|
|
|
if (option == null)
|
|
|
|
|
text = Color("?", Colors.White);
|
2022-11-16 12:40:59 +01:00
|
|
|
else if (Object.Equals(option, SelectedOption ?? ActiveOption))
|
2022-11-14 11:06:03 +01:00
|
|
|
text = Color(option.ToString(), Colors.Red);
|
|
|
|
|
else if(Object.Equals(option, ActiveOption))
|
|
|
|
|
text = Color(option.ToString(), Colors.White);
|
|
|
|
|
else
|
|
|
|
|
text = Color(option.ToString(), Colors.Green);
|
|
|
|
|
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Render(MenuItem selected)
|
|
|
|
|
{
|
|
|
|
|
string output = "";
|
|
|
|
|
|
|
|
|
|
if (selected == this)
|
|
|
|
|
output += Color(Name + ":", Colors.White).PadRight(30);
|
|
|
|
|
else
|
|
|
|
|
output += Color(Name + ":", Colors.Blue).PadRight(30);
|
|
|
|
|
|
2022-11-16 12:32:09 +01:00
|
|
|
output += optionText(SelectedOption ?? ActiveOption);
|
2022-11-14 11:06:03 +01:00
|
|
|
|
2022-11-16 12:40:59 +01:00
|
|
|
if (SelectedOption != null && !Object.Equals(ActiveOption, SelectedOption))
|
2022-11-14 11:06:03 +01:00
|
|
|
output += " (active: " + optionText(ActiveOption) + ")";
|
|
|
|
|
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class MenuRoot : MenuItem
|
|
|
|
|
{
|
|
|
|
|
public IList<MenuItem> Items { get; set; } = new List<MenuItem>();
|
|
|
|
|
|
|
|
|
|
public MenuItem Selected;
|
|
|
|
|
|
|
|
|
|
public delegate void VisibleChangedDelegate();
|
|
|
|
|
public VisibleChangedDelegate? VisibleChanged;
|
|
|
|
|
|
2022-11-16 08:28:17 +01:00
|
|
|
public MenuItem this[String name]
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
foreach(var item in Items)
|
|
|
|
|
{
|
|
|
|
|
if (item.Name == name)
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-14 11:06:03 +01:00
|
|
|
public override void CreateMenu(ToolStripItemCollection collection)
|
|
|
|
|
{
|
|
|
|
|
foreach(var item in Items)
|
|
|
|
|
item.CreateMenu(collection);
|
|
|
|
|
}
|
|
|
|
|
public override void Update()
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in Items)
|
|
|
|
|
item.Update();
|
2022-11-18 16:14:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Reset()
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in Items)
|
|
|
|
|
item.Reset();
|
|
|
|
|
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
2022-11-14 11:06:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string Render(MenuItem parentSelected)
|
|
|
|
|
{
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
sb.AppendJoin("", Helpers);
|
|
|
|
|
if (Name != "")
|
|
|
|
|
sb.AppendLine(Color(Name, Colors.Blue));
|
|
|
|
|
|
|
|
|
|
foreach (var item in Items)
|
|
|
|
|
{
|
|
|
|
|
if (!item.Visible)
|
|
|
|
|
continue;
|
|
|
|
|
var lines = item.Render(Selected).Split("\r\n").Select(line => " " + line);
|
|
|
|
|
foreach (var line in lines)
|
|
|
|
|
sb.AppendLine(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Show()
|
|
|
|
|
{
|
|
|
|
|
if (Visible)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
Visible = true;
|
|
|
|
|
Update();
|
|
|
|
|
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Prev()
|
|
|
|
|
{
|
|
|
|
|
if (Show())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int index = Items.IndexOf(Selected);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < Items.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
index = (index - 1 + Items.Count) % Items.Count;
|
|
|
|
|
var item = Items[index];
|
|
|
|
|
if (item.Visible && item.Selectable) {
|
|
|
|
|
Selected = item;
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Next()
|
|
|
|
|
{
|
|
|
|
|
if (Show())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int index = Items.IndexOf(Selected);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < Items.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
index = (index + 1) % Items.Count;
|
|
|
|
|
var item = Items[index];
|
|
|
|
|
if (item.Visible && item.Selectable)
|
|
|
|
|
{
|
|
|
|
|
Selected = item;
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void SelectNext()
|
|
|
|
|
{
|
|
|
|
|
if (Show())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (Selected != null)
|
|
|
|
|
{
|
|
|
|
|
Selected.SelectNext();
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-16 08:28:17 +01:00
|
|
|
public void SelectNext(String name)
|
|
|
|
|
{
|
|
|
|
|
var item = this[name];
|
|
|
|
|
if (item is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Show();
|
|
|
|
|
Selected = item;
|
|
|
|
|
item.SelectNext();
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-14 11:06:03 +01:00
|
|
|
public override void SelectPrev()
|
|
|
|
|
{
|
|
|
|
|
if (Show())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (Selected != null)
|
|
|
|
|
{
|
|
|
|
|
Selected.SelectPrev();
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-16 08:28:17 +01:00
|
|
|
|
|
|
|
|
public void SelectPrev(String name)
|
|
|
|
|
{
|
|
|
|
|
var item = this[name];
|
|
|
|
|
if (item is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Show();
|
|
|
|
|
Selected = item;
|
|
|
|
|
item.SelectPrev();
|
|
|
|
|
if (VisibleChanged != null)
|
|
|
|
|
VisibleChanged();
|
|
|
|
|
}
|
2022-11-14 11:06:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|