SourceCode/PROMS/Volian.Base.Library/PropGridCollEditor.cs

302 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Reflection;
namespace Volian.Base.Library
{
// The PropGridCollEditor expands the functionality of the CollectionEditor (the collection editor comes up when in a
// property grid, and the current selected item is a collection, and the user selects the '...'.
public class PropGridCollEditor : CollectionEditor
{
// Define a static event to expose the inner PropertyGrid's
// PropertyValueChanged event args...
public delegate void MyPropertyValueChangedEventHandler(object sender, PropertyValueChangedEventArgs e);
public static event MyPropertyValueChangedEventHandler MyPropertyValueChanged;
private bool AllowAddDel = false; // flags whether the Add/Delete buttons should be displayed:
// Inherit the default constructor from the standard
// Collection Editor...
private Type _origType;
public PropGridCollEditor(Type type)
: base(type)
{
AllowAddDel = false;
_origType = type;
if (type.Name == "ReplaceStrData") AllowAddDel = true; // Defaults to not having the 'Add' & 'Remove' buttons.
}
protected override Type CreateCollectionItemType()
{
return base.CreateCollectionItemType();
}
private Button resetbtn = null;
// Override this method in order to access the containing user controls
// from the default Collection Editor form or to add new ones...
protected override CollectionForm CreateCollectionForm()
{
// Getting the default layout of the Collection Editor...
CollectionForm collectionForm = base.CreateCollectionForm();
Form frmCollectionEditorForm = collectionForm as Form;
// The Add/Remove buttons are made invisible:
if (!AllowAddDel) HideAddRemoveButtons(0, frmCollectionEditorForm);
Button okbtn = FindOkButton(frmCollectionEditorForm);
if (!AllowAddDel)
{
// add a reset button and put next to ok button:
resetbtn = new Button();
resetbtn.Text = "Reset";
resetbtn.Location = new System.Drawing.Point(okbtn.Location.X - 20, okbtn.Location.Y);
resetbtn.Width = 250;
resetbtn.Visible = true;
resetbtn.Enabled = false; // only enabled on data change
resetbtn.Click += resetbtn_Click;
okbtn.Parent.Controls.Add(resetbtn);
}
SetMembersLabel(collectionForm);
TableLayoutPanel tlpLayout = frmCollectionEditorForm.Controls[0] as TableLayoutPanel;
if (tlpLayout != null)
{
// Get a reference to the inner PropertyGrid and hook an event handler to it.
if (tlpLayout.Controls[5] is PropertyGrid)
{
propertyGrid = tlpLayout.Controls[5] as PropertyGrid;
propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(propertyGrid_PropertyValueChanged);
propertyGrid.SelectedGridItemChanged += PG_SelectedGridItemChanged;
}
}
return collectionForm;
}
// when the reset button is clicked the data will be reset to the data from the original format file. Note that if
// data is added to the UCF that is part of a collection, code will need to be added here to reset the value.
void resetbtn_Click(object sender, EventArgs e)
{
resetbtn.Text = "Reset";
resetbtn.Enabled = false;
if (SelectedGridField.Contains("Left Margin"))
ResetValue(propertyGrid.SelectedGridItem.Parent.Value, "LeftMargin");
else if (SelectedGridField.Contains("Page Length"))
ResetValue(propertyGrid.SelectedGridItem.Parent.Value, "PageLength");
else if (SelectedGridField.Contains("WindowsFont"))
ResetValue(propertyGrid.SelectedGridItem.Parent.Value, "WindowsFont");
// B2019-100: for headers, use Parent's parent and also for both header & checkoffs the field name is 'Active' (not 'Inactive')
else if (SelectedGridField.Contains("Active CheckOff Header"))
ResetValue(propertyGrid.SelectedGridItem.Parent.Parent.Value, "Active");
else if (SelectedGridField.Contains("Active CheckOff"))
ResetValue(propertyGrid.SelectedGridItem.Parent.Parent.Value, "Active");
}
private void ShowReflection(Object data)
{
if (data == null) return;
//Object data = new A();
FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
String str = "";
foreach (FieldInfo f in fields)
{
str += f.Name + " = " + f.GetValue(data) + "\r\n";
}
Console.WriteLine("reflection = {0}", str);
}
PropertyGrid propertyGrid = null;
private string SelectedGridField = "";
// The following method is used to enable and set text on the 'Reset' button. When a grid item is selected, if it has
// UCF data, then put the original value as part of the button text & enable it:
void PG_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
{
if (resetbtn == null) return;
if (propertyGrid != null) Console.WriteLine(LabelPath(propertyGrid.SelectedGridItem)); // PG.SelectedGridItem.Label + " : " + PG.SelectedGridItem.Value;
// see if data has changed, and if so, enable the Reset button.
bool enabled = false;
resetbtn.Text = "Reset";
SelectedGridField = LabelPath(propertyGrid.SelectedGridItem);
if (SelectedGridField.Contains("WindowsFont"))
{
string origForButton = OrigValue(propertyGrid.SelectedGridItem.Parent.Value, "WindowsFont");
if (origForButton != null)
{
resetbtn.Text = "Reset to " + origForButton;
enabled = true;
}
}
else if (SelectedGridField.Contains("Left Margin"))
{
string origForButton = OrigValue(propertyGrid.SelectedGridItem.Parent.Value, "LeftMargin");
if (origForButton != null)
{
resetbtn.Text = "Reset to " + origForButton;
enabled = true;
}
}
else if (SelectedGridField.Contains("Page Length"))
{
string origForButton = OrigValue(propertyGrid.SelectedGridItem.Parent.Value, "PageLength");
if (origForButton != null)
{
resetbtn.Text = "Reset to " + origForButton;
enabled = true;
}
}
else if (SelectedGridField.Contains("Active CheckOff Header"))
{
string origForButton = OrigValue(propertyGrid.SelectedGridItem.Parent.Parent.Value, "Active");
if (origForButton != null)
{
resetbtn.Text = "Reset to " + origForButton;
enabled = true;
}
}
else if (SelectedGridField.Contains("Active CheckOff"))
{
string origForButton = OrigValue(propertyGrid.SelectedGridItem.Parent.Parent.Value, "Active");
if (origForButton != null)
{
resetbtn.Text = "Reset to " + origForButton;
enabled = true;
}
}
else enabled = false;
resetbtn.Enabled = enabled;
}
// This code,using data reflection, will determine the if there is UCF (changed) data, and if so
// will return its value as a string for concatenation of Reset button text.
private string OrigValue(object data, string fieldName)
{
FieldInfo fldVal = null;
FieldInfo fldOrig = null;
if (data == null) return null;
FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
// Go through the fields in the data structure, looking to match that passed in. Also look for the original
// field to compare the 2 to see if a change was made, i.e. UCF data exists.
foreach (FieldInfo f in fields)
{
if (f.Name == "_" + fieldName) fldVal = f;
if (f.Name == "_Orig" + fieldName) fldOrig = f;
}
if (fldVal != null && fldOrig != null)
{
try
{
// see if values are different:
string orig = fldOrig.GetValue(data).ToString();
string newv = fldVal.GetValue(data).ToString();
string retval = fldOrig.GetValue(data).ToString();
if (retval.StartsWith("[Font:"))
{
retval = retval.Replace("[Font: Name=", "").Replace(", Size=", ",");
}
if (orig != newv) return retval;
else return null;
}
catch (Exception ex)
{
return null;
}
}
return null;
}
// The following Resets the format variable's value from the original format (as stored in the 'OrigXXX' field in FormatConfig
private void ResetValue(object data, string fieldName)
{
FieldInfo fldVal = null;
FieldInfo fldOrig = null;
if (data == null) return;
FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
foreach (FieldInfo f in fields)
{
if (f.Name == "_" + fieldName) fldVal = f;
if (f.Name == "_Orig" + fieldName) fldOrig = f;
}
if (fldVal != null && fldOrig != null)
{
fldVal.SetValue(data, fldOrig.GetValue(data));
propertyGrid.Refresh();
}
}
// Remove this on release, and any uses of it.
private string LabelPath(GridItem gi)
{
return (gi.Parent == null ? "" : LabelPath(gi.Parent) + ":" + gi.Label);
}
// set the 'members' label to better reflect what is displayed:
private bool SetMembersLabel(Control myControl)
{
if (myControl is Label && myControl.Text.ToUpper().Contains("MEMBER"))
{
string dt = myControl.TopLevelControl.Text;
if (dt.ToUpper().Contains("DOCSTYL")) myControl.Text = "Section Types";
else if (dt.ToUpper().Contains("REPLACE")) myControl.Text = "Replace Words";
else if (dt.ToUpper().Contains("CHECKOFFHEADER")) myControl.Text = "CheckOff Headers";
else if (dt.ToUpper().Contains("CHECKOFF")) myControl.Text = "CheckOffs";
else if (dt.ToUpper().Contains("STEP")) myControl.Text = "Steps";
return true;
}
if (myControl.Controls != null && myControl.Controls.Count > 0)
{
foreach (Control con in myControl.Controls)
{
bool found = SetMembersLabel(con);
if (found == true) return true;
}
}
return false;
}
// This code looks for the 'OK' button, so that the 'Reset' button can be placed by it.
private Button FindOkButton(Control myControl)
{
if (myControl is Button && myControl.Text == "OK")
{
return myControl as Button;
}
if (myControl.Controls != null && myControl.Controls.Count > 0)
{
foreach (Control con in myControl.Controls)
{
Button found = FindOkButton(con);
if (found != null) return found;
}
}
return null;
}
// Find the 'Add' & 'Remove' buttons based on their text, and then make invisible.
private void HideAddRemoveButtons(int level, Control myControl)
{
if (myControl.Text == "&Add" || myControl.Text == "&Remove")
{
myControl.Visible = false;
return;
}
if (myControl.Controls != null && myControl.Controls.Count > 0)
{
foreach (Control con in myControl.Controls)
HideAddRemoveButtons(level + 1, con);
}
}
void propertyGrid_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
{
// Fire our customized collection event...
if (PropGridCollEditor.MyPropertyValueChanged != null)
{
PropGridCollEditor.MyPropertyValueChanged(this, e);
}
}
}
}