mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-27 14:12:16 +00:00
5cb573d938
Enhanced scripting workflow. Thing and linedef arguments can now have default value in configuration files. Fixed laggy visual camera movement on systems with big uptime. Fixed incorrect alignment of Things with "hangs" flag in GZDoom Visual mode. Fixed Editor crash when nodebuilder fails to build map. A window with error description will be shown instead. Doom light levels were used even in maps in non-doom map format. Tag Explorer plugin: Elements list wasn't updated when map element was deleted. Pugin wasn't disposed properly, which may led to Doom Builder 2 crash on map close. Fixed plugin crash after opening another map. Fixed unresponsive text entry in Filter text box. Fixed plugin crash when Doom Builder can't determmine thing category ("UNKNOWN" category will be used instead).
868 lines
24 KiB
C#
868 lines
24 KiB
C#
|
|
#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.Text;
|
|
using System.Windows.Forms;
|
|
using Microsoft.Win32;
|
|
using System.Diagnostics;
|
|
using CodeImp.DoomBuilder.Actions;
|
|
using CodeImp.DoomBuilder.Data;
|
|
using CodeImp.DoomBuilder.Config;
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
using SlimDX.Direct3D9;
|
|
using System.Drawing.Imaging;
|
|
using System.Drawing.Drawing2D;
|
|
using CodeImp.DoomBuilder.Map;
|
|
using System.Globalization;
|
|
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;
|
|
|
|
#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(); } }
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor
|
|
|
|
// Constructor
|
|
public FieldsEditorControl()
|
|
{
|
|
InitializeComponent();
|
|
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;
|
|
|
|
// 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);
|
|
|
|
if(sortorder == (int)SortOrder.Ascending)
|
|
fieldslist.Sort(fieldslist.Columns[sortcolumn], ListSortDirection.Ascending);
|
|
else if(sortorder == (int)SortOrder.Descending)
|
|
fieldslist.Sort(fieldslist.Columns[sortcolumn], ListSortDirection.Descending);
|
|
}
|
|
|
|
// This adds a list of fixed fields (in undefined state)
|
|
public void ListFixedFields(List<UniversalFieldInfo> list)
|
|
{
|
|
// Add all fields
|
|
foreach(UniversalFieldInfo uf in list)
|
|
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)
|
|
{
|
|
// Go for all rows
|
|
bool foundrow = false;
|
|
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)
|
|
{
|
|
// First time?
|
|
if(first)
|
|
{
|
|
// Set type when row is not fixed
|
|
if(!frow.IsFixed) 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Row not found?
|
|
if(!foundrow)
|
|
{
|
|
// Make new row
|
|
FieldsEditorRow frow = new FieldsEditorRow(fieldslist, f.Key, f.Value.Type, f.Value.Value);
|
|
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 object GetValue(string name) {
|
|
//have required row?
|
|
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 == name) {
|
|
// Apply value of field to row
|
|
if (frow.IsDefined && !frow.IsEmpty)
|
|
return frow.GetResult(null);
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
//mxd
|
|
public void SetValue(string name, object value, UniversalType type) {
|
|
//have required row?
|
|
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 == name) {
|
|
// Apply value of field to row
|
|
frow.Define(value);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//no such row... let's add it
|
|
FieldsEditorRow newfrow = new FieldsEditorRow(fieldslist, name, (int)type, value);
|
|
fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, newfrow);
|
|
}
|
|
|
|
|
|
// 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)
|
|
{
|
|
// Go for all rows
|
|
bool foundrow = false;
|
|
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;
|
|
|
|
// Field is defined?
|
|
if(frow.IsDefined)
|
|
{
|
|
foundrow = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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.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.IsFixed)
|
|
{
|
|
// Write type to map configuration
|
|
General.Map.Options.SetUniversalFieldType(elementname, frow.Name, frow.TypeHandler.Index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#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)
|
|
{
|
|
// Not a fixed field?
|
|
if((frow != null) && !frow.IsFixed)
|
|
{
|
|
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, true, CultureInfo.InvariantCulture))
|
|
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;
|
|
|
|
// Fixed field?
|
|
if(row.IsFixed)
|
|
{
|
|
// 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;
|
|
if(autoinsertuserprefix)
|
|
fieldslist.Rows[e.RowIndex].Cells[0].Value = FIELD_PREFIX_SUGGESTION;
|
|
else
|
|
fieldslist.Rows[e.RowIndex].Cells[0].Value = "";
|
|
}
|
|
}
|
|
// Value cell?
|
|
else if(e.ColumnIndex == 2)
|
|
{
|
|
// Get the row
|
|
FieldsEditorRow frow = null;
|
|
DataGridViewRow row = fieldslist.Rows[e.RowIndex];
|
|
if(row is FieldsEditorRow)
|
|
{
|
|
// Get specializedrow
|
|
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.SendMessage(enumscombo.Handle, General.CB_SETITEMHEIGHT, -1, 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(), true, CultureInfo.InvariantCulture) == 0)
|
|
{
|
|
// Select this item
|
|
enumscombo.SelectedItem = i;
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
DataGridViewRow row = null;
|
|
|
|
// Get the row
|
|
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)
|
|
{
|
|
// 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);
|
|
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)
|
|
{
|
|
// 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(Exception) { }
|
|
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
|
|
(row as FieldsEditorRow).Browse(this.ParentForm);
|
|
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.IsFixed || !frow.Info.Default.Equals(value)))
|
|
{
|
|
frow.Define(value);
|
|
}
|
|
else if(frow.IsFixed)
|
|
{
|
|
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 = (enumscombo.Tag as FieldsEditorRow);
|
|
|
|
// 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;
|
|
DataGridViewRow row = null;
|
|
|
|
// Any row selected?
|
|
if(fieldslist.SelectedRows.Count > 0)
|
|
{
|
|
// Get selected row
|
|
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;
|
|
Console.WriteLine(cellrect.Height.ToString());
|
|
browsebutton.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
HideBrowseButton();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HideBrowseButton();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HideBrowseButton();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|