166 lines
4.7 KiB
C#
166 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.RegularExpressions;
|
|
using System.Windows.Forms;
|
|
using SebWindowsConfig.Entities;
|
|
using SebWindowsConfig.Utilities;
|
|
|
|
namespace SebWindowsConfig.Controls
|
|
{
|
|
public partial class FilterRuleControl : UserControl
|
|
{
|
|
public FilterRuleControl()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
internal delegate void DataChangedHandler(IEnumerable<FilterRule> rules);
|
|
|
|
internal event DataChangedHandler DataChanged;
|
|
|
|
internal void AddRule(FilterRule rule)
|
|
{
|
|
RuleDataGridView.Rows.Add(rule.IsActive, rule.IsRegex, rule.Expression, rule.Action.ToString());
|
|
}
|
|
|
|
internal IEnumerable<FilterRule> GetRules()
|
|
{
|
|
foreach (DataGridViewRow row in RuleDataGridView.Rows)
|
|
{
|
|
var isValid = true;
|
|
|
|
isValid &= row.Cells[ActiveColumn.Index].Value != null;
|
|
isValid &= row.Cells[RegexColumn.Index].Value != null;
|
|
isValid &= row.Cells[ActionColumn.Index].Value != null;
|
|
|
|
if (row.Cells[RegexColumn.Index].Value as bool? == true)
|
|
{
|
|
isValid &= IsValidRegexRule(row.Cells[ExpressionColumn.Index].Value as string);
|
|
}
|
|
else
|
|
{
|
|
isValid &= IsValidUrlRule(row.Cells[ExpressionColumn.Index].Value as string);
|
|
}
|
|
|
|
if (isValid)
|
|
{
|
|
yield return new FilterRule
|
|
{
|
|
IsActive = (bool) row.Cells[ActiveColumn.Index].Value,
|
|
IsRegex = (bool) row.Cells[RegexColumn.Index].Value,
|
|
Expression = row.Cells[ExpressionColumn.Index].Value as string,
|
|
Action = (FilterAction) Enum.Parse(typeof(FilterAction), row.Cells[ActionColumn.Index].Value as string)
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AddButton_Click(object sender, EventArgs e)
|
|
{
|
|
var isActive = true;
|
|
var isRegex = false;
|
|
|
|
RuleDataGridView.Rows.Add(isActive, isRegex);
|
|
}
|
|
|
|
private void RemoveButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (RuleDataGridView.SelectedRows.Count != 0)
|
|
{
|
|
foreach (DataGridViewRow row in RuleDataGridView.SelectedRows)
|
|
{
|
|
RuleDataGridView.Rows.Remove(row);
|
|
}
|
|
} else
|
|
{
|
|
if (RuleDataGridView.CurrentRow != null)
|
|
{
|
|
RuleDataGridView.Rows.RemoveAt(RuleDataGridView.CurrentRow.Index);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private void RuleDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (e.RowIndex >= 0 && e.ColumnIndex == ExpressionColumn.Index)
|
|
{
|
|
var row = RuleDataGridView.Rows[e.RowIndex];
|
|
var expression = row.Cells[ExpressionColumn.Index].Value as string;
|
|
|
|
if (expression == null)
|
|
{
|
|
RuleDataGridView.Rows.Remove(row);
|
|
}
|
|
}
|
|
|
|
DataChanged?.Invoke(GetRules());
|
|
}
|
|
|
|
private void RuleDataGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
|
|
{
|
|
DataChanged?.Invoke(GetRules());
|
|
}
|
|
|
|
private void RuleDataGridView_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
|
|
{
|
|
DataChanged?.Invoke(GetRules());
|
|
}
|
|
|
|
private void RuleDataGridView_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
|
|
{
|
|
if (e.RowIndex >= 0)
|
|
{
|
|
var row = RuleDataGridView.Rows[e.RowIndex];
|
|
var expression = (row.Cells[ExpressionColumn.Index].Value as string)?.Trim();
|
|
var isRegex = row.Cells[RegexColumn.Index].Value as bool? == true;
|
|
var isValidExpression = isRegex ? IsValidRegexRule(expression) : IsValidUrlRule(expression);
|
|
var isValidAction = !String.IsNullOrWhiteSpace(row.Cells[ActionColumn.Index].Value as string);
|
|
|
|
row.Cells[ActionColumn.Index].ErrorText = isValidAction ? null : "Please choose an action!";
|
|
row.Cells[ExpressionColumn.Index].ErrorText = isValidExpression ? null : (isRegex ? "Invalid regular expression!" : "Invalid URL rule!");
|
|
row.Cells[ExpressionColumn.Index].Value = expression;
|
|
}
|
|
}
|
|
|
|
private void RuleDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
// The row should be updated as soon as the checkbox is changed, not just when the cell looses focus...
|
|
if (e.ColumnIndex == ActiveColumn.Index || e.ColumnIndex == RegexColumn.Index)
|
|
{
|
|
RuleDataGridView.EndEdit();
|
|
}
|
|
}
|
|
|
|
private void RuleDataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
|
|
{
|
|
// If the current cell has changes, they need to be commited immediately. Otherwise, changes can be lost if the user
|
|
// chooses to save the settings via menu or key command since in that case the CellValueChanged event won't fire.
|
|
// See: https://stackoverflow.com/questions/963601/datagridview-value-does-not-gets-saved-if-selection-is-not-lost-from-a-cell
|
|
if (RuleDataGridView.IsCurrentCellDirty)
|
|
{
|
|
RuleDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
|
}
|
|
}
|
|
|
|
private bool IsValidRegexRule(string regex)
|
|
{
|
|
try
|
|
{
|
|
new Regex(regex);
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool IsValidUrlRule(string rule)
|
|
{
|
|
return new SEBURLFilterExpression(rule) != null;
|
|
}
|
|
}
|
|
}
|