312 lines
12 KiB
C#
312 lines
12 KiB
C#
using System.Reflection;
|
|
using Hawkeye.VisionBuilder.Features.ImagePreview;
|
|
using Hawkeye.VisionBuilder.Features.VisionSteps;
|
|
using Hawkeye.VisionBuilder.Panels;
|
|
using Hawkeye.VisionBuilder.Workflow;
|
|
using Hawkeye.VisionBuilder.Workflow.Datatypes;
|
|
using Hawkeye.VisionBuilder.Workflow.Links;
|
|
using Hawkeye.VisionBuilder.Workflow.Operations.Attributes;
|
|
using Hawkeye.VisionBuilder.Workflow.Operations.Filters;
|
|
using Rectangle = Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.Rectangle.RectangleElement;
|
|
|
|
namespace Hawkeye.VisionBuilder.Features.ToolEditor
|
|
{
|
|
public partial class ToolConfigurationPanel : BasePannel
|
|
{
|
|
private readonly WorkflowList _workflowList;
|
|
private readonly VisionStepsPanel _visionStepsPanel;
|
|
private BaseOperation _selectedOperation;
|
|
private Dictionary<string, object> _parameters;
|
|
|
|
public ToolConfigurationPanel(WorkflowList workflowList,VisionStepsPanel visionStepsPanel)
|
|
{
|
|
_workflowList = workflowList;
|
|
_visionStepsPanel = visionStepsPanel;
|
|
InitializeComponent();
|
|
}
|
|
|
|
|
|
public void SetOperation(BaseOperation operation)
|
|
{
|
|
_selectedOperation=operation;
|
|
panel2.Enabled=false;
|
|
|
|
//todo: generate header
|
|
|
|
var parameters = operation.GetParameters();
|
|
_parameters=parameters;
|
|
this.flowLayoutPanel1.Controls.Clear();
|
|
foreach (var p in parameters)
|
|
{
|
|
GenerateParameterField(parameters,p.Key, operation);
|
|
}
|
|
|
|
}
|
|
|
|
private void GenerateParameterField(Dictionary<string, object> toolParameter, string pKey,
|
|
BaseOperation operation)
|
|
{
|
|
|
|
|
|
var value = toolParameter[pKey];
|
|
if (value is int i)
|
|
{
|
|
var control = new NumericUpDown() { Minimum = -99999999, Maximum = 99999999, Value = i, };
|
|
control.TextChanged += (sender, args) =>
|
|
{
|
|
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
control.ValueChanged += (sender, args) =>
|
|
{
|
|
|
|
toolParameter[pKey] = ((int) control.Value);
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
}else if (value is double d)
|
|
{
|
|
var control = new NumericUpDown() { Minimum = -99999999, Maximum = 99999999, Value = (decimal)d, Increment = (decimal)0.1, DecimalPlaces = 2};
|
|
control.TextChanged += (sender, args) =>
|
|
{
|
|
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
control.ValueChanged += (sender, args) =>
|
|
{
|
|
|
|
toolParameter[pKey] = ((double) control.Value);
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
}else if (value is string s)
|
|
{
|
|
var control = new TextBox() { Text = s };
|
|
control.TextChanged += (sender, args) =>
|
|
{
|
|
toolParameter[pKey] = (control.Text);
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
}
|
|
else if (value is FilePath filePath)
|
|
{
|
|
|
|
var control = new Button()
|
|
{
|
|
Text = filePath.Path,
|
|
|
|
};
|
|
control.Click += (sender, args) =>
|
|
{
|
|
OpenFileDialog dialog = new OpenFileDialog();
|
|
dialog.Filter = filePath.Format;
|
|
dialog.FileName = filePath.Path;
|
|
if (dialog.ShowDialog() == DialogResult.OK)
|
|
{
|
|
control.Text = dialog.FileName;
|
|
filePath.Path = MakeRelative(dialog.FileName,Environment.CurrentDirectory);
|
|
control.Text = filePath.Path;
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
}
|
|
};
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
|
|
}
|
|
else if (value is SelectFromList selectFromList)
|
|
{
|
|
var control = new ComboBox()
|
|
{
|
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|
};
|
|
control.Items.AddRange(selectFromList.GetList().ToArray());
|
|
control.SelectedItem = selectFromList.Value;
|
|
control.SelectedIndexChanged += (sender, args) =>
|
|
{
|
|
selectFromList.Value = (control.SelectedItem as string);
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
}
|
|
else if (value is ScriptValue scriptValue)
|
|
{
|
|
var control = new TextBox() { Text = scriptValue.Script };
|
|
control.TextChanged += (sender, args) =>
|
|
{
|
|
scriptValue.Script = (control.Text);
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
var cc = new CodeCompletionControl(control);
|
|
cc.NeedSugestions += Cc_NeedSugestions;
|
|
}
|
|
else if (value is bool b)
|
|
{
|
|
var control = new CheckBox() { Checked = b };
|
|
control.CheckedChanged += (sender, args) =>
|
|
{
|
|
toolParameter[pKey] = (control.Checked);
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
}
|
|
if (value is Guid refId && pKey.StartsWith("Reference"))
|
|
{
|
|
var control = new ComboBox()
|
|
{
|
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|
};
|
|
control.SelectedIndexChanged += (sender, args) =>
|
|
{
|
|
toolParameter[pKey] = ((control.SelectedItem)as BaseOperation)?.Id??NoOrigin.Instance.Id;
|
|
panel2.Enabled = true;
|
|
TriggerChanged();
|
|
};
|
|
var candidates = _workflowList.Operations.TakeWhile(x=> x.Id != operation.Id);
|
|
control.Items.Add(NoOrigin.Instance);
|
|
if (pKey.Contains("Edge"))
|
|
{
|
|
control.Items.AddRange(candidates.Where(x => x is IHaveEdge).Select(x => x as IHaveEdge).ToArray());
|
|
}
|
|
else
|
|
{
|
|
control.Items.AddRange(candidates.Where(x => x is IHaveOrigin ).Select(x => x as IHaveOrigin).ToArray());
|
|
}
|
|
|
|
|
|
control.DisplayMember = nameof(BaseOperation.Label);
|
|
control.SelectedItem = candidates.FirstOrDefault(x=>x.Id==refId)?? NoOrigin.Instance;
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
}
|
|
else if(value is Action a)
|
|
{
|
|
var control = new Button()
|
|
{
|
|
Text = "Execute"
|
|
};
|
|
|
|
control.Click += (sender, args) => a();
|
|
var row = new ToolConfigurationRow(BaseOperation.MakeOperationName(pKey), control);
|
|
row.Width = flowLayoutPanel1.Width - 50;
|
|
this.flowLayoutPanel1.Controls.Add(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
private static string MakeRelative(string path, string basePath)
|
|
{
|
|
var uri = new Uri(path);
|
|
var baseUri = new Uri(basePath);
|
|
|
|
// if path can't be made relative
|
|
if (baseUri.Scheme != uri.Scheme)
|
|
{
|
|
return path;
|
|
}
|
|
|
|
var res= baseUri.MakeRelativeUri(uri).ToString();
|
|
// ensure windows path separator
|
|
return "..\\"+res.Replace("/", "\\");
|
|
|
|
|
|
}
|
|
|
|
private void Cc_NeedSugestions(string input, List<string> suggestions)
|
|
{
|
|
|
|
var start = input.IndexOf(".");
|
|
if (start == -1)
|
|
{
|
|
|
|
suggestions.AddRange(_workflowList.Operations.Select(x => x.Label).Where(x=>x.StartsWith(input)));
|
|
suggestions.Add("config");
|
|
return;
|
|
}
|
|
var word = input.Substring(0, start);
|
|
if (word == "config")
|
|
{
|
|
GenerateSugestions(input.Substring(start + 1), _workflowList.Configuration, suggestions);
|
|
return;
|
|
}
|
|
|
|
var o = _workflowList.Operations.FirstOrDefault(x => x.Label == word);
|
|
if (o!=null)
|
|
{
|
|
GenerateSugestions(input.Substring(start + 1), o, suggestions);
|
|
}
|
|
}
|
|
|
|
private IEnumerable<PropertyInfo> GetAllowedProperties(Type type)
|
|
{
|
|
return type.GetProperties().Where(x => x.GetCustomAttribute<NotForToolAttribute>() == null);
|
|
}
|
|
private void GenerateSugestions(string input, object o, List<string> suggestions)
|
|
{
|
|
var start = input.IndexOf(".");
|
|
if (start == -1)
|
|
{
|
|
var props = GetAllowedProperties(o.GetType()).Where(x => x.Name.StartsWith(input)).ToList();
|
|
props.ForEach(x => suggestions.Add(x.Name));
|
|
}
|
|
else
|
|
{
|
|
var word = input.Substring(0, start);
|
|
var prop = GetAllowedProperties(o.GetType()).FirstOrDefault(x => x.Name == word);
|
|
if (prop != null)
|
|
{
|
|
GenerateSugestions(input.Substring(start + 1), prop.GetValue(o), suggestions);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void TriggerChanged()
|
|
{
|
|
if(cbAutoApply.Checked)
|
|
btnOk_Click(null,null);
|
|
}
|
|
|
|
private void btnOk_Click(object sender, EventArgs e)
|
|
{
|
|
_selectedOperation.SetParameters(_parameters);
|
|
SetOperation(_selectedOperation);
|
|
_workflowList.ExecuteTill(_selectedOperation);
|
|
_workflowList.ExecuteOne(_selectedOperation);
|
|
_visionStepsPanel.UpdateView();
|
|
}
|
|
|
|
private void btnCancel_Click(object sender, EventArgs e)
|
|
{
|
|
SetOperation(_selectedOperation);
|
|
}
|
|
}
|
|
}
|