342 lines
13 KiB
C#
342 lines
13 KiB
C#
using System.Diagnostics;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Windows.Forms;
|
|
using Hawkeye.VisionBuilder.Features.ImagePreview;
|
|
using Hawkeye.VisionBuilder.Panels;
|
|
using Hawkeye.VisionBuilder.Workflow;
|
|
using Hawkeye.VisionBuilder.Workflow.Datatypes;
|
|
using Hawkeye.VisionBuilder.Workflow.Datatypes.Elements;
|
|
using Hawkeye.VisionBuilder.Workflow.Links;
|
|
using Rectangle = System.Drawing.Rectangle;
|
|
|
|
namespace Hawkeye.VisionBuilder.Features.VisionSteps
|
|
{
|
|
public partial class VisionStepsPanel : BasePannel
|
|
{
|
|
private readonly WorkflowList _workflowList;
|
|
private readonly OperationDiscoveryService _discoveryService;
|
|
private readonly ImagePreviewPanel _imagePreviewPanel;
|
|
|
|
private BindingSource _bindingSource = new BindingSource();
|
|
|
|
|
|
public VisionStepsPanel(Workflow.WorkflowList workflowList, OperationDiscoveryService discoveryService,
|
|
ImagePreview.ImagePreviewPanel imagePreviewPanel)
|
|
{
|
|
_workflowList = workflowList;
|
|
_discoveryService = discoveryService;
|
|
_imagePreviewPanel = imagePreviewPanel;
|
|
|
|
InitializeComponent();
|
|
dataGridView1.AutoGenerateColumns = false;
|
|
|
|
|
|
dataGridView1.DataSource = _bindingSource;
|
|
dataGridView1.Columns[0].DataPropertyName = nameof(BaseOperationDecorator.Result);
|
|
dataGridView1.Columns[1].DataPropertyName = nameof(BaseOperationDecorator.IsEnabled);
|
|
dataGridView1.Columns[2].DataPropertyName = nameof(BaseOperationDecorator.Label);
|
|
dataGridView1.Columns[2].ReadOnly = false;
|
|
dataGridView1.ReadOnly = false;
|
|
|
|
dataGridView1.Columns[3].DataPropertyName = nameof(BaseOperationDecorator.ResultString);
|
|
dataGridView1.Columns[4].DataPropertyName = nameof(BaseOperationDecorator.TypeName);
|
|
dataGridView1.Columns[5].DataPropertyName = nameof(BaseOperationDecorator.ExecutionTimeString);
|
|
|
|
dataGridView1.DefaultCellStyle.SelectionBackColor = Color.Bisque;
|
|
dataGridView1.DefaultCellStyle.SelectionForeColor = Color.Black;
|
|
dataGridView1.CellPainting += DataGridView1_CellPainting;
|
|
|
|
|
|
dataGridView1.SelectionChanged += DataGridView1_SelectionChanged;
|
|
|
|
|
|
|
|
|
|
RefreshWorkflow();
|
|
|
|
//dataGridView1.Paint += DataGridView1_Paint;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RefreshWorkflow()
|
|
{
|
|
_bindingSource.Clear();
|
|
foreach (BaseOperation operation in _workflowList.Operations)
|
|
{
|
|
_bindingSource.Add(new BaseOperationDecorator(operation));
|
|
}
|
|
}
|
|
|
|
|
|
public event Action<BaseOperation> OperationSelected = delegate { };
|
|
|
|
private void DataGridView1_SelectionChanged(object? sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
public void UpdateView()
|
|
{
|
|
_imagePreviewPanel.ClearGraphics();
|
|
_imagePreviewPanel.SetImage(_workflowList.Context.ActiveImage);
|
|
_workflowList.Context.GraphicsElements.ForEach(_imagePreviewPanel.AddGraphics);
|
|
_imagePreviewPanel.Refresh();
|
|
Refresh();
|
|
}
|
|
|
|
|
|
private void DataGridView1_Paint(object? sender, PaintEventArgs e)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
private void DataGridView1_CellPainting(object? sender, DataGridViewCellPaintingEventArgs e)
|
|
{
|
|
|
|
if (e.RowIndex > -1)
|
|
{
|
|
var c1 = dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
|
|
var row = dataGridView1.Rows[e.RowIndex];
|
|
var rowValue = row.DataBoundItem as BaseOperationDecorator;
|
|
e.PaintBackground(c1, true);
|
|
if (e.ColumnIndex == 0 && e.Value != null)
|
|
{
|
|
var cx = e.CellBounds.Width / 2 + e.CellBounds.Left;
|
|
var cy = e.CellBounds.Height / 2 + e.CellBounds.Top;
|
|
var radius = e.CellBounds.Height / 2 - 3;
|
|
|
|
|
|
|
|
if ((bool) e.Value)
|
|
{
|
|
e.Graphics.FillEllipse(Brushes.Green, cx - radius, cy - radius, radius * 2, radius * 2);
|
|
}
|
|
else
|
|
{
|
|
e.Graphics.FillEllipse(Brushes.Red, cx - radius, cy - radius, radius * 2, radius * 2);
|
|
}
|
|
e.Handled = true;
|
|
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private static ToolStripMenuItem EnsureCategory(ToolStripItemCollection collection, string category)
|
|
{
|
|
var name = category.Split("/", StringSplitOptions.RemoveEmptyEntries);
|
|
ToolStripMenuItem currentCategory = null;
|
|
foreach (var s in name)
|
|
{
|
|
if (currentCategory == null)
|
|
{
|
|
if (!collection.ContainsKey(s))
|
|
{
|
|
currentCategory = new ToolStripMenuItem()
|
|
{
|
|
Name = s,
|
|
Text = s
|
|
};
|
|
collection.Add(currentCategory);
|
|
}
|
|
else
|
|
{
|
|
currentCategory = collection[s] as ToolStripMenuItem;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!currentCategory.DropDownItems.ContainsKey(s))
|
|
{
|
|
var newCategory = new ToolStripMenuItem()
|
|
{
|
|
Name = s,
|
|
Text = s
|
|
};
|
|
currentCategory.DropDownItems.Add(newCategory);
|
|
currentCategory = newCategory;
|
|
}
|
|
else
|
|
{
|
|
currentCategory = currentCategory.DropDownItems[s] as ToolStripMenuItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
return currentCategory!;
|
|
}
|
|
|
|
private void button1_Click(object sender, EventArgs e)
|
|
{
|
|
var factories = _discoveryService.DiscoverOperations();
|
|
var context = new ContextMenuStrip();
|
|
|
|
foreach (OperationDescription desc in factories)
|
|
{
|
|
var descCategory = desc.Category;
|
|
ToolStripMenuItem currentCategory = EnsureCategory(context.Items, descCategory);
|
|
|
|
currentCategory.DropDownItems.Add(desc.Name).Click += (o, args) =>
|
|
{
|
|
var operation = _discoveryService.CreateInstance(desc.Type);
|
|
_workflowList.Operations.Add(operation);
|
|
int num = 1;
|
|
while (_workflowList.Operations.Any(x => x.Label == operation.Label + num)) num++;//generate unique name
|
|
|
|
|
|
operation.Label += "" + num;
|
|
_bindingSource.Add(new BaseOperationDecorator(operation));
|
|
|
|
dataGridView1.ClearSelection();
|
|
dataGridView1.Rows[^1].Selected = true;
|
|
ProcessRowSelection();
|
|
};
|
|
}
|
|
|
|
context.Show(button1, button1.Location);
|
|
}
|
|
|
|
private void btnTest_Click(object sender, EventArgs e)
|
|
{
|
|
ExecuteWorkflow();
|
|
}
|
|
public WorkflowList WorkflowList => _workflowList;
|
|
public void ExecuteWorkflow()
|
|
{
|
|
_workflowList.Context = new Context();
|
|
var sw = Stopwatch.StartNew();
|
|
_workflowList.Operations.ForEach(x => x.NeedsUpdate = true);
|
|
_workflowList.Execute();
|
|
sw.Stop();
|
|
lblProcessingTime.Text = sw.ElapsedMilliseconds.ToString() + " ms";
|
|
_imagePreviewPanel.SetImage(_workflowList.Context.ActiveImage);
|
|
_imagePreviewPanel.ClearGraphics();
|
|
_workflowList.Context.GraphicsElements.ForEach(_imagePreviewPanel.AddGraphics);
|
|
Refresh();
|
|
}
|
|
|
|
private void dataGridView1_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
ProcessRowSelection();
|
|
}
|
|
|
|
|
|
public BaseOperation? GetSelectedOperation()
|
|
{
|
|
if (dataGridView1.SelectedRows.Count == 0) return null;
|
|
var rowIndex = dataGridView1.SelectedRows[0].Index;
|
|
return (_bindingSource[rowIndex] as BaseOperationDecorator)?.Operation;
|
|
}
|
|
|
|
public void ProcessRowSelection()
|
|
{
|
|
if (dataGridView1.SelectedRows.Count == 0) return;
|
|
var rowIndex = dataGridView1.SelectedRows[0].Index;
|
|
var x = (_bindingSource[rowIndex] as BaseOperationDecorator);
|
|
OperationSelected.Invoke(x.Operation);
|
|
_imagePreviewPanel.ClearGraphics();
|
|
foreach (BaseOperation operation in _workflowList.Operations)
|
|
{
|
|
if (operation.NeedsUpdate) _workflowList.ExecuteOne(operation);
|
|
if (operation == x.Operation) break;
|
|
}
|
|
|
|
UpdateView();
|
|
}
|
|
|
|
|
|
|
|
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Delete)
|
|
{
|
|
if (dataGridView1.SelectedRows.Count == 0) return;
|
|
var rowIndex = dataGridView1.SelectedRows[0].Index;
|
|
_bindingSource.RemoveAt(rowIndex);
|
|
_workflowList.Operations.RemoveAt(rowIndex);
|
|
if (rowIndex > 0)
|
|
{
|
|
dataGridView1.ClearSelection();
|
|
dataGridView1.Rows[rowIndex - 1].Selected = true;
|
|
ProcessRowSelection();
|
|
}
|
|
}
|
|
}
|
|
|
|
private Rectangle dragBoxFromMouseDown;
|
|
private int rowIndexFromMouseDown;
|
|
private int rowIndexOfItemUnderMouseToDrop;
|
|
|
|
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
|
|
{
|
|
// If the mouse moves outside the rectangle, start the drag.
|
|
if (dragBoxFromMouseDown != Rectangle.Empty &&
|
|
!dragBoxFromMouseDown.Contains(e.X, e.Y))
|
|
{
|
|
|
|
// Proceed with the drag and drop, passing in the list item.
|
|
DragDropEffects dropEffect = dataGridView1.DoDragDrop(
|
|
dataGridView1.Rows[rowIndexFromMouseDown],
|
|
DragDropEffects.Move);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
// Get the index of the item the mouse is below.
|
|
rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;
|
|
if (rowIndexFromMouseDown != -1)
|
|
{
|
|
// Remember the point where the mouse down occurred.
|
|
// The DragSize indicates the size that the mouse can move
|
|
// before a drag event should be started.
|
|
Size dragSize = SystemInformation.DragSize;
|
|
|
|
// Create a rectangle using the DragSize, with the mouse position being
|
|
// at the center of the rectangle.
|
|
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
|
|
e.Y - (dragSize.Height / 2)),
|
|
dragSize);
|
|
}
|
|
else
|
|
// Reset the rectangle if the mouse is not over an item in the ListBox.
|
|
dragBoxFromMouseDown = Rectangle.Empty;
|
|
}
|
|
|
|
private void dataGridView1_DragOver(object sender, DragEventArgs e)
|
|
{
|
|
e.Effect = DragDropEffects.Move;
|
|
}
|
|
|
|
private void dataGridView1_DragDrop(object sender, DragEventArgs e)
|
|
{
|
|
// The mouse locations are relative to the screen, so they must be
|
|
// converted to client coordinates.
|
|
Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));
|
|
|
|
// Get the row index of the item the mouse is below.
|
|
rowIndexOfItemUnderMouseToDrop =
|
|
dataGridView1.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
|
|
|
|
var movable = _workflowList.Operations[rowIndexFromMouseDown];
|
|
_workflowList.Operations.RemoveAt(rowIndexFromMouseDown);
|
|
if (rowIndexOfItemUnderMouseToDrop == -1) rowIndexOfItemUnderMouseToDrop = _workflowList.Operations.Count;
|
|
|
|
_workflowList.Operations.Insert(rowIndexOfItemUnderMouseToDrop, movable);
|
|
dataGridView1.ClearSelection();
|
|
RefreshWorkflow();
|
|
dataGridView1.Rows[rowIndexOfItemUnderMouseToDrop].Selected = true;
|
|
ProcessRowSelection();
|
|
|
|
}
|
|
}
|
|
}
|