/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using JetBrains.Omea.GUIControls; using JetBrains.Omea.OpenAPI; using JetBrains.Omea.FiltersManagement; namespace JetBrains.Omea.CustomProperties { /** * Dialog for configuring the types of custom properties. */ public class CustomPropTypesDlg : DialogBase { private Button _btnOK; private Button _btnCancel; private ColumnHeader columnHeader1; private ColumnHeader columnHeader2; private Button _btnAdd; private ContextMenu _mnuPropType; private MenuItem miAddStringProp; private ListView _lvTypes; private Button _btnDelete; private MenuItem miAddNumberProp; private MenuItem miAddDateProp; /// /// Required designer variable. /// private System.ComponentModel.Container components = null; private MenuItem miAddBoolProp; private readonly List _deletedPropIDs = new List(); private class PropTypeTag { public readonly int PropID; public readonly PropDataType DataType; public PropTypeTag( int propID, PropDataType dataType ) { PropID = propID; DataType = dataType; } } public CustomPropTypesDlg() { InitializeComponent(); } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(CustomPropTypesDlg)); this._btnOK = new System.Windows.Forms.Button(); this._btnCancel = new System.Windows.Forms.Button(); this._lvTypes = new System.Windows.Forms.ListView(); this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); this._btnAdd = new System.Windows.Forms.Button(); this._mnuPropType = new System.Windows.Forms.ContextMenu(); this.miAddStringProp = new System.Windows.Forms.MenuItem(); this.miAddNumberProp = new System.Windows.Forms.MenuItem(); this.miAddDateProp = new System.Windows.Forms.MenuItem(); this.miAddBoolProp = new System.Windows.Forms.MenuItem(); this._btnDelete = new System.Windows.Forms.Button(); this.SuspendLayout(); // // _btnOK // this._btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this._btnOK.DialogResult = System.Windows.Forms.DialogResult.OK; this._btnOK.FlatStyle = System.Windows.Forms.FlatStyle.System; this._btnOK.Location = new System.Drawing.Point(264, 227); this._btnOK.Name = "_btnOK"; this._btnOK.TabIndex = 0; this._btnOK.Text = "OK"; // // _btnCancel // this._btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this._btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this._btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.System; this._btnCancel.Location = new System.Drawing.Point(348, 227); this._btnCancel.Name = "_btnCancel"; this._btnCancel.TabIndex = 1; this._btnCancel.Text = "Cancel"; // // _lvTypes // this._lvTypes.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this._lvTypes.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader1, this.columnHeader2}); this._lvTypes.FullRowSelect = true; this._lvTypes.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; this._lvTypes.HideSelection = false; this._lvTypes.Location = new System.Drawing.Point(4, 8); this._lvTypes.MultiSelect = false; this._lvTypes.Name = "_lvTypes"; this._lvTypes.Size = new System.Drawing.Size(336, 211); this._lvTypes.TabIndex = 2; this._lvTypes.View = System.Windows.Forms.View.Details; this._lvTypes.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this._lvTypes_AfterLabelEdit); this._lvTypes.SelectedIndexChanged += new System.EventHandler(this._lvTypes_SelectedIndexChanged); // // columnHeader1 // this.columnHeader1.Text = "Name"; this.columnHeader1.Width = 92; // // columnHeader2 // this.columnHeader2.Text = "Type"; this.columnHeader2.Width = 88; // // _btnAdd // this._btnAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this._btnAdd.FlatStyle = System.Windows.Forms.FlatStyle.System; this._btnAdd.Image = ((System.Drawing.Image)(resources.GetObject("_btnAdd.Image"))); this._btnAdd.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; this._btnAdd.Location = new System.Drawing.Point(348, 8); this._btnAdd.Name = "_btnAdd"; this._btnAdd.TabIndex = 3; this._btnAdd.Text = "Add"; this._btnAdd.Click += new System.EventHandler(this._btnAdd_Click); // // _mnuPropType // this._mnuPropType.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.miAddStringProp, this.miAddNumberProp, this.miAddDateProp, this.miAddBoolProp}); // // miAddStringProp // this.miAddStringProp.Index = 0; this.miAddStringProp.Text = "Add Text Property"; this.miAddStringProp.Click += new System.EventHandler(this.miAddStringProp_Click); // // miAddNumberProp // this.miAddNumberProp.Index = 1; this.miAddNumberProp.Text = "Add Number Property"; this.miAddNumberProp.Click += new System.EventHandler(this.miAddNumberProp_Click); // // miAddDateProp // this.miAddDateProp.Index = 2; this.miAddDateProp.Text = "Add Date Property"; this.miAddDateProp.Click += new System.EventHandler(this.miAddDateProp_Click); // // miAddBoolProp // this.miAddBoolProp.Index = 3; this.miAddBoolProp.Text = "Add Yes/No Property"; this.miAddBoolProp.Click += new System.EventHandler(this.miAddBoolProp_Click); // // _btnDelete // this._btnDelete.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this._btnDelete.FlatStyle = System.Windows.Forms.FlatStyle.System; this._btnDelete.Location = new System.Drawing.Point(348, 40); this._btnDelete.Name = "_btnDelete"; this._btnDelete.TabIndex = 4; this._btnDelete.Text = "Delete"; this._btnDelete.Click += new System.EventHandler(this._btnDelete_Click); // // CustomPropTypesDlg // this.AcceptButton = this._btnOK; this.AutoScaleBaseSize = new System.Drawing.Size(5, 14); this.CancelButton = this._btnCancel; this.ClientSize = new System.Drawing.Size(432, 258); this.Controls.Add(this._btnDelete); this.Controls.Add(this._btnAdd); this.Controls.Add(this._lvTypes); this.Controls.Add(this._btnCancel); this.Controls.Add(this._btnOK); this.MinimumSize = new System.Drawing.Size(288, 196); this.Name = "CustomPropTypesDlg"; this.Text = "Custom Property Types"; this.ResumeLayout(false); } #endregion public void EditCustomPropertyTypes() { IResourceList customPropTypes = Core.ResourceStore.FindResources( "PropType", "Custom", 1 ); foreach( IResource res in customPropTypes ) { string name = res.GetStringProp( Core.Props.Name ); PropDataType dataType = Core.ResourceStore.PropTypes [name].DataType; if ( dataType != PropDataType.Link ) { if ( name.StartsWith( "Custom.") ) { name = name.Substring( 7 ); } ListViewItem lvItem = _lvTypes.Items.Add( name ); lvItem.SubItems.Add( GetDataTypeName( dataType ) ); lvItem.Tag = new PropTypeTag( res.GetIntProp( "ID" ), dataType ); if ( lvItem.Index == 0 ) { lvItem.Selected = true; } } } UpdateButtonState(); if ( ShowDialog( Core.MainWindow ) == DialogResult.OK ) { Core.ResourceAP.RunJob( new MethodInvoker( SaveCustomPropertyTypes ) ); } } private void UpdateButtonState() { _btnDelete.Enabled = (_lvTypes.SelectedItems.Count > 0); } private void _lvTypes_SelectedIndexChanged( object sender, EventArgs e ) { UpdateButtonState(); } private void _btnAdd_Click( object sender, EventArgs e ) { _mnuPropType.Show( _btnAdd, new Point( 0, _btnAdd.Height ) ); } private void miAddStringProp_Click( object sender, EventArgs e ) { AddPropertyType( PropDataType.String ); } private void miAddNumberProp_Click( object sender, EventArgs e ) { AddPropertyType( PropDataType.Int ); } private void miAddDateProp_Click( object sender, EventArgs e ) { AddPropertyType( PropDataType.Date ); } private void miAddBoolProp_Click( object sender, EventArgs e ) { AddPropertyType( PropDataType.Bool ); } private void AddPropertyType( PropDataType dataType ) { _lvTypes.LabelEdit = true; ListViewItem lvItem = _lvTypes.Items.Add( "" ); lvItem.SubItems.Add( GetDataTypeName( dataType ) ); lvItem.Tag = new PropTypeTag( -1, dataType ); lvItem.BeginEdit(); } private static string GetDataTypeName( PropDataType type ) { switch( type ) { case PropDataType.String: return "text"; case PropDataType.Int: return "number"; case PropDataType.Date: return "date"; case PropDataType.Bool: return "yes/no"; default: return "other"; } } private void _lvTypes_AfterLabelEdit( object sender, LabelEditEventArgs e ) { if ( e.Label == null ) { _lvTypes.Items.RemoveAt( e.Item ); return; } if ( PropTypeExists( e.Label, e.Item ) ) { MessageBox.Show( this, "A property type called '" + e.Label + "' already exists. Please choose a different name.", "New Property Type" ); e.CancelEdit = true; _lvTypes.Items [e.Item].BeginEdit(); } else { _lvTypes.Items [e.Item].Selected = true; } _lvTypes.LabelEdit = false; } /** * Checks if the property type with the specified name is either registered * in the resource store (and not deleted in the dialog) or added in the dialog * and not yet saved. */ private bool PropTypeExists( string name, int skipItem ) { IResourceStore store = Core.ResourceStore; if ( store.PropTypes.Exist( "Custom." + name ) ) { int propID = store.PropTypes ["Custom." + name].Id; if ( _deletedPropIDs.IndexOf( propID ) < 0 ) { return true; } } for( int i=0; i<_lvTypes.Items.Count; i++ ) { if ( i != skipItem && _lvTypes.Items [i].Text == name ) { return true; } } return false; } private void _btnDelete_Click( object sender, EventArgs e ) { if ( _lvTypes.SelectedItems.Count > 0 ) { ListViewItem lvItem = _lvTypes.SelectedItems [0]; PropTypeTag tag = (PropTypeTag) lvItem.Tag; if ( tag != null ) { if ( tag.PropID >= 0 ) { string warnText = ". Are you sure you wish to delete it?"; IResourceList resList = Core.ResourceStore.FindResourcesWithProp( null, tag.PropID ); IResourceList conditions = Core.ResourceStore.FindResources( SelectionType.Normal, FilterManagerProps.ConditionResName, "ApplicableToProp", "Custom." + lvItem.Text ); DialogResult dr = DialogResult.Yes; if ( resList.Count > 0 ) { if( conditions.Count > 0 ) { warnText = resList.Count + " resources have the property " + lvItem.Text + " and " + conditions.Count + " views use it" + warnText; } else { warnText = resList.Count + " resources have the property " + lvItem.Text + warnText; } dr = MessageBox.Show( Core.MainWindow, warnText, "Delete Custom Property Type", MessageBoxButtons.YesNo ); } if ( dr == DialogResult.Yes ) { _deletedPropIDs.Add( tag.PropID ); _lvTypes.Items.Remove( lvItem ); } } else { _lvTypes.Items.Remove( lvItem ); } } } } private void SaveCustomPropertyTypes() { IResourceStore store = Core.ResourceStore; foreach( int propID in _deletedPropIDs ) { Core.DisplayColumnManager.RemoveAvailableColumn( null, store.PropTypes [propID].Name ); DeleteCustomPropCondition( propID ); store.PropTypes.Delete( propID ); } foreach( ListViewItem lvItem in _lvTypes.Items ) { PropTypeTag tag = (PropTypeTag) lvItem.Tag; if ( tag.PropID == -1 ) { string propName = "Custom." + lvItem.Text; int propID = store.PropTypes.Register( propName, tag.DataType ); store.PropTypes.RegisterDisplayName( propID, lvItem.Text ); IResource res = store.FindUniqueResource( "PropType", Core.Props.Name, propName ); res.SetProp( "Custom", 1 ); Core.DisplayColumnManager.RegisterAvailableColumn( null, new ColumnDescriptor( propName, 100 ) ); RegisterCustomPropCondition( propID ); } } } /** * Registers a condition allowing to use the custom property with the specified * ID in views. */ private static void RegisterCustomPropCondition( int propID ) { IPropType propType = Core.ResourceStore.PropTypes [propID]; string condName = GetConditionName( propType ); IResource condition = null; if ( propType.DataType == PropDataType.String || propType.DataType == PropDataType.Date ) { condition = Core.FilterRegistry.CreateConditionTemplate( condName, condName, null, ConditionOp.Eq, propType.Name ); } else if ( propType.DataType == PropDataType.Int ) { condition = Core.FilterRegistry.CreateConditionTemplate( condName, condName, null, ConditionOp.InRange, propType.Name, Int32.MinValue.ToString(), Int32.MaxValue.ToString() ); } else if ( propType.DataType == PropDataType.Bool ) { condition = Core.FilterRegistry.CreateStandardCondition( condName, condName, null, propType.Name, ConditionOp.HasProp ); } if ( condition != null ) { Core.FilterRegistry.AssociateConditionWithGroup( condition, "Custom Property Conditions" ); } } private static void DeleteCustomPropCondition( int propID ) { IPropType propType = Core.ResourceStore.PropTypes [propID]; // remove condition template which is made from this property string resTypeName = (propType.DataType != PropDataType.Bool) ? FilterManagerProps.ConditionTemplateResName : FilterManagerProps.ConditionResName; IResourceList conditions = Core.ResourceStore.FindResources( resTypeName, Core.Props.Name, GetConditionName( propType ) ); if ( conditions.Count == 1 ) { conditions[ 0 ].Delete(); } // remove views which use conditions based on condition templates conditions = Core.ResourceStore.FindResources( SelectionType.Normal, FilterManagerProps.ConditionResName, "ApplicableToProp", propType.Name ); IResourceList views = Core.ResourceStore.EmptyResourceList; foreach( IResource res in conditions ) { views = views.Union( res.GetLinksOfType( FilterManagerProps.ViewResName, "LinkedCondition" )); } foreach( IResource res in views ) { Core.FilterRegistry.DeleteView( res ); } } private static string GetConditionName( IPropType propType ) { switch( propType.DataType ) { case PropDataType.String: return "'" + propType.DisplayName + "' is equal to %value%"; case PropDataType.Int: return "'" + propType.DisplayName + "' is in %range%"; case PropDataType.Date: return "'" + propType.DisplayName + "' is in %range%"; case PropDataType.Bool: return "Has property '" + propType.DisplayName + "'"; default: return propType.DisplayName; } } } }