/// <summary> /// Fills propertgrid with the data of the selected hypothesis /// </summary> /// <param name="hypothesisId">Id of the hypothesis to take data from</param> private void FillPropertyGrid(int hypothesisId) { HypothesisStruct hypothesis = this.resultBrowser.GetHypothese(hypothesisId); PropertyTable table = new PropertyTable(); string antecedentText = string.Empty; string succedentText = string.Empty; #region Filling in name, antecedent, succedent, condition, first set, second set if ((this.taskType == "LISpMinerTasks.SDKLTask") || (this.taskType == "LISpMinerTasks.CFTask") || (this.taskType == "LISpMinerTasks.SDCFTask") || (this.taskType == "LISpMinerTasks.KLTask")) { antecedentText = resManager.GetString("RowAttribute"); } else { antecedentText = resManager.GetString("ColumnAntecedent"); } if ((this.taskType == "LISpMinerTasks.SDKLTask") || (this.taskType == "LISpMinerTasks.KLTask")) { succedentText = resManager.GetString("ColumnAttribute"); } else { if ((this.taskType == "LISpMinerTasks.CFTask") || (this.taskType == "LISpMinerTasks.SDCFTask")) { succedentText = ""; } else { succedentText = resManager.GetString("ColumnSuccedent"); } } //name PropertySpec hName = new PropertySpec( resManager.GetString("ColumnHypothesisName"), typeof(string), resManager.GetString("HypothesisData"), resManager.GetString("HypothesisData"), FerdaResult.GetHypothesisName(hypothesis) ); hName.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hName); table[resManager.GetString("ColumnHypothesisName")] = FerdaResult.GetHypothesisName(hypothesis); //antecedent PropertySpec hAntecedent = new PropertySpec( antecedentText, typeof(string), resManager.GetString("HypothesisData"), resManager.GetString("HypothesisData"), FerdaResult.GetAntecedentString(hypothesis) ); hAntecedent.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hAntecedent); table[antecedentText] = FerdaResult.GetAntecedentString(hypothesis); //succedent if (succedentText != String.Empty) { PropertySpec hSuccedent = new PropertySpec( succedentText, typeof(string), resManager.GetString("HypothesisData"), resManager.GetString("HypothesisData"), FerdaResult.GetSuccedentString(hypothesis) ); hSuccedent.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hSuccedent); table[succedentText] = FerdaResult.GetSuccedentString(hypothesis); } //condition PropertySpec hCondition = new PropertySpec( resManager.GetString("ColumnCondition"), typeof(string), resManager.GetString("HypothesisData"), resManager.GetString("HypothesisData"), FerdaResult.GetConditionString(hypothesis) ); hCondition.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hCondition); table[resManager.GetString("ColumnCondition")] = FerdaResult.GetConditionString(hypothesis); //first set string temp1 = FerdaResult.GetFirstSetString(hypothesis); if(!(temp1.CompareTo(String.Empty) == 0)) { PropertySpec hFirstSet = new PropertySpec( "1" + resManager.GetString("FirstSet"), typeof(string), resManager.GetString("HypothesisData"), resManager.GetString("HypothesisData"), temp1 ); hFirstSet.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hFirstSet); table["1" + resManager.GetString("FirstSet")] = temp1; } //second set temp1 = FerdaResult.GetSecondSetString(hypothesis); if (!(temp1.CompareTo(String.Empty) == 0)) { PropertySpec hSecondSet = new PropertySpec( "2" + resManager.GetString("SecondSet"), typeof(string), resManager.GetString("HypothesisData"), resManager.GetString("HypothesisData"), temp1 ); hSecondSet.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hSecondSet); table["2" + resManager.GetString("SecondSet")] = temp1; } #endregion #region Used quantifiers and their values //used quantifiers and their values List<string> names = this.resultBrowser.GetAllQuantifierNames(); double[] quantifiers = this.resultBrowser.ReadAllQuantifiersFromCache(hypothesisId, Convert.ToInt32(this.NumericUpDownDecimals.Value)); for (int i = 0; i < quantifiers.Length; i++) { PropertySpec hQuantifier = new PropertySpec( names[i], typeof(double), resManager.GetString("AppliedQuantifiers"), resManager.GetString("AppliedQuantifiers"), quantifiers[i] ); hQuantifier.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hQuantifier); table[names[i]] = quantifiers[i]; } #endregion #region Contingency tables int i1 = 1; int j1 = 1; if (FerdaResult.IsFFT(hypothesis)) { foreach (int[] row in hypothesis.quantifierSetting.firstContingencyTableRows) { foreach (int value in row) { string temp = String.Empty; switch (i1) { case 1: if (j1 == 1) { temp = "a"; } else { temp = "b"; } break; default: if (j1 == 1) { temp = "c"; } else { temp = "d"; } break; } PropertySpec hValue = new PropertySpec( temp, typeof(int), "1. " + resManager.GetString("ContingencyTable"), "1. " + resManager.GetString("ContingencyTable"), value ); hValue.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hValue); table[temp] = value; j1++; } j1 = 1; i1++; } i1 = 1; j1 = 1; foreach (int[] row in hypothesis.quantifierSetting.secondContingencyTableRows) { foreach (int value in row) { string temp = String.Empty; switch (i1) { case 1: if (j1 == 1) { temp = "a"; } else { temp = "b"; } break; default: if (j1 == 1) { temp = "c"; } else { temp = "d"; } break; } PropertySpec hValue = new PropertySpec( temp, typeof(int), "2. " + resManager.GetString("ContingencyTable"), "2. " + resManager.GetString("ContingencyTable"), value ); hValue.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hValue); table[temp] = value; j1++; } j1 = 1; i1++; } } else { foreach (int[] row in hypothesis.quantifierSetting.firstContingencyTableRows) { foreach (int value in row) { string antName = i1.ToString(); string sucName = j1.ToString(); if ((this.taskType == "LISpMinerTasks.SDKLTask") || (this.taskType == "LISpMinerTasks.KLTask")) { foreach (LiteralStruct literal in hypothesis.literals) { if (literal.cedentType == CedentEnum.Antecedent) { if (literal.categoriesNames.Length > (i1-1)) { antName = literal.categoriesNames[(i1-1)]; } break; } } foreach (LiteralStruct literal in hypothesis.literals) { if (literal.cedentType == CedentEnum.Succedent) { if (literal.categoriesNames.Length > (j1-1)) { sucName = literal.categoriesNames[(j1-1)]; } break; } } } else if ((this.taskType == "LISpMinerTasks.SDCFTask") || (this.taskType == "LISpMinerTasks.CFTask")) { foreach (LiteralStruct literal in hypothesis.literals) { if (literal.cedentType == CedentEnum.Antecedent) { if (literal.categoriesNames.Length > (j1-1)) { antName = literal.categoriesNames[(j1-1)]; } break; } } sucName = String.Empty; } if (sucName != String.Empty) { PropertySpec hValue = new PropertySpec( antName.ToString() + "-" + sucName.ToString(), typeof(int), "1. " + resManager.GetString("ContingencyTable"), "1. " + resManager.GetString("ContingencyTable"), value ); hValue.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hValue); table[antName.ToString() + "-" + sucName.ToString()] = value; } else { PropertySpec hValue = new PropertySpec( antName.ToString(), typeof(int), "1. " + resManager.GetString("ContingencyTable"), "1. " + resManager.GetString("ContingencyTable"), value ); hValue.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hValue); table[antName.ToString()] = value; } j1++; } j1 = 1; i1++; } i1 = 1; j1 = 1; foreach (int[] row in hypothesis.quantifierSetting.secondContingencyTableRows) { foreach (int value in row) { string antName = i1.ToString(); string sucName = j1.ToString(); if ((this.taskType == "LISpMinerTasks.SDKLTask") || (this.taskType == "LISpMinerTasks.KLTask")) { foreach (LiteralStruct literal in hypothesis.literals) { if (literal.cedentType == CedentEnum.Antecedent) { if (literal.categoriesNames.Length > (i1 - 1)) { antName = literal.categoriesNames[(i1 - 1)]; } break; } } foreach (LiteralStruct literal in hypothesis.literals) { if (literal.cedentType == CedentEnum.Succedent) { if (literal.categoriesNames.Length > (j1 - 1)) { sucName = literal.categoriesNames[(j1 - 1)]; } break; } } } else if ((this.taskType == "LISpMinerTasks.SDCFTask") || (this.taskType == "LISpMinerTasks.CFTask")) { foreach (LiteralStruct literal in hypothesis.literals) { if (literal.cedentType == CedentEnum.Antecedent) { if (literal.categoriesNames.Length > (j1 - 1)) { antName = literal.categoriesNames[(j1 - 1)]; } break; } } sucName = String.Empty; } if (sucName != String.Empty) { PropertySpec hValue = new PropertySpec( antName.ToString() + "-" + sucName.ToString(), typeof(int), "1. " + resManager.GetString("ContingencyTable"), "1. " + resManager.GetString("ContingencyTable"), value ); hValue.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hValue); table[antName.ToString() + "-" + sucName.ToString()] = value; } else { PropertySpec hValue = new PropertySpec( antName.ToString(), typeof(int), "2. " + resManager.GetString("ContingencyTable"), "2. " + resManager.GetString("ContingencyTable"), value ); hValue.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(hValue); table[antName.ToString()] = value; } j1++; } j1 = 1; i1++; } } #endregion #region Statistics functions foreach (CountedValues value in this.resultBrowser.ReadStatisticsFromCache(hypothesisId, Convert.ToInt32(this.NumericUpDownDecimals.Value))) { string temp = String.Empty; temp = value.Value.ToString(); PropertySpec statistics = new PropertySpec( value.Name, typeof(string), this.resManager.GetString("Statistics"), this.resManager.GetString("Statistics"), temp ); statistics.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; table.Properties.Add(statistics); table[value.Name] = temp; } #endregion this.displayer.Reset(); this.displayer.OtherObjectAdapt(table); }
/// <summary> /// A special method to refresh the property grid with a new property bag, /// that can be called from other threads than the owner thread. /// </summary> /// <param name="bag">A bag with the right values of the properties</param> private void SetPropertyGrid(PropertyTable bag) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (this.InvokeRequired) { RefreshDelegate d = new RefreshDelegate(SetPropertyGrid); this.Invoke(d, new object[] { bag }); } else { this.SelectedObject = bag; } }
/// <summary> /// Adapts the PropertyGrid when another object than a box is selected. /// Uses the SelectedObject as its object. /// </summary> /// <param name="objectProperties">The /// <see cref="T:Ferda.FrontEnd.External.PropertyTable"/> object /// that contains information about the object. /// </param> public void OtherObjectAdapt(PropertyTable objectProperties) { if (IsDisposed) { return; } this.SelectedObject = objectProperties; }
/// <summary> /// Creates a property for a "::Ferda::Modules::StringT". There can be not /// only string, but also types of ComboBoxes and this method decides, which /// FerdaPropertySpec will be created /// </summary> /// <param name="pinfo">Information about the property</param> /// <param name="box">Box where it finds the other property</param> /// <param name="bag">Bag where to put the FerdaPropertySpec</param> protected void CreateStringProperty(PropertyInfo pinfo, IBoxModule box, PropertyTable bag) { FerdaPropertySpec ps; SelectString[] array; //determining the type of the property array = box.GetPropertyOptions(pinfo.name); if (array.Length == 0) //it is a normal string property { SocketInfo si = box.MadeInCreator.GetSocket(pinfo.name); ps = new FerdaPropertySpec(si.label, typeof(string), false); ps.Category = pinfo.categoryName; ps.Description = si.hint; if (box.IsPropertyReadOnly(pinfo.name) || box.GetPropertySocking(pinfo.name)) { ps.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; } bag.Properties.Add(ps); //adding the asynch stuff AddAsyncTemporary(pinfo.name, "System.String", !IsOneBoxSelected); } else //a combo-box should be used { //if there are more boxes selected, the property should not be added if (!IsOneBoxSelected) { return; } if (box.ArePropertyOptionsObligatory(pinfo.name)) //this means user cannot edit values { SocketInfo si = box.MadeInCreator.GetSocket(pinfo.name); ps = new FerdaPropertySpec(si.label, typeof(StringSequence), false); ps.Category = pinfo.categoryName; ps.Description = si.hint; //atributes if (box.IsPropertyReadOnly(pinfo.name) || box.GetPropertySocking(pinfo.name)) { ps.Attributes = new Attribute[] { ReadOnlyAttribute.Yes, new EditorAttribute(typeof(StringComboEditor), typeof(System.Drawing.Design.UITypeEditor)), new TypeConverterAttribute(typeof(StringSequenceConverter)) }; } else { ps.Attributes = new Attribute[] { new EditorAttribute(typeof(StringComboEditor), typeof(System.Drawing.Design.UITypeEditor)), new TypeConverterAttribute(typeof(StringSequenceConverter)) }; } //adding to the bag bag.Properties.Add(ps); } else //user can add his own option to the string selection { SocketInfo si = box.MadeInCreator.GetSocket(pinfo.name); ps = new FerdaPropertySpec(si.label, typeof(StringSequence), false); ps.Description = si.hint; ps.Category = pinfo.categoryName; //atributes if (box.IsPropertyReadOnly(pinfo.name) || box.GetPropertySocking(pinfo.name)) { ps.Attributes = new Attribute[] { ReadOnlyAttribute.Yes, new EditorAttribute(typeof(StringComboAddingEditor), typeof(System.Drawing.Design.UITypeEditor)), new TypeConverterAttribute(typeof(StringSequenceConverter)) }; } else { ps.Attributes = new Attribute[] { new EditorAttribute(typeof(StringComboAddingEditor), typeof(System.Drawing.Design.UITypeEditor)), new TypeConverterAttribute(typeof(StringSequenceConverter)) }; } //adding to the bag bag.Properties.Add(ps); } //adding the asynch stuff if (IsOneBoxSelected) { AddAsyncTemporary(pinfo.name, "Ferda.FrontEnd.Properties.StringSequence", false); } } }
/// <summary> /// Adds the common properties of the selected boxes on the desktop /// to the <see cref="T:Ferda.FrontEnd.External.PropertyTable"/> /// object. Common properties mean that all the boxes have the property /// of that name and the same type. /// </summary> /// <param name="boxes">The boxes from which the properties should /// be created</param> /// <returns>A <see cref="T:Ferda.FrontEnd.External.PropertyTable"/> /// object filled with common properties</returns> protected PropertyTable CreatePropertiesFromMoreBoxes(IList<IBoxModule> boxes) { //structure where the common properties will be stored List<PropertyInfo> commonProperties = new List<PropertyInfo>(); //initializing a new bag PropertyTable bag = new PropertyTable(); bag.GetValue += new PropertySpecEventHandler(propertyBag_GetValue); bag.SetValue += new PropertySpecEventHandler(propertyBag_SetValue); //increasing the number of clicks of the user on the desktop bag.ClickID = IncreaseClickID(); //first creator - properties from this creator will be //compared to creators from other boxes IBoxModuleFactoryCreator firstCreator = boxes[0].MadeInCreator; //iterating throutg all the properties of the first selected box foreach (PropertyInfo info in firstCreator.Properties) { bool contains = true; //all the boxes should include this property for (int i = 1; i < boxes.Count; i++) { contains = ContainsPropertyInfo(boxes[i].MadeInCreator, info); if (!contains) { break; } } if (contains) { commonProperties.Add(info); } } //iterating through all the common properties foreach (PropertyInfo pinfo in commonProperties) { FerdaPropertySpec ps; if (pinfo.visible) { //two known other property types - StringSeqT and CategoriesT if (pinfo.typeClassIceId == "::Ferda::Modules::StringSeqT" || pinfo.typeClassIceId == "::Ferda::Modules::CategoriesT") { //CreateOtherProperty(pinfo, box, bag); continue; } //strings are also dealt with separatelly if (pinfo.typeClassIceId == "::Ferda::Modules::StringT") { //deterimining if we can use a module to set the property //bool canBeSetWithModule = true; //foreach (IBoxModule box in boxes) //{ // canBeSetWithModule = // box.IsPropertySetWithSettingModule(pinfo.name); //} ////we can set the property with a module (ODBC Connection string) //if (canBeSetWithModule) //{ // string normalType = GetNormalType(pinfo.typeClassIceId); // if (normalType != "") // { // //getting the displayable name of the property // SocketInfo si = firstCreator.GetSocket(pinfo.name); // ps = new FerdaPropertySpec(si.label, normalType, false); // ps.Category = pinfo.categoryName; // //getting the hint // ps.Description = si.hint; // //setting the attributes of the property // if (IsPropertyReadOnlyMoreBoxes(boxes, pinfo.name) || // IsPropertySockedMoreBoxes(boxes, pinfo.name)) // { // ps.Attributes = new Attribute[] // { // ReadOnlyAttribute.Yes, // new TypeConverterAttribute(typeof(OtherPropertyAddingConverter)), // new EditorAttribute(typeof(OtherPropertyEditor), // typeof(System.Drawing.Design.UITypeEditor)) // }; // } // else // { // ps.Attributes = new Attribute[] // { // new TypeConverterAttribute(typeof(OtherPropertyAddingConverter)), // new EditorAttribute(typeof(OtherPropertyEditor), // typeof(System.Drawing.Design.UITypeEditor)) // }; // } // //getting the property to the bag // bag.Properties.Add(ps); // //adding the asynchronous stuff // AddAsyncTemporary(pinfo.name, "Ferda.FrontEnd.Properties.OtherProperty", true); // } //} //else { //it is a normal string property CreateStringProperty(pinfo, boxes[0], bag); } } else { string normalType = GetNormalType(pinfo.typeClassIceId); //This is a normal type, creating a normal property for it if (normalType != "") { //getting the displayable name of the property SocketInfo si = firstCreator.GetSocket(pinfo.name); ps = new FerdaPropertySpec(si.label, normalType, false); ps.Category = pinfo.categoryName; //geting the socket information about the category ps.Description = si.hint; //it is readonly or it is already there as a socket - //cannot edit "socketed" value if (IsPropertyReadOnlyMoreBoxes(boxes, pinfo.name) || IsPropertySockedMoreBoxes(boxes, pinfo.name)) { ps.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; } bag.Properties.Add(ps); //adding the asynchronous stuff AddAsyncTemporary(pinfo.name, normalType, true); } else { throw new ApplicationException("Wierd type that we dont know!!!"); } } } } return bag; }
/// <summary> /// Adds the properties of the selectedBox to the bag /// </summary> /// <param name="box">Box from where the properties should be /// loaded</param> /// <returns>A bag full of properties from the box</returns> protected PropertyTable CreatePropertiesFromBox(IBoxModule box) { //initializing a new bag PropertyTable bag = new PropertyTable(); //increasing the number of clicks of the user on the desktop bag.ClickID = IncreaseClickID(); IBoxModuleFactoryCreator creator = box.MadeInCreator; FerdaPropertySpec ps; bag.GetValue += new PropertySpecEventHandler(propertyBag_GetValue); bag.SetValue += new PropertySpecEventHandler(propertyBag_SetValue); //iterating through all the properties foreach (PropertyInfo pinfo in creator.Properties) { if (pinfo.visible) { if (box.IsPropertySetWithSettingModule(pinfo.name)) { //creating the "other" property if (IsOneBoxSelected) { CreateOtherProperty(pinfo, box, bag); } } else { //creating normal property //two known other property types - StringSeqT and CategoriesT if (pinfo.typeClassIceId == "::Ferda::Modules::StringSeqT" || pinfo.typeClassIceId == "::Ferda::Modules::CategoriesT") { CreateOtherProperty(pinfo, box, bag); continue; } //strings are also dealt with separatelly if (pinfo.typeClassIceId == "::Ferda::Modules::StringT") { CreateStringProperty(pinfo, box, bag); } else { string normalType = GetNormalType(pinfo.typeClassIceId); //This is a normal type, creating a normal property for it if (normalType != "") { //getting the displayable name of the property SocketInfo si = creator.GetSocket(pinfo.name); ps = new FerdaPropertySpec(si.label, normalType, false); ps.Category = pinfo.categoryName; //geting the socket information about the category ps.Description = si.hint; //it is readonly or it is already there as a socket - //cannot edit "socketed" value if (box.IsPropertyReadOnly(pinfo.name) || box.GetPropertySocking(pinfo.name)) { ps.Attributes = new Attribute[] { ReadOnlyAttribute.Yes }; } bag.Properties.Add(ps); AddAsyncTemporary(pinfo.name, normalType, false); } else { //throw new ApplicationException("Wierd type that we dont know!!!"); } } } } } return bag; }
/// <summary> /// Creates a property for all other properties /// </summary> /// <param name="pinfo">Information about the property</param> /// <param name="box">Box where it finds the other property</param> /// <param name="bag">Bag where to put the propertyspec</param> protected void CreateOtherProperty(PropertyInfo pinfo, IBoxModule box, PropertyTable bag) { FerdaPropertySpec ps; SocketInfo si = box.MadeInCreator.GetSocket(pinfo.name); ps = new FerdaPropertySpec(si.label, typeof(OtherProperty), false); ps.Description = si.hint; ps.Category = pinfo.categoryName; //properties that user can set without executing the module (ODBC Connection string) if (box.IsPossibleToSetWithAbout(pinfo.name)) //using a OtherPropertyAddingConverter { if (box.IsPropertyReadOnly(pinfo.name) || box.GetPropertySocking(pinfo.name)) { ps.Attributes = new Attribute[] { ReadOnlyAttribute.Yes, new TypeConverterAttribute(typeof(OtherPropertyAddingConverter)), new EditorAttribute(typeof(OtherPropertyEditor), typeof(System.Drawing.Design.UITypeEditor)) }; } else { ps.Attributes = new Attribute[] { new TypeConverterAttribute(typeof(OtherPropertyAddingConverter)), new EditorAttribute(typeof(OtherPropertyEditor), typeof(System.Drawing.Design.UITypeEditor)) }; } } else //using a OtherPropertyConverter { if (box.IsPropertyReadOnly(pinfo.name) || box.GetPropertySocking(pinfo.name)) { ps.Attributes = new Attribute[] { ReadOnlyAttribute.Yes, new TypeConverterAttribute(typeof(OtherPropertyConverter)), new EditorAttribute(typeof(OtherPropertyEditor), typeof(System.Drawing.Design.UITypeEditor)) }; } else { ps.Attributes = new Attribute[] { new TypeConverterAttribute(typeof(OtherPropertyConverter)), new EditorAttribute(typeof(OtherPropertyEditor), typeof(System.Drawing.Design.UITypeEditor)) }; } } if (IsOneBoxSelected) { AddAsyncTemporary(pinfo.name, "Ferda.FrontEnd.Properties.OtherProperty", false); } bag.Properties.Add(ps); }
/// <summary> /// Adds to the <see cref="T:Ferda.FrontEnd.External.PropertyTable"/> table /// information about sockets of the box /// </summary> /// <param name="propertyTable">Table to put the properties</param> /// <param name="box">Box from where to get the properties</param> protected PropertyTable AddSocketProperties(PropertyTable propertyTable, IBoxModule box) { IBoxModuleFactoryCreator creator = box.MadeInCreator; FerdaPropertySpec ps; foreach (PropertyInfo pinfo in creator.Properties) { //we are not adding the visible and readonly properties if (pinfo.visible && !pinfo.readOnly) { //getting the displayable name of the property SocketInfo si = creator.GetSocket(pinfo.name); //zatim je to udelane takhle if (si.label != "") { ps = new FerdaPropertySpec(si.label, "System.Boolean", true); ps.Category = ResManager.GetString("PropertySocketName"); ps.Description = ResManager.GetString("PropertySocketHint"); propertyTable.Properties.Add(ps); } else { throw new ApplicationException("A not read-only, visible property does not have a label."); } } } return propertyTable; }