mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-25 21:31:14 +00:00
1036 lines
30 KiB
C#
Executable file
1036 lines
30 KiB
C#
Executable file
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
/*
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
* This program is released under GNU General Public License
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region ================== Namespaces
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using CodeImp.DoomBuilder.Config;
|
|
using CodeImp.DoomBuilder.Map;
|
|
using CodeImp.DoomBuilder.Types;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.Controls
|
|
{
|
|
/// <summary>
|
|
/// Control to view and/or change custom UDMF fields.
|
|
/// </summary>
|
|
public partial class FieldsEditorControl : UserControl
|
|
{
|
|
#region ================== Constants
|
|
|
|
// Constants
|
|
private const string ADD_FIELD_TEXT = " (click to add custom field)";
|
|
private const string FIELD_PREFIX_SUGGESTION = "user_";
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
public delegate void SingleFieldNameEvent(string fieldname);
|
|
public delegate void DualFieldNameEvent(string oldname, string newname);
|
|
|
|
// Events
|
|
public event SingleFieldNameEvent OnFieldInserted;
|
|
public event DualFieldNameEvent OnFieldNameChanged;
|
|
public event SingleFieldNameEvent OnFieldValueChanged;
|
|
public event SingleFieldNameEvent OnFieldTypeChanged;
|
|
public event SingleFieldNameEvent OnFieldDeleted;
|
|
public event SingleFieldNameEvent OnFieldUndefined;
|
|
|
|
// Variables
|
|
private string elementname;
|
|
private string lasteditfieldname;
|
|
private bool autoinsertuserprefix;
|
|
private Dictionary<string, UniversalType> uifields;//mxd
|
|
private bool showfixedfields = true; //mxd
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
public bool AllowInsert { get { return fieldslist.AllowUserToAddRows; } set { fieldslist.AllowUserToAddRows = value; SetupNewRowStyle(); } }
|
|
public bool AutoInsertUserPrefix { get { return autoinsertuserprefix; } set { autoinsertuserprefix = value; } }
|
|
public int PropertyColumnWidth { get { return fieldname.Width; } set { fieldname.Width = value; UpdateValueColumn(); UpdateBrowseButton(); } }
|
|
public int TypeColumnWidth { get { return fieldtype.Width; } set { fieldtype.Width = value; UpdateValueColumn(); UpdateBrowseButton(); } }
|
|
public bool PropertyColumnVisible { get { return fieldname.Visible; } set { fieldname.Visible = value; UpdateValueColumn(); UpdateBrowseButton(); } }
|
|
public bool TypeColumnVisible { get { return fieldtype.Visible; } set { fieldtype.Visible = value; UpdateValueColumn(); UpdateBrowseButton(); } }
|
|
public bool ValueColumnVisible { get { return fieldvalue.Visible; } set { fieldvalue.Visible = value; UpdateValueColumn(); UpdateBrowseButton(); } }
|
|
public bool ShowFixedFields {get { return showfixedfields; } set { showfixedfields = value; UpdateFixedFieldsVisibility(); } } //mxd
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor
|
|
|
|
// Constructor
|
|
public FieldsEditorControl()
|
|
{
|
|
InitializeComponent();
|
|
CodeImp.DoomBuilder.General.ApplyDataGridViewFix(fieldslist);
|
|
autoinsertuserprefix = true;
|
|
enumscombo.Location = new Point(-1000, 1);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Setup / Apply
|
|
|
|
// This sets up the control
|
|
public void Setup(string elementname)
|
|
{
|
|
// Keep element name
|
|
this.elementname = elementname;
|
|
|
|
//mxd. Get proper UIFields
|
|
uifields = General.Map.FormatInterface.UIFields[General.Map.FormatInterface.GetElementType(elementname)];
|
|
|
|
// Make types list
|
|
fieldtype.Items.Clear();
|
|
fieldtype.Items.AddRange(General.Types.GetCustomUseAttributes());
|
|
}
|
|
|
|
// This applies last sort order
|
|
private void Sort()
|
|
{
|
|
// Sort
|
|
int sortcolumn = General.Settings.ReadSetting("customfieldssortcolumn", 0);
|
|
int sortorder = General.Settings.ReadSetting("customfieldssortorder", (int)ListSortDirection.Ascending);
|
|
|
|
switch(sortorder)
|
|
{
|
|
case (int)SortOrder.Ascending:
|
|
fieldslist.Sort(fieldslist.Columns[sortcolumn], ListSortDirection.Ascending);
|
|
break;
|
|
case (int)SortOrder.Descending:
|
|
fieldslist.Sort(fieldslist.Columns[sortcolumn], ListSortDirection.Descending);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// This adds a list of fixed fields (in undefined state)
|
|
public void ListFixedFields(List<UniversalFieldInfo> list)
|
|
{
|
|
// Add all fields
|
|
foreach(UniversalFieldInfo uf in list)
|
|
{
|
|
//if(uifields.ContainsKey(uf.Name)) continue; //mxd
|
|
// Only add fields that are not managed by the UI
|
|
if(!uf.Managed)
|
|
fieldslist.Rows.Add(new FieldsEditorRow(fieldslist, uf));
|
|
}
|
|
|
|
// Sort fields
|
|
Sort();
|
|
|
|
// Update new row
|
|
SetupNewRowStyle();
|
|
}
|
|
|
|
// Use this in case you don't want the fixed fields
|
|
public void ListNoFixedFields()
|
|
{
|
|
// Update new row
|
|
SetupNewRowStyle();
|
|
}
|
|
|
|
// Clear all fields
|
|
public void ClearFields()
|
|
{
|
|
// Trash rows
|
|
fieldslist.Rows.Clear();
|
|
|
|
// Update new row
|
|
SetupNewRowStyle();
|
|
}
|
|
|
|
// This sets up the fields and values from a UniFields object
|
|
// When first is true, the values are applied unconditionally
|
|
// When first is false, the values in the grid are erased when
|
|
// they differ from the given values (for multiselection)
|
|
public void SetValues(UniFields fromfields, bool first)
|
|
{
|
|
// Go for all the fields
|
|
foreach(KeyValuePair<string, UniValue> f in fromfields)
|
|
{
|
|
if(uifields.ContainsKey(f.Key)) continue; //mxd
|
|
|
|
// Go for all rows
|
|
bool foundrow = false;
|
|
bool skiprow = false; //mxd
|
|
foreach(DataGridViewRow row in fieldslist.Rows)
|
|
{
|
|
// Row is a field?
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
|
|
// Row name matches with field
|
|
if(frow.Name == f.Key)
|
|
{
|
|
//mxd. User vars are set separately
|
|
if(frow.RowType == FieldsEditorRowType.USERVAR)
|
|
{
|
|
skiprow = true;
|
|
break;
|
|
}
|
|
|
|
// First time?
|
|
if(first)
|
|
{
|
|
// Set type when row is not fixed
|
|
if(frow.RowType == FieldsEditorRowType.DYNAMIC) frow.ChangeType(f.Value.Type);
|
|
|
|
// Apply value of field to row
|
|
frow.Define(f.Value.Value);
|
|
}
|
|
else
|
|
{
|
|
// Check if the value is different
|
|
if(!frow.TypeHandler.GetValue().Equals(f.Value.Value))
|
|
{
|
|
// Clear the value in the row
|
|
frow.Define(f.Value.Value);
|
|
frow.Clear();
|
|
}
|
|
}
|
|
|
|
// Done
|
|
foundrow = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//mxd. User vars are set separately
|
|
if(skiprow) continue;
|
|
|
|
// Row not found?
|
|
if(!foundrow)
|
|
{
|
|
// Make new row
|
|
FieldsEditorRow frow = new FieldsEditorRow(fieldslist, f.Key, f.Value.Type, f.Value.Value, false);
|
|
fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, frow);
|
|
|
|
// When not the first, clear the field because the others did not define this one
|
|
if(!first) frow.Clear();
|
|
}
|
|
}
|
|
|
|
// Now check for rows that the givens fields do NOT have
|
|
foreach(DataGridViewRow row in fieldslist.Rows)
|
|
{
|
|
// Row is a field?
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
|
|
// Is this row defined previously?
|
|
if(frow.IsDefined)
|
|
{
|
|
// Check if this row can not be found in the fields at all
|
|
if(!fromfields.ContainsKey(frow.Name))
|
|
{
|
|
// It is not defined in these fields, clear the value
|
|
frow.Clear();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort fields
|
|
Sort();
|
|
}
|
|
|
|
//mxd
|
|
public void SetUserVars(Dictionary<string, UniversalType> vars, Dictionary<string, object> defaults, UniFields fromfields, bool first)
|
|
{
|
|
foreach(KeyValuePair<string, UniversalType> group in vars)
|
|
{
|
|
// Go for all rows
|
|
bool foundrow = false;
|
|
TypeHandler vartype = General.Types.GetFieldHandler((int)group.Value, 0);
|
|
|
|
object defaultvalue;
|
|
if (defaults.ContainsKey(group.Key))
|
|
defaultvalue = defaults[group.Key];
|
|
else defaultvalue = vartype.GetDefaultValue();
|
|
|
|
object value = fromfields.ContainsKey(group.Key) ? fromfields[group.Key].Value : defaultvalue;
|
|
|
|
foreach(DataGridViewRow row in fieldslist.Rows)
|
|
{
|
|
// Row is a field?
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
|
|
// Row name matches with user var?
|
|
if(frow.RowType == FieldsEditorRowType.USERVAR && frow.Name == group.Key)
|
|
{
|
|
// First time?
|
|
if(first)
|
|
{
|
|
frow.Define(value);
|
|
}
|
|
// Check if the value is different
|
|
else if(!frow.TypeHandler.GetValue().Equals(value))
|
|
{
|
|
// Clear the value in the row
|
|
frow.Define(value);
|
|
frow.Clear();
|
|
}
|
|
|
|
// Done
|
|
foundrow = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Row not found?
|
|
if(!foundrow)
|
|
{
|
|
// Make new row
|
|
// [ZZ] 24.07.08: add support for custom defaults for user vars. ZScript only for now.
|
|
FieldsEditorRow frow = new FieldsEditorRow(fieldslist, group.Key, (int)group.Value, defaultvalue, true);
|
|
if(!value.Equals(defaultvalue)) frow.Define(value);
|
|
fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, frow);
|
|
}
|
|
}
|
|
|
|
// Now check for rows that the givens fields do NOT have
|
|
foreach(DataGridViewRow row in fieldslist.Rows)
|
|
{
|
|
// Row is a field?
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
|
|
// Don't undefine user var rows defined by other actor types
|
|
if(frow.RowType == FieldsEditorRowType.USERVAR || vars.ContainsKey(frow.Name)) continue;
|
|
|
|
// Is this row defined previously?
|
|
if(frow.IsDefined)
|
|
{
|
|
// Check if this row can not be found in the fields at all
|
|
if(!fromfields.ContainsKey(frow.Name))
|
|
{
|
|
// It is not defined in these fields, undefine the value
|
|
frow.Undefine();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort fields
|
|
Sort();
|
|
}
|
|
|
|
// This applies the current fields to a UniFields object
|
|
public void Apply(UniFields tofields)
|
|
{
|
|
tofields.BeforeFieldsChange();
|
|
|
|
// Go for all the fields
|
|
UniFields tempfields = new UniFields(tofields);
|
|
foreach(KeyValuePair<string, UniValue> f in tempfields)
|
|
{
|
|
if(uifields.ContainsKey(f.Key)) continue; //mxd
|
|
|
|
// Go for all rows
|
|
bool foundrow = false;
|
|
bool skiprow = false; //mxd
|
|
foreach(DataGridViewRow row in fieldslist.Rows)
|
|
{
|
|
// Row is a field and matches field name?
|
|
if((row is FieldsEditorRow) && (row.Cells[0].Value.ToString() == f.Key))
|
|
{
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
|
|
//mxd. User vars are stored separately
|
|
if(frow.RowType == FieldsEditorRowType.USERVAR)
|
|
{
|
|
skiprow = true;
|
|
break;
|
|
}
|
|
|
|
// Field is defined?
|
|
if(frow.IsDefined)
|
|
{
|
|
foundrow = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//mxd. User vars are stored separately
|
|
if(skiprow) continue;
|
|
|
|
// No such row?
|
|
if(!foundrow)
|
|
{
|
|
// Remove the definition from the fields
|
|
tofields.Remove(f.Key);
|
|
}
|
|
}
|
|
|
|
// Go for all rows
|
|
foreach(DataGridViewRow row in fieldslist.Rows)
|
|
{
|
|
// Row is a field?
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
|
|
// Field is defined and not empty?
|
|
if(frow.RowType != FieldsEditorRowType.USERVAR && frow.IsDefined && !frow.IsEmpty)
|
|
{
|
|
// Apply field
|
|
object oldvalue = null;
|
|
if(tofields.ContainsKey(frow.Name)) oldvalue = tofields[frow.Name].Value;
|
|
tofields[frow.Name] = new UniValue(frow.TypeHandler.Index, frow.GetResult(oldvalue));
|
|
|
|
// Custom row?
|
|
if(frow.RowType == FieldsEditorRowType.DYNAMIC)
|
|
{
|
|
// Write type to map configuration
|
|
General.Map.Options.SetUniversalFieldType(elementname, frow.Name, frow.TypeHandler.Index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
public void ApplyUserVars(Dictionary<string, UniversalType> vars, Dictionary<string, object> vardefaults, UniFields tofields)
|
|
{
|
|
// Apply user variables when target map element contains user var definition and the value is not default
|
|
foreach(DataGridViewRow row in fieldslist.Rows)
|
|
{
|
|
// Row is a field?
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
if(frow.RowType != FieldsEditorRowType.USERVAR || !vars.ContainsKey(frow.Name)) continue;
|
|
|
|
object oldvalue = (tofields.ContainsKey(frow.Name) ? tofields[frow.Name].Value : null);
|
|
object newvalue = frow.GetResult(oldvalue);
|
|
|
|
// Skip field when mixed values
|
|
if(newvalue == null) continue;
|
|
|
|
object typedefault = frow.TypeHandler.GetDefaultValue();
|
|
object userdefault = vardefaults.ContainsKey(frow.Name) ? vardefaults[frow.Name] : typedefault;
|
|
|
|
// Remove field, but only if the type's default value is the same as the user var's default value
|
|
if (newvalue.Equals(typedefault) && typedefault.Equals(userdefault))
|
|
{
|
|
if(tofields.ContainsKey(frow.Name)) tofields.Remove(frow.Name);
|
|
}
|
|
// Add field
|
|
else if(!newvalue.Equals(oldvalue))
|
|
{
|
|
tofields[frow.Name] = new UniValue(frow.TypeHandler.Index, newvalue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Events
|
|
|
|
// Column header clicked
|
|
private void fieldslist_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
// Save sort order
|
|
if(fieldslist.SortedColumn != null)
|
|
{
|
|
int sortcolumn = fieldslist.SortedColumn.Index;
|
|
int sortorder = (int)fieldslist.SortOrder;
|
|
General.Settings.WriteSetting("customfieldssortcolumn", sortcolumn);
|
|
General.Settings.WriteSetting("customfieldssortorder", sortorder);
|
|
}
|
|
|
|
// Stop any cell editing
|
|
ApplyEnums(true);
|
|
fieldslist.EndEdit();
|
|
HideBrowseButton();
|
|
}
|
|
|
|
// Resized
|
|
private void FieldsEditorControl_Resize(object sender, EventArgs e)
|
|
{
|
|
// Rearrange controls
|
|
fieldslist.Size = this.ClientSize;
|
|
UpdateValueColumn();
|
|
UpdateBrowseButton();
|
|
}
|
|
|
|
// Layout change
|
|
private void FieldsEditorControl_Layout(object sender, LayoutEventArgs e)
|
|
{
|
|
FieldsEditorControl_Resize(sender, EventArgs.Empty);
|
|
}
|
|
|
|
// Cell clicked
|
|
private void fieldslist_CellClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
ApplyEnums(true);
|
|
|
|
// Anything selected
|
|
if(fieldslist.SelectedCells.Count > 0)
|
|
{
|
|
if(e.RowIndex == fieldslist.NewRowIndex)
|
|
fieldslist.BeginEdit(false);
|
|
else if(e.ColumnIndex > 0)
|
|
fieldslist.BeginEdit(true);
|
|
}
|
|
}
|
|
|
|
// Cell doubleclicked
|
|
private void fieldslist_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
FieldsEditorRow frow = null;
|
|
|
|
// Anything selected
|
|
if(fieldslist.SelectedRows.Count > 0 && e.RowIndex > -1)
|
|
{
|
|
// Get the row
|
|
DataGridViewRow row = fieldslist.Rows[e.RowIndex];
|
|
if(row is FieldsEditorRow) frow = row as FieldsEditorRow;
|
|
|
|
// First column?
|
|
if(e.ColumnIndex == 0)
|
|
{
|
|
// Dynamic field?
|
|
if((frow != null) && frow.RowType == FieldsEditorRowType.DYNAMIC)
|
|
{
|
|
lasteditfieldname = frow.Name;
|
|
fieldslist.CurrentCell = fieldslist.SelectedRows[0].Cells[0];
|
|
fieldslist.CurrentCell.ReadOnly = false;
|
|
|
|
if((e.RowIndex == fieldslist.NewRowIndex) ||
|
|
frow.Name.StartsWith(FIELD_PREFIX_SUGGESTION, StringComparison.OrdinalIgnoreCase))
|
|
fieldslist.BeginEdit(false);
|
|
else
|
|
fieldslist.BeginEdit(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// User deletes a row
|
|
private void fieldslist_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
|
|
{
|
|
// Get the row
|
|
FieldsEditorRow row = e.Row as FieldsEditorRow;
|
|
if(row == null) return;
|
|
|
|
// Fixed/uservar field?
|
|
if(row.RowType == FieldsEditorRowType.FIXED || row.RowType == FieldsEditorRowType.USERVAR)
|
|
{
|
|
// Just undefine the field
|
|
row.Undefine();
|
|
e.Cancel = true;
|
|
|
|
if(OnFieldUndefined != null) OnFieldUndefined(row.Name);
|
|
}
|
|
else
|
|
{
|
|
if(OnFieldDeleted != null) OnFieldDeleted(row.Name);
|
|
}
|
|
}
|
|
|
|
// User selects a cell for editing
|
|
private void fieldslist_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
|
|
{
|
|
// Field name cell?
|
|
if(e.ColumnIndex == 0)
|
|
{
|
|
// New row index?
|
|
if(e.RowIndex == fieldslist.NewRowIndex)
|
|
{
|
|
// Remove all text
|
|
fieldslist.Rows[e.RowIndex].Cells[0].Style.ForeColor = SystemColors.WindowText;
|
|
fieldslist.Rows[e.RowIndex].Cells[0].Value = (autoinsertuserprefix ? FIELD_PREFIX_SUGGESTION : string.Empty);
|
|
}
|
|
}
|
|
// Value cell?
|
|
else if(e.ColumnIndex == 2)
|
|
{
|
|
// Get the row
|
|
DataGridViewRow row = fieldslist.Rows[e.RowIndex];
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
// Get specializedrow
|
|
FieldsEditorRow frow = row as FieldsEditorRow;
|
|
|
|
// Enumerable?
|
|
if(frow.TypeHandler.IsEnumerable)
|
|
{
|
|
// Fill combo with enums
|
|
enumscombo.SelectedItem = null;
|
|
enumscombo.Text = "";
|
|
enumscombo.Items.Clear();
|
|
enumscombo.Items.AddRange(frow.TypeHandler.GetEnumList().ToArray());
|
|
enumscombo.Tag = frow;
|
|
|
|
// Lock combo to enums?
|
|
if(frow.TypeHandler.IsLimitedToEnums)
|
|
enumscombo.DropDownStyle = ComboBoxStyle.DropDownList;
|
|
else
|
|
enumscombo.DropDownStyle = ComboBoxStyle.DropDown;
|
|
|
|
// Position combobox
|
|
Rectangle cellrect = fieldslist.GetCellDisplayRectangle(2, row.Index, false);
|
|
enumscombo.Location = new Point(cellrect.Left, cellrect.Top);
|
|
enumscombo.Width = cellrect.Width;
|
|
int internalheight = cellrect.Height - (enumscombo.Height - enumscombo.ClientRectangle.Height) - 6;
|
|
General.SetComboBoxItemHeight(enumscombo, internalheight);
|
|
|
|
// Select the value of this field (for DropDownList style combo)
|
|
foreach(EnumItem i in enumscombo.Items)
|
|
{
|
|
// Matches?
|
|
if(string.Compare(i.Title, frow.TypeHandler.GetStringValue(), StringComparison.OrdinalIgnoreCase) == 0)
|
|
{
|
|
// Select this item
|
|
enumscombo.SelectedItem = i;
|
|
break; //mxd
|
|
}
|
|
}
|
|
|
|
// Put the display text in the text (for DropDown style combo)
|
|
enumscombo.Text = frow.TypeHandler.GetStringValue();
|
|
|
|
// Show combo
|
|
enumscombo.Show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Done editing cell contents
|
|
private void fieldslist_CellEndEdit(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
FieldsEditorRow frow = null;
|
|
|
|
// Get the row
|
|
DataGridViewRow row = fieldslist.Rows[e.RowIndex];
|
|
if(row is FieldsEditorRow) frow = row as FieldsEditorRow;
|
|
|
|
// Renaming a field?
|
|
if(e.ColumnIndex == 0)
|
|
{
|
|
// Row is a new row?
|
|
if(frow == null)
|
|
{
|
|
// Name given?
|
|
if((row.Cells[0].Value != null) && (row.Cells[0].Value.ToString() != FIELD_PREFIX_SUGGESTION))
|
|
{
|
|
// Make a valid UDMF field name
|
|
string validname = UniValue.ValidateName(row.Cells[0].Value.ToString());
|
|
if(validname.Length > 0)
|
|
{
|
|
if(uifields.ContainsKey(validname)) //mxd
|
|
{
|
|
MessageBox.Show("Please set this field's value via user interface.");
|
|
}
|
|
else
|
|
{
|
|
// Check if no other row already has this name
|
|
foreach(DataGridViewRow r in fieldslist.Rows)
|
|
{
|
|
// Name matches and not the same row?
|
|
if((r.Index != row.Index) && (r.Cells.Count > 0) && (r.Cells[0].Value != null) &&
|
|
(r.Cells[0].Value.ToString().ToLowerInvariant() == validname))
|
|
{
|
|
// Cannot have two rows with same name
|
|
validname = "";
|
|
General.ShowWarningMessage("Fields must have unique names!", MessageBoxButtons.OK);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Still valid?
|
|
if(validname.Length > 0)
|
|
{
|
|
// Try to find the type in the map options
|
|
int type = General.Map.Options.GetUniversalFieldType(elementname, validname, 0);
|
|
|
|
// Make new row
|
|
frow = new FieldsEditorRow(fieldslist, validname, type, null, false);
|
|
frow.Visible = false;
|
|
fieldslist.Rows.Insert(e.RowIndex + 1, frow);
|
|
|
|
if(OnFieldInserted != null) OnFieldInserted(validname);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Mark the row for delete
|
|
row.ReadOnly = true;
|
|
deleterowstimer.Start();
|
|
}
|
|
else
|
|
{
|
|
// Name given?
|
|
if(row.Cells[0].Value != null)
|
|
{
|
|
// Make a valid UDMF field name
|
|
string validname = UniValue.ValidateName(row.Cells[0].Value.ToString());
|
|
if(validname.Length > 0 && !uifields.ContainsKey(validname)) //mxd
|
|
{
|
|
// Check if no other row already has this name
|
|
foreach(DataGridViewRow r in fieldslist.Rows)
|
|
{
|
|
// Name matches and not the same row?
|
|
if((r.Index != row.Index) && (r.Cells.Count > 0) && (r.Cells[0].Value != null) &&
|
|
(r.Cells[0].Value.ToString().ToLowerInvariant() == validname))
|
|
{
|
|
// Cannot have two rows with same name
|
|
validname = "";
|
|
row.Cells[0].Value = lasteditfieldname;
|
|
General.ShowWarningMessage("Fields must have unique names!", MessageBoxButtons.OK);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Still valid?
|
|
if(validname.Length > 0)
|
|
{
|
|
// Try to find the type in the map options
|
|
int type = General.Map.Options.GetUniversalFieldType(elementname, validname, -1);
|
|
|
|
// Rename row and change type
|
|
row.Cells[0].Value = validname;
|
|
if(type != -1) frow.ChangeType(type);
|
|
|
|
if(OnFieldNameChanged != null) OnFieldNameChanged(lasteditfieldname, validname);
|
|
if(OnFieldTypeChanged != null) OnFieldTypeChanged(validname);
|
|
}
|
|
else
|
|
{
|
|
// Keep old name
|
|
row.Cells[0].Value = lasteditfieldname;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Keep old name
|
|
row.Cells[0].Value = lasteditfieldname;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Keep old name
|
|
row.Cells[0].Value = lasteditfieldname;
|
|
}
|
|
}
|
|
}
|
|
// Changing field type?
|
|
if((e.ColumnIndex == 1) && (frow != null))
|
|
{
|
|
if(OnFieldTypeChanged != null) OnFieldTypeChanged(frow.Name);
|
|
}
|
|
// Changing field value?
|
|
if((e.ColumnIndex == 2) && (frow != null))
|
|
{
|
|
// Apply changes
|
|
ApplyValue(frow, row.Cells[2].Value);
|
|
}
|
|
|
|
// Updated
|
|
if(frow != null) frow.CellChanged();
|
|
|
|
// Update button
|
|
UpdateBrowseButton();
|
|
}
|
|
|
|
// Time to delete rows
|
|
private void deleterowstimer_Tick(object sender, EventArgs e)
|
|
{
|
|
// Stop timer
|
|
deleterowstimer.Stop();
|
|
|
|
// Delete all rows that must be deleted
|
|
for(int i = fieldslist.Rows.Count - 1; i >= 0; i--)
|
|
{
|
|
if(fieldslist.Rows[i].ReadOnly)
|
|
{
|
|
try { fieldslist.Rows.RemoveAt(i); } catch { }
|
|
}
|
|
else
|
|
{
|
|
//mxd. Preserve fixed fields visibility setting
|
|
FieldsEditorRow frow = (fieldslist.Rows[i] as FieldsEditorRow);
|
|
if(frow != null && frow.RowType == FieldsEditorRowType.FIXED) frow.Visible = showfixedfields;
|
|
else fieldslist.Rows[i].Visible = true;
|
|
}
|
|
}
|
|
|
|
// Update new row
|
|
SetupNewRowStyle();
|
|
|
|
// Update button
|
|
UpdateBrowseButton();
|
|
}
|
|
|
|
// Selection changes
|
|
private void fieldslist_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
browsebutton.Visible = false;
|
|
ApplyEnums(true);
|
|
|
|
// Update button
|
|
UpdateBrowseButton();
|
|
}
|
|
|
|
// Browse clicked
|
|
private void browsebutton_Click(object sender, EventArgs e)
|
|
{
|
|
// Any row selected?
|
|
if(fieldslist.SelectedRows.Count > 0)
|
|
{
|
|
// Get selected row
|
|
DataGridViewRow row = fieldslist.SelectedRows[0];
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
// Browse
|
|
FieldsEditorRow frow = (FieldsEditorRow)row;
|
|
frow.Browse(this.ParentForm);
|
|
if(frow.TypeHandler.DynamicImage) browsebutton.Image = frow.TypeHandler.BrowseImage; //mxd
|
|
fieldslist.Focus();
|
|
}
|
|
}
|
|
}
|
|
|
|
// This handles field data errors
|
|
private void fieldslist_DataError(object sender, DataGridViewDataErrorEventArgs e)
|
|
{
|
|
// Ignore this, because we want to display values
|
|
// in the type column that are not in their combobox
|
|
e.ThrowException = false;
|
|
}
|
|
|
|
// Validate value in enums combobox
|
|
private void enumscombo_Validating(object sender, CancelEventArgs e)
|
|
{
|
|
ApplyEnums(false);
|
|
}
|
|
|
|
// Scrolling
|
|
private void fieldslist_Scroll(object sender, ScrollEventArgs e)
|
|
{
|
|
// Stop any cell editing
|
|
ApplyEnums(true);
|
|
fieldslist.EndEdit();
|
|
HideBrowseButton();
|
|
}
|
|
|
|
// Mouse up event
|
|
private void fieldslist_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
// Focus to enums combobox when visible
|
|
if(enumscombo.Visible)
|
|
{
|
|
enumscombo.Focus();
|
|
enumscombo.SelectAll();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Private Methods
|
|
|
|
// This applies a value to a row
|
|
private void ApplyValue(FieldsEditorRow frow, object value)
|
|
{
|
|
// Defined?
|
|
if((value != null) && (frow.RowType == FieldsEditorRowType.DYNAMIC || frow.RowType == FieldsEditorRowType.USERVAR
|
|
|| !frow.Info.Default.Equals(value)))
|
|
{
|
|
frow.Define(value);
|
|
}
|
|
else if(frow.RowType == FieldsEditorRowType.FIXED)
|
|
{
|
|
frow.Undefine();
|
|
}
|
|
|
|
if(OnFieldValueChanged != null) OnFieldValueChanged(frow.Name);
|
|
}
|
|
|
|
// This applies the contents of the enums combobox and hides (if opened)
|
|
private void ApplyEnums(bool hide)
|
|
{
|
|
// Enums combobox shown?
|
|
if(enumscombo.Visible && (enumscombo.Tag is FieldsEditorRow))
|
|
{
|
|
// Get the row
|
|
FieldsEditorRow frow = (FieldsEditorRow)enumscombo.Tag;
|
|
|
|
// Take the selected value and apply it
|
|
ApplyValue(frow, enumscombo.Text);
|
|
|
|
// Updated
|
|
frow.CellChanged();
|
|
}
|
|
|
|
if(hide)
|
|
{
|
|
// Hide combobox
|
|
enumscombo.Tag = null;
|
|
enumscombo.Visible = false;
|
|
enumscombo.Items.Clear();
|
|
}
|
|
}
|
|
|
|
// This sets up the new row
|
|
private void SetupNewRowStyle()
|
|
{
|
|
if(fieldslist.AllowUserToAddRows)
|
|
{
|
|
// Show text for new row
|
|
fieldslist.Rows[fieldslist.NewRowIndex].Cells[0].Value = ADD_FIELD_TEXT;
|
|
fieldslist.Rows[fieldslist.NewRowIndex].Cells[0].Style.ForeColor = SystemColors.GrayText;
|
|
fieldslist.Rows[fieldslist.NewRowIndex].Cells[0].ReadOnly = false;
|
|
|
|
// Make sure user can only enter property name in a new row
|
|
fieldslist.Rows[fieldslist.NewRowIndex].Cells[1].ReadOnly = true;
|
|
fieldslist.Rows[fieldslist.NewRowIndex].Cells[2].ReadOnly = true;
|
|
}
|
|
}
|
|
|
|
// This hides the browse button
|
|
private void HideBrowseButton()
|
|
{
|
|
browsebutton.Visible = false;
|
|
}
|
|
|
|
// This updates the Value column width
|
|
private void UpdateValueColumn()
|
|
{
|
|
int fieldnamewidth = fieldname.Visible ? fieldname.Width : 0;
|
|
int fieldtypewidth = fieldtype.Visible ? fieldtype.Width : 0;
|
|
fieldvalue.Width = fieldslist.ClientRectangle.Width - fieldnamewidth - fieldtypewidth - SystemInformation.VerticalScrollBarWidth - 10;
|
|
}
|
|
|
|
// This updates the button
|
|
private void UpdateBrowseButton()
|
|
{
|
|
FieldsEditorRow frow = null;
|
|
|
|
// Any row selected?
|
|
if(fieldslist.SelectedRows.Count > 0)
|
|
{
|
|
// Get selected row
|
|
DataGridViewRow row = fieldslist.SelectedRows[0];
|
|
if(row is FieldsEditorRow) frow = row as FieldsEditorRow;
|
|
|
|
// Not the new row and FieldsEditorRow available?
|
|
if((row.Index < fieldslist.NewRowIndex) && (frow != null))
|
|
{
|
|
// Browse button available for this type?
|
|
if(frow.TypeHandler.IsBrowseable && !frow.TypeHandler.IsEnumerable)
|
|
{
|
|
Rectangle cellrect = fieldslist.GetCellDisplayRectangle(2, row.Index, false);
|
|
|
|
// Show button
|
|
enumscombo.Visible = false;
|
|
browsebutton.Image = frow.TypeHandler.BrowseImage;
|
|
browsebutton.Location = new Point(cellrect.Right - browsebutton.Width, cellrect.Top);
|
|
browsebutton.Height = cellrect.Height;
|
|
browsebutton.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
HideBrowseButton();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HideBrowseButton();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HideBrowseButton();
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void UpdateFixedFieldsVisibility()
|
|
{
|
|
foreach(var row in fieldslist.Rows)
|
|
{
|
|
FieldsEditorRow frow = (row as FieldsEditorRow);
|
|
if(frow != null && frow.RowType == FieldsEditorRowType.FIXED) frow.Visible = showfixedfields;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes an field by its name.
|
|
/// </summary>
|
|
/// <param name="name">Name of the field to remove</param>
|
|
public void RemoveField(string name)
|
|
{
|
|
int index = -1;
|
|
|
|
foreach(DataGridViewRow dgvr in fieldslist.Rows)
|
|
{
|
|
if(dgvr.Cells[0].Value.ToString().ToLowerInvariant() == name.ToLowerInvariant())
|
|
{
|
|
index = dgvr.Index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index >= 0)
|
|
fieldslist.Rows.RemoveAt(index);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes all user vars that have their default values.
|
|
/// </summary>
|
|
public void RemoveUserVarsWithDefaultValue()
|
|
{
|
|
List<int> removeindices = new List<int>();
|
|
|
|
// Go through all rows and find the ones to remove. We can't remove them immediately since that would
|
|
// change the collection while the loop is going through it.
|
|
foreach (DataGridViewRow dgvr in fieldslist.Rows)
|
|
{
|
|
if(dgvr is FieldsEditorRow frow)
|
|
{
|
|
if (frow.RowType == FieldsEditorRowType.USERVAR && frow.Info != null && frow.TypeHandler.GetValue().Equals(frow.Info.Default))
|
|
removeindices.Add(dgvr.Index);
|
|
}
|
|
}
|
|
|
|
// Remove rows. Do it from behind since otherwise the indices would not match
|
|
for (int i = removeindices.Count - 1; i >= 0; i--)
|
|
fieldslist.Rows.RemoveAt(removeindices[i]);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|