302 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			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);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 |