/// <summary>
        /// User has changed the value of a cell.
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="e">Event parameters</param>
        private void OnCellValueChanged(object sender, GridCellsChangedArgs e)
        {
            this.explorerPresenter.CommandHistory.ModelChanged -= this.OnModelChanged;

            foreach (GridCellChangedArgs cell in e.ChangedCells)
            {
                try
                {
                    //need to subtract one for column index of the cell due to description column
                    Model            childmodel = this.childrenWithSameType[cell.ColIndex - 1] as Model;
                    VariableProperty property   = properties[cell.ColIndex - 1][cell.RowIndex];

                    object newValue = GetNewCellValue(property, cell.NewValue);
                    this.SetPropertyValue(childmodel, property, newValue);
                    if (newValue.GetType().IsEnum)
                    {
                        newValue = VariableProperty.GetEnumDescription(newValue as Enum);
                    }
                    grid.DataSource.Rows[cell.RowIndex][cell.ColIndex] = newValue;
                }
                catch (Exception ex)
                {
                    explorerPresenter.MainPresenter.ShowError(ex);
                }
            }

            this.explorerPresenter.CommandHistory.ModelChanged += this.OnModelChanged;
        }
        /// <summary>
        /// Called when the view is changed. Updates the model's state.
        /// </summary>
        /// <param name="sender">Sending object.</param>
        /// <param name="args">Event data.</param>
        protected void OnViewChanged(object sender, PropertyChangedEventArgs args)
        {
            // We don't want to refresh the entire view after applying the change
            // to the model, so we need to temporarily detach the ModelChanged handler.
            //presenter.CommandHistory.ModelChanged -= OnModelChanged;

            // Figure out which property of which object is being changed.
            PropertyInfo property      = propertyMap[args.ID].Property;
            object       changedObject = propertyMap[args.ID].Model;

            object newValue = args.NewValue;

            // When using a multi-line text editor for an IEnumerable property, the
            // new value returned from the view will contain the enumerable with one
            // element per line. The 'canonical' form of an enumerable as recognised by
            // the StringToObject function is csv. Therefore we need to convert from
            // lf-separated elements to comma-separated elements. This should probably
            // occur somewhere else.
            DisplayAttribute attrib;

            if (newValue is string str && property.PropertyType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(property.PropertyType) && (attrib = property.GetCustomAttribute <DisplayAttribute>()) != null && attrib.Type == DisplayType.MultiLineText)
            {
                newValue = string.Join(",", str.Split(Environment.NewLine.ToCharArray()));
            }

            if (property.PropertyType.IsEnum && newValue is string enumDescription)
            {
                foreach (Enum value in Enum.GetValues(property.PropertyType))
                {
                    if (VariableProperty.GetEnumDescription(value) == enumDescription)
                    {
                        newValue = Enum.GetName(property.PropertyType, value);
                        break;
                    }
                }
            }

            // In some cases, the new value passed back from the view may be
            // already of the correct type. For example a boolean property
            // is editable via a checkbutton, so the view will return a bool.
            // However, most numbers are just rendered using an entry widget,
            // so the value from the view will be a string (e.g. 1e-6).
            if ((newValue == null || newValue is string) && property.PropertyType != typeof(string))
            {
                if (newValue is string modelName && typeof(IModel).IsAssignableFrom(property.PropertyType))
                {
                    newValue = model.FindAllInScope(modelName).FirstOrDefault(m => property.PropertyType.IsAssignableFrom(m.GetType()));
                }
                else
                {
                    newValue = ReflectionUtilities.StringToObject(property.PropertyType, (string)newValue, CultureInfo.CurrentCulture);
                }
            }
Beispiel #3
0
        /// <summary>
        /// User has changed the value of a cell. Validate the change
        /// apply the change.
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="args">Event parameters</param>
        private void OnCellsChanged(object sender, GridCellsChangedArgs args)
        {
            List <ChangeProperty.Property> changes = new List <ChangeProperty.Property>();

            foreach (GridCellChangedArgs cell in args.ChangedCells)
            {
                if (cell.NewValue == cell.OldValue)
                {
                    continue; // silently fail
                }
                // If there are multiple changed cells, each change will be
                // individually undoable.
                IVariable property = GetProperty(cell.RowIndex, cell.ColIndex);
                if (property == null)
                {
                    continue;
                }

                // Parse the input string to the appropriate type.
                object newValue = GetNewPropertyValue(property, cell);

                // Update the value of the model's property.
                SetPropertyValue(property, newValue);

                // Update the value shown in the grid.
                object val = GetCellValue(property, cell.RowIndex, cell.ColIndex);
                // Special handling for enumerations, as we want to display the description, not the value
                if (val.GetType().IsEnum)
                {
                    val = VariableProperty.GetEnumDescription(val as Enum);
                }
                grid.DataSource.Rows[cell.RowIndex][cell.ColIndex] = val;
            }

            UpdateReadOnlyProperties();
        }
Beispiel #4
0
        /// <summary>
        /// Format the grid.
        /// </summary>
        private void FormatGrid()
        {
            for (int i = 0; i < properties.Count; i++)
            {
                IGridCell cell = grid.GetCell(1, i);

                if (properties[i] is VariableObject)
                {
                    cell.EditorType = EditorTypeEnum.TextBox;

                    grid.SetRowAsSeparator(i, true);
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.TableName)
                {
                    cell.EditorType      = EditorTypeEnum.DropDown;
                    cell.DropDownStrings = storage.Reader.TableNames.ToArray();
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.CultivarName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    IPlant crop = GetCrop(properties);
                    if (crop != null)
                    {
                        cell.DropDownStrings = GetCultivarNames(crop);
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.FileName)
                {
                    cell.EditorType = EditorTypeEnum.Button;
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.FieldName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = GetFieldNames();
                    if (fieldNames != null)
                    {
                        fieldNames.Insert(0, string.Empty);
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.ResidueName &&
                         model is SurfaceOrganicMatter)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    string[] fieldNames = GetResidueNames();
                    if (fieldNames != null)
                    {
                        cell.DropDownStrings = fieldNames;
                    }
                }
                else if (properties[i].Display != null &&
                         (properties[i].Display.Type == DisplayType.CLEMResourceName))
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = new List <string>();
                    fieldNames.AddRange(this.GetCLEMResourceNames(this.properties[i].Display.CLEMResourceNameResourceGroups));

                    // add any extras elements provided to the list.
                    if (this.properties[i].Display.CLEMExtraEntries != null)
                    {
                        fieldNames.AddRange(this.properties[i].Display.CLEMExtraEntries);
                    }

                    if (fieldNames.Count != 0)
                    {
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         (properties[i].Display.Type == DisplayType.CLEMCropFileName))
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = new List <string>();
                    Simulation    clemParent = Apsim.Parent(this.model, typeof(Simulation)) as Simulation;
                    // get crop file names
                    fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileCrop)).Select(a => a.Name).ToList());
                    fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileSQLiteCrop)).Select(a => a.Name).ToList());
                    if (fieldNames.Count != 0)
                    {
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         (properties[i].Display.Type == DisplayType.CLEMGraspFileName))
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = new List <string>();
                    Simulation    clemParent = Apsim.Parent(this.model, typeof(Simulation)) as Simulation;
                    // get GRASP file names
                    fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileGRASP)).Select(a => a.Name).ToList());
                    fieldNames.AddRange(Apsim.ChildrenRecursively(clemParent, typeof(FileSQLiteGRASP)).Select(a => a.Name).ToList());
                    if (fieldNames.Count != 0)
                    {
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.Model)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;

                    string[] modelNames = GetModelNames(properties[i].Display.ModelType);
                    if (modelNames != null)
                    {
                        cell.DropDownStrings = modelNames;
                    }
                }
                else
                {
                    object cellValue = properties[i].ValueWithArrayHandling;
                    if (cellValue is DateTime)
                    {
                        cell.EditorType = EditorTypeEnum.DateTime;
                    }
                    else if (cellValue is bool)
                    {
                        cell.EditorType = EditorTypeEnum.Boolean;
                    }
                    else if (cellValue.GetType().IsEnum)
                    {
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = VariableProperty.EnumToStrings(cellValue);
                        Enum cellValueAsEnum = cellValue as Enum;
                        if (cellValueAsEnum != null)
                        {
                            cell.Value = VariableProperty.GetEnumDescription(cellValueAsEnum);
                        }
                    }
                    else if (cellValue.GetType() == typeof(IPlant))
                    {
                        cell.EditorType = EditorTypeEnum.DropDown;
                        List <string> cropNames = new List <string>();
                        foreach (Model crop in Apsim.FindAll(model, typeof(IPlant)))
                        {
                            cropNames.Add(crop.Name);
                        }

                        cell.DropDownStrings = cropNames.ToArray();
                    }
                    else if (properties[i].DataType == typeof(IPlant))
                    {
                        List <string> plantNames = Apsim.FindAll(model, typeof(IPlant)).Select(m => m.Name).ToList();
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = plantNames.ToArray();
                    }
                    else if (!string.IsNullOrWhiteSpace(properties[i].Display?.Values))
                    {
                        MethodInfo method = model.GetType().GetMethod(properties[i].Display.Values);
                        string[]   values = ((IEnumerable <object>)method.Invoke(model, null))?.Select(v => v?.ToString())?.ToArray();
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = values;
                    }
                    else
                    {
                        cell.EditorType = EditorTypeEnum.TextBox;
                    }
                }
            }

            IGridColumn descriptionColumn = grid.GetColumn(0);

            descriptionColumn.Width    = -1;
            descriptionColumn.ReadOnly = true;

            IGridColumn valueColumn = grid.GetColumn(1);

            valueColumn.Width = -1;
        }
Beispiel #5
0
        /// <summary>
        /// Format the grid.
        /// </summary>
        protected virtual void FormatGrid()
        {
            for (int i = 0; i < properties.Count; i++)
            {
                IGridCell cell = grid.GetCell(1, i);

                if (properties[i] is VariableObject)
                {
                    cell.EditorType = EditorTypeEnum.TextBox;

                    grid.SetRowAsSeparator(i, true);
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.TableName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    if (storage == null)
                    {
                        storage = model.FindInScope <IDataStore>();
                    }
                    cell.DropDownStrings = storage.Reader.TableNames.ToArray();
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.CultivarName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    IPlant crop;
                    if (properties[i].Display.PlantName != null)
                    {
                        crop = model.FindInScope <IPlant>(properties[i].Display.PlantName);
                    }
                    else
                    {
                        crop = GetCrop(properties);
                    }
                    if (crop != null)
                    {
                        cell.DropDownStrings = PropertyPresenterHelpers.GetCultivarNames(crop);
                    }
                }

                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.LifeCycleName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    Zone zone = model.FindInScope <Zone>();
                    if (zone != null)
                    {
                        cell.DropDownStrings = PropertyPresenterHelpers.GetLifeCycleNames(zone);
                    }
                }

                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.LifePhaseName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    LifeCycle lifeCycle = GetLifeCycle(properties);
                    if (lifeCycle != null)
                    {
                        cell.DropDownStrings = PropertyPresenterHelpers.GetPhaseNames(lifeCycle);
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.FileName)
                {
                    cell.EditorType = EditorTypeEnum.Button;
                }
                else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.FileNames)
                {
                    cell.EditorType = EditorTypeEnum.MultiFiles;
                }
                else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.DirectoryName)
                {
                    cell.EditorType = EditorTypeEnum.DirectoryChooser;
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.FieldName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = GetFieldNames();
                    if (fieldNames != null)
                    {
                        fieldNames.Insert(0, string.Empty);
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.ResidueName &&
                         model is SurfaceOrganicMatter)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    string[] fieldNames = GetResidueNames();
                    if (fieldNames != null)
                    {
                        cell.DropDownStrings = fieldNames;
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.Model)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;

                    string[] modelNames = GetModelNames(properties[i].Display.ModelType);
                    if (modelNames != null)
                    {
                        cell.DropDownStrings = modelNames;
                    }
                }
                else
                {
                    object cellValue = properties[i].ValueWithArrayHandling;
                    if (cellValue is DateTime)
                    {
                        cell.EditorType = EditorTypeEnum.DateTime;
                    }
                    else if (cellValue is bool)
                    {
                        cell.EditorType = EditorTypeEnum.Boolean;
                    }
                    else if (cellValue.GetType().IsEnum)
                    {
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = VariableProperty.EnumToStrings(cellValue);
                        Enum cellValueAsEnum = cellValue as Enum;
                        if (cellValueAsEnum != null)
                        {
                            cell.Value = VariableProperty.GetEnumDescription(cellValueAsEnum);
                        }
                    }
                    else if (cellValue.GetType() == typeof(IPlant))
                    {
                        cell.EditorType = EditorTypeEnum.DropDown;
                        List <string> cropNames = new List <string>();
                        foreach (Model crop in model.FindAllInScope <IPlant>())
                        {
                            cropNames.Add(crop.Name);
                        }

                        cell.DropDownStrings = cropNames.ToArray();
                    }
                    else if (properties[i].DataType == typeof(IPlant))
                    {
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = model.FindAllInScope <IPlant>().OfType <IModel>().Select(m => m.Name).ToArray();
                    }
                    else if (!string.IsNullOrWhiteSpace(properties[i].Display?.Values))
                    {
                        explorerPresenter.ApsimXFile.Links.Resolve(model, allLinks: true, throwOnFail: false);
                        BindingFlags flags  = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy;
                        MethodInfo   method = model.GetType().GetMethod(properties[i].Display.Values, flags);
                        string[]     values = ((IEnumerable <object>)method.Invoke(model, properties[i].Display.ValuesArgs))?.Select(v => v?.ToString())?.ToArray();
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = values;
                    }
                    else
                    {
                        cell.EditorType = EditorTypeEnum.TextBox;
                    }
                }
                cell.IsRowReadonly = !IsPropertyEnabled(i);
            }

            IGridColumn descriptionColumn = grid.GetColumn(0);

            descriptionColumn.Width    = -1;
            descriptionColumn.ReadOnly = true;

            IGridColumn valueColumn = grid.GetColumn(1);

            valueColumn.Width = -1;
        }
Beispiel #6
0
        /// <summary>
        /// Instantiates a Property object by reading metadata about
        /// the given property.
        /// </summary>
        /// <param name="obj">The object reference used to fetch the current value of the property.</param>
        /// <param name="metadata">Property metadata.</param>
        public Property(object obj, PropertyInfo metadata)
        {
            IModel model = obj as IModel;

            ID   = Guid.NewGuid();
            Name = metadata.GetCustomAttribute <DescriptionAttribute>()?.ToString();
            if (string.IsNullOrEmpty(Name))
            {
                Name = metadata.Name;
            }

            Tooltip    = metadata.GetCustomAttribute <TooltipAttribute>()?.Tooltip;
            Separators = metadata.GetCustomAttributes <SeparatorAttribute>()?.Select(s => s.ToString())?.ToList();

            Value = metadata.GetValue(obj);
            if (metadata.PropertyType == typeof(DateTime) || (metadata.PropertyType == typeof(DateTime?) && Value != null))
            {
                // Note: ToShortDateString() uses the current culture, which is what we want in this case.
                Value = ((DateTime)Value).ToShortDateString();
            }
            // ?else if property type isn't a struct?
            else if (Value != null && typeof(IModel).IsAssignableFrom(Value.GetType()))
            {
                Value = ((IModel)Value).Name;
            }
            else if (metadata.PropertyType.IsEnum)
            {
                Value = VariableProperty.GetEnumDescription((Enum)Enum.Parse(metadata.PropertyType, Value?.ToString()));
            }
            else if (metadata.PropertyType != typeof(bool) && metadata.PropertyType != typeof(System.Drawing.Color))
            {
                Value = ReflectionUtilities.ObjectToString(Value, CultureInfo.CurrentCulture);
            }

            // fixme - need to fix this unmaintainable mess brought across from the old PropertyPresenter
            DisplayAttribute attrib      = metadata.GetCustomAttribute <DisplayAttribute>();
            DisplayType      displayType = attrib?.Type ?? DisplayType.None;

            // For compatibility with the old PropertyPresenter, assume a default of
            // DisplayType.DropDown if the Values property is specified.
            if (displayType == DisplayType.None && !string.IsNullOrEmpty(attrib?.Values))
            {
                displayType = DisplayType.DropDown;
            }

            switch (displayType)
            {
            case DisplayType.None:
                if (metadata.PropertyType.IsEnum)
                {
                    // Enums use dropdown
                    DropDownOptions = Enum.GetValues(metadata.PropertyType).Cast <Enum>()
                                      .Select(e => VariableProperty.GetEnumDescription(e))
                                      .ToArray();
                    DisplayMethod = PropertyType.DropDown;
                }
                else if (typeof(IModel).IsAssignableFrom(metadata.PropertyType))
                {
                    // Model selector - use a dropdown containing names of all models in scope.
                    DisplayMethod   = PropertyType.DropDown;
                    DropDownOptions = model.FindAllInScope()
                                      .Where(m => metadata.PropertyType.IsAssignableFrom(m.GetType()))
                                      .Select(m => m.Name)
                                      .ToArray();
                }
                else if (metadata.PropertyType == typeof(bool))
                {
                    DisplayMethod = PropertyType.Checkbox;
                }
                else if (metadata.PropertyType == typeof(System.Drawing.Color))
                {
                    DisplayMethod = PropertyType.Colour;
                }
                else
                {
                    DisplayMethod = PropertyType.SingleLineText;
                }
                break;

            case DisplayType.FileName:
                DisplayMethod = PropertyType.File;
                break;

            case DisplayType.FileNames:
                DisplayMethod = PropertyType.Files;
                break;

            case DisplayType.DirectoryName:
                DisplayMethod = PropertyType.Directory;
                break;

            case DisplayType.DropDown:
                string methodName = metadata.GetCustomAttribute <DisplayAttribute>().Values;
                if (methodName == null)
                {
                    throw new ArgumentNullException($"When using DisplayType.DropDown, the Values property must be specified.");
                }
                BindingFlags flags  = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy;
                MethodInfo   method = model.GetType().GetMethod(methodName, flags);

                object[] args = metadata.GetCustomAttribute <DisplayAttribute>().ValuesArgs;

                // Attempt to resolve links - populating the dropdown may
                // require access to linked models.
                Simulations sims = model.FindAncestor <Simulations>();
                if (sims != null)
                {
                    sims.Links.Resolve(model, allLinks: true, throwOnFail: false);
                }

                DropDownOptions = ((IEnumerable <object>)method.Invoke(model, args))?.Select(v => v?.ToString())?.ToArray();
                DisplayMethod   = PropertyType.DropDown;
                break;

            case DisplayType.CultivarName:
                DisplayMethod = PropertyType.DropDown;
                IPlant       plant         = null;
                PropertyInfo plantProperty = model.GetType().GetProperties().FirstOrDefault(p => typeof(IPlant).IsAssignableFrom(p.PropertyType));
                if (plantProperty != null)
                {
                    plant = plantProperty.GetValue(model) as IPlant;
                }
                else
                {
                    plant = model.FindInScope <IPlant>();
                }
                if (plant != null)
                {
                    DropDownOptions = PropertyPresenterHelpers.GetCultivarNames(plant);
                }
                break;

            case DisplayType.TableName:
                DisplayMethod   = PropertyType.DropDown;
                DropDownOptions = model.FindInScope <IDataStore>()?.Reader?.TableNames?.ToArray();
                break;

            case DisplayType.FieldName:
                DisplayMethod = PropertyType.DropDown;
                IDataStore   storage           = model.FindInScope <IDataStore>();
                PropertyInfo tableNameProperty = model.GetType().GetProperties().FirstOrDefault(p => p.GetCustomAttribute <DisplayAttribute>()?.Type == DisplayType.TableName);
                string       tableName         = tableNameProperty?.GetValue(model) as string;
                if (storage != null && storage.Reader.TableNames.Contains(tableName))
                {
                    DropDownOptions = storage.Reader.ColumnNames(tableName).ToArray();
                }
                break;

            case DisplayType.LifeCycleName:
                DisplayMethod = PropertyType.DropDown;
                Zone zone = model.FindInScope <Zone>();
                if (zone != null)
                {
                    DropDownOptions = PropertyPresenterHelpers.GetLifeCycleNames(zone);
                }
                break;

            case DisplayType.LifePhaseName:
                DisplayMethod = PropertyType.DropDown;
                LifeCycle lifeCycle = null;
                if (attrib.LifeCycleName != null)
                {
                    lifeCycle = model.FindInScope <LifeCycle>(attrib.LifeCycleName);
                }
                else
                {
                    foreach (PropertyInfo property in model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                    {
                        if (property.PropertyType == typeof(string))
                        {
                            string    value = property.GetValue(model) as string;
                            LifeCycle match = model.FindInScope <LifeCycle>(value);
                            if (match != null)
                            {
                                lifeCycle = match;
                                break;
                            }
                        }
                    }
                }
                if (lifeCycle != null)
                {
                    DropDownOptions = PropertyPresenterHelpers.GetPhaseNames(lifeCycle).ToArray();
                }
                break;

            case DisplayType.Model:
                DisplayMethod   = PropertyType.DropDown;
                DropDownOptions = model.FindAllInScope().Where(m => metadata.PropertyType.IsAssignableFrom(m.GetType()))
                                  .Select(m => m.Name)
                                  .ToArray();
                break;

            case DisplayType.ResidueName:
                if (model is SurfaceOrganicMatter surfaceOM)
                {
                    DisplayMethod   = PropertyType.DropDown;
                    DropDownOptions = surfaceOM.ResidueTypeNames().ToArray();
                    break;
                }
                else
                {
                    throw new NotImplementedException($"Display type {displayType} is only supported on models of type {typeof(SurfaceOrganicMatter).Name}, but model is of type {model.GetType().Name}.");
                }

            case DisplayType.MultiLineText:
                DisplayMethod = PropertyType.MultiLineText;
                if (Value is IEnumerable enumerable && metadata.PropertyType != typeof(string))
                {
                    Value = string.Join(Environment.NewLine, ((IEnumerable)metadata.GetValue(obj)).ToGenericEnumerable());
                }
                break;

            // Should never happen - presenter should handle this(?)
            //case DisplayType.SubModel:
            default:
                throw new NotImplementedException($"Unknown display type {displayType}");
            }

            // If the list of dropdown options doesn't contain the actual value of the
            // property, add that value to the list of valid options.
            if (DisplayMethod == PropertyType.DropDown && Value != null)
            {
                if (DropDownOptions == null)
                {
                    DropDownOptions = new string[1] {
                        Value.ToString()
                    }
                }
                ;
                else if (!DropDownOptions.Contains(Value.ToString()))
                {
                    List <string> values = DropDownOptions.ToList();
                    values.Add(Value.ToString());
                    DropDownOptions = values.ToArray();
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Format the grid.
        /// </summary>
        private void FormatGrid()
        {
            for (int i = 0; i < this.properties.Count; i++)
            {
                IGridCell cell = this.grid.GetCell(1, i);

                if (this.properties[i] is VariableObject)
                {
                    cell.EditorType = EditorTypeEnum.TextBox;

                    grid.SetRowAsSeparator(i, true);
                }
                else if (this.properties[i].Display != null &&
                         this.properties[i].Display.Type == DisplayType.TableName)
                {
                    cell.EditorType      = EditorTypeEnum.DropDown;
                    cell.DropDownStrings = this.storage.TableNames.ToArray();
                }
                else if (this.properties[i].Display != null &&
                         this.properties[i].Display.Type == DisplayType.CultivarName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    IPlant crop = this.GetCrop(this.properties);
                    if (crop != null)
                    {
                        cell.DropDownStrings = this.GetCultivarNames(crop);
                    }
                }
                else if (this.properties[i].Display != null &&
                         this.properties[i].Display.Type == DisplayType.FileName)
                {
                    cell.EditorType = EditorTypeEnum.Button;
                }
                else if (this.properties[i].Display != null &&
                         this.properties[i].Display.Type == DisplayType.FieldName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    string[] fieldNames = this.GetFieldNames();
                    if (fieldNames != null)
                    {
                        cell.DropDownStrings = fieldNames;
                    }
                }
                else if (this.properties[i].Display != null &&
                         this.properties[i].Display.Type == DisplayType.ResidueName &&
                         this.model is Models.Surface.SurfaceOrganicMatter)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    string[] fieldNames = GetResidueNames();
                    if (fieldNames != null)
                    {
                        cell.DropDownStrings = fieldNames;
                    }
                }
                else if (this.properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.Model)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;

                    string[] modelNames = GetModelNames(properties[i].Display.ModelType);
                    if (modelNames != null)
                    {
                        cell.DropDownStrings = modelNames;
                    }
                }
                else
                {
                    object cellValue = this.properties[i].ValueWithArrayHandling;
                    if (cellValue is DateTime)
                    {
                        cell.EditorType = EditorTypeEnum.DateTime;
                    }
                    else if (cellValue is bool)
                    {
                        cell.EditorType = EditorTypeEnum.Boolean;
                    }
                    else if (cellValue.GetType().IsEnum)
                    {
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = VariableProperty.EnumToStrings(cellValue);
                        Enum cellValueAsEnum = cellValue as Enum;
                        if (cellValueAsEnum != null)
                        {
                            cell.Value = VariableProperty.GetEnumDescription(cellValueAsEnum);
                        }
                    }
                    else if (cellValue.GetType() == typeof(IPlant))
                    {
                        cell.EditorType = EditorTypeEnum.DropDown;
                        List <string> cropNames = new List <string>();
                        foreach (Model crop in Apsim.FindAll(this.model, typeof(IPlant)))
                        {
                            cropNames.Add(crop.Name);
                        }

                        cell.DropDownStrings = cropNames.ToArray();
                    }
                    else if (this.properties[i].DataType == typeof(IPlant))
                    {
                        List <string> plantNames = Apsim.FindAll(this.model, typeof(IPlant)).Select(m => m.Name).ToList();
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = plantNames.ToArray();
                    }
                    else
                    {
                        cell.EditorType = EditorTypeEnum.TextBox;
                    }
                }
            }

            IGridColumn descriptionColumn = this.grid.GetColumn(0);

            descriptionColumn.Width    = -1;
            descriptionColumn.ReadOnly = true;

            IGridColumn valueColumn = this.grid.GetColumn(1);

            valueColumn.Width = -1;
        }
Beispiel #8
0
        /// <summary>
        /// Instantiates a Property object by reading metadata about
        /// the given property.
        /// </summary>
        /// <param name="obj">The object reference used to fetch the current value of the property.</param>
        /// <param name="metadata">Property metadata.</param>
        public Property(object obj, PropertyInfo metadata)
        {
            IModel model = obj as IModel;

            ID   = Guid.NewGuid();
            Name = metadata.GetCustomAttribute <DescriptionAttribute>()?.ToString();
            if (string.IsNullOrEmpty(Name))
            {
                Name = metadata.Name;
            }

            Tooltip    = metadata.GetCustomAttribute <TooltipAttribute>()?.Tooltip;
            Separators = metadata.GetCustomAttributes <SeparatorAttribute>()?.Select(s => s.ToString())?.ToList();

            Value = metadata.GetValue(obj);
            if (metadata.PropertyType == typeof(DateTime) || (metadata.PropertyType == typeof(DateTime?) && Value != null))
            {
                // Note: ToShortDateString() uses the current culture, which is what we want in this case.
                Value = ((DateTime)Value).ToShortDateString();
            }
            // ?else if property type isn't a struct?
            else if (Value != null && typeof(IModel).IsAssignableFrom(Value.GetType()))
            {
                Value = ((IModel)Value).Name;
            }
            else if (metadata.PropertyType != typeof(bool) && metadata.PropertyType != typeof(System.Drawing.Color))
            {
                Value = ReflectionUtilities.ObjectToString(Value, CultureInfo.CurrentCulture);
            }

            // fixme - need to fix this unmaintainable mess brought across from the old PropertyPresenter
            DisplayAttribute attrib      = metadata.GetCustomAttribute <DisplayAttribute>();
            DisplayType      displayType = attrib?.Type ?? DisplayType.None;

            switch (displayType)
            {
            case DisplayType.None:
                if (metadata.PropertyType.IsEnum)
                {
                    // Enums use dropdown
                    DropDownOptions = Enum.GetValues(metadata.PropertyType).Cast <Enum>()
                                      .Select(e => VariableProperty.GetEnumDescription(e))
                                      .ToArray();
                    DisplayMethod = PropertyType.DropDown;
                }
                else if (typeof(IModel).IsAssignableFrom(metadata.PropertyType))
                {
                    // Model selector - use a dropdown containing names of all models in scope.
                    DisplayMethod   = PropertyType.DropDown;
                    DropDownOptions = model.FindAllInScope()
                                      .Where(m => metadata.PropertyType.IsAssignableFrom(m.GetType()))
                                      .Select(m => m.Name)
                                      .ToArray();
                }
                else if (metadata.PropertyType == typeof(bool))
                {
                    DisplayMethod = PropertyType.Checkbox;
                }
                else if (metadata.PropertyType == typeof(System.Drawing.Color))
                {
                    DisplayMethod = PropertyType.Colour;
                }
                else
                {
                    DisplayMethod = PropertyType.SingleLineText;
                }
                break;

            case DisplayType.FileName:
                DisplayMethod = PropertyType.File;
                break;

            case DisplayType.FileNames:
                DisplayMethod = PropertyType.Files;
                break;

            case DisplayType.DirectoryName:
                DisplayMethod = PropertyType.Directory;
                break;

            case DisplayType.DropDown:
                string     methodName = metadata.GetCustomAttribute <DisplayAttribute>().Values;
                MethodInfo method     = model.GetType().GetMethod(methodName);
                DropDownOptions = ((IEnumerable <object>)method.Invoke(model, null))?.Select(v => v?.ToString())?.ToArray();
                DisplayMethod   = PropertyType.DropDown;
                break;

            case DisplayType.CultivarName:
                DisplayMethod = PropertyType.DropDown;
                IPlant       plant         = null;
                PropertyInfo plantProperty = model.GetType().GetProperties().FirstOrDefault(p => typeof(IPlant).IsAssignableFrom(p.PropertyType));
                if (plantProperty != null)
                {
                    plant = plantProperty.GetValue(model) as IPlant;
                }
                else
                {
                    plant = model.FindInScope <IPlant>();
                }
                DropDownOptions = PropertyPresenterHelpers.GetCultivarNames(plant);
                break;

            case DisplayType.TableName:
                DisplayMethod   = PropertyType.DropDown;
                DropDownOptions = model.FindInScope <IDataStore>()?.Reader?.TableNames?.ToArray();
                break;

            case DisplayType.FieldName:
                DisplayMethod = PropertyType.DropDown;
                IDataStore   storage           = model.FindInScope <IDataStore>();
                PropertyInfo tableNameProperty = model.GetType().GetProperties().FirstOrDefault(p => p.GetCustomAttribute <DisplayAttribute>()?.Type == DisplayType.TableName);
                string       tableName         = tableNameProperty?.GetValue(model) as string;
                if (storage != null && storage.Reader.TableNames.Contains(tableName))
                {
                    DropDownOptions = storage.Reader.ColumnNames(tableName).ToArray();
                }
                break;

            case DisplayType.LifeCycleName:
                DisplayMethod = PropertyType.DropDown;
                Zone zone = model.FindInScope <Zone>();
                if (zone != null)
                {
                    DropDownOptions = PropertyPresenterHelpers.GetLifeCycleNames(zone);
                }
                break;

            case DisplayType.LifePhaseName:
                DisplayMethod = PropertyType.DropDown;
                LifeCycle lifeCycle = null;
                if (attrib.LifeCycleName != null)
                {
                    lifeCycle = model.FindInScope <LifeCycle>(attrib.LifeCycleName);
                }
                else
                {
                    foreach (PropertyInfo property in model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                    {
                        if (property.PropertyType == typeof(string))
                        {
                            string    value = property.GetValue(model) as string;
                            LifeCycle match = model.FindInScope <LifeCycle>(value);
                            if (match != null)
                            {
                                lifeCycle = match;
                                break;
                            }
                        }
                    }
                }
                if (lifeCycle != null)
                {
                    DropDownOptions = PropertyPresenterHelpers.GetPhaseNames(lifeCycle).ToArray();
                }
                break;

            case DisplayType.Model:
                DisplayMethod   = PropertyType.DropDown;
                DropDownOptions = model.FindAllInScope().Where(m => metadata.PropertyType.IsAssignableFrom(m.GetType()))
                                  .Select(m => m.Name)
                                  .ToArray();
                break;

            case DisplayType.ResidueName:
                if (model is SurfaceOrganicMatter surfaceOM)
                {
                    DisplayMethod   = PropertyType.DropDown;
                    DropDownOptions = surfaceOM.ResidueTypeNames().ToArray();
                    break;
                }
                else
                {
                    throw new NotImplementedException($"Display type {displayType} is only supported on models of type {typeof(SurfaceOrganicMatter).Name}, but model is of type {model.GetType().Name}.");
                }

            // Should never happen - presenter should handle this(?)
            //case DisplayType.SubModel:
            default:
                throw new NotImplementedException($"Unknown display type {displayType}");
            }
        }
Beispiel #9
0
        /// <summary>
        /// Format the grid.
        /// </summary>
        protected virtual void FormatGrid()
        {
            for (int i = 0; i < properties.Count; i++)
            {
                IGridCell cell = grid.GetCell(1, i);

                if (properties[i] is VariableObject)
                {
                    cell.EditorType = EditorTypeEnum.TextBox;

                    grid.SetRowAsSeparator(i, true);
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.TableName)
                {
                    cell.EditorType      = EditorTypeEnum.DropDown;
                    cell.DropDownStrings = storage.Reader.TableNames.ToArray();
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.CultivarName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    IPlant crop;
                    if (properties[i].Display.PlantName != null)
                    {
                        crop = model.FindInScope <IPlant>(properties[i].Display.PlantName);
                    }
                    else
                    {
                        crop = GetCrop(properties);
                    }
                    if (crop != null)
                    {
                        cell.DropDownStrings = PropertyPresenterHelpers.GetCultivarNames(crop);
                    }
                }

                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.LifeCycleName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    Zone zone = model.FindInScope <Zone>();
                    if (zone != null)
                    {
                        cell.DropDownStrings = PropertyPresenterHelpers.GetLifeCycleNames(zone);
                    }
                }

                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.LifePhaseName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    LifeCycle lifeCycle = GetLifeCycle(properties);
                    if (lifeCycle != null)
                    {
                        cell.DropDownStrings = PropertyPresenterHelpers.GetPhaseNames(lifeCycle);
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.FileName)
                {
                    cell.EditorType = EditorTypeEnum.Button;
                }
                else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.FileNames)
                {
                    cell.EditorType = EditorTypeEnum.MultiFiles;
                }
                else if (properties[i].Display != null && properties[i].Display.Type == DisplayType.DirectoryName)
                {
                    cell.EditorType = EditorTypeEnum.DirectoryChooser;
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.FieldName)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = GetFieldNames();
                    if (fieldNames != null)
                    {
                        fieldNames.Insert(0, string.Empty);
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.ResidueName &&
                         model is SurfaceOrganicMatter)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    string[] fieldNames = GetResidueNames();
                    if (fieldNames != null)
                    {
                        cell.DropDownStrings = fieldNames;
                    }
                }
                else if (properties[i].Display != null &&
                         (properties[i].Display.Type == DisplayType.CLEMResource))
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = new List <string>();
                    fieldNames.AddRange(this.GetCLEMResourceNames(this.properties[i].Display.CLEMResourceGroups));

                    // add any extras elements provided to the list.
                    if (this.properties[i].Display.CLEMExtraEntries != null)
                    {
                        fieldNames.AddRange(this.properties[i].Display.CLEMExtraEntries);
                    }

                    if (fieldNames.Count != 0)
                    {
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         (properties[i].Display.Type == DisplayType.CLEMCropFileReader))
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = new List <string>();
                    Simulation    clemParent = model.FindAncestor <Simulation>();
                    // get crop file names
                    fieldNames.AddRange(clemParent.FindAllDescendants <FileCrop>().Select(a => a.Name).ToList());
                    fieldNames.AddRange(clemParent.FindAllDescendants <FileSQLiteCrop>().Select(a => a.Name).ToList());
                    if (fieldNames.Count != 0)
                    {
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         (properties[i].Display.Type == DisplayType.CLEMPastureFileReader))
                {
                    cell.EditorType = EditorTypeEnum.DropDown;
                    List <string> fieldNames = new List <string>();
                    Simulation    clemParent = model.FindAncestor <Simulation>();
                    // get Pasture file names
                    fieldNames.AddRange(clemParent.FindAllDescendants <FilePasture>().Select(a => a.Name).ToList());
                    fieldNames.AddRange(clemParent.FindAllDescendants <FileSQLitePasture>().Select(a => a.Name).ToList());
                    if (fieldNames.Count != 0)
                    {
                        cell.DropDownStrings = fieldNames.ToArray();
                    }
                }
                else if (properties[i].Display != null &&
                         properties[i].Display.Type == DisplayType.Model)
                {
                    cell.EditorType = EditorTypeEnum.DropDown;

                    string[] modelNames = GetModelNames(properties[i].Display.ModelType);
                    if (modelNames != null)
                    {
                        cell.DropDownStrings = modelNames;
                    }
                }
                else
                {
                    object cellValue = properties[i].ValueWithArrayHandling;
                    if (cellValue is DateTime)
                    {
                        cell.EditorType = EditorTypeEnum.DateTime;
                    }
                    else if (cellValue is bool)
                    {
                        cell.EditorType = EditorTypeEnum.Boolean;
                    }
                    else if (cellValue.GetType().IsEnum)
                    {
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = VariableProperty.EnumToStrings(cellValue);
                        Enum cellValueAsEnum = cellValue as Enum;
                        if (cellValueAsEnum != null)
                        {
                            cell.Value = VariableProperty.GetEnumDescription(cellValueAsEnum);
                        }
                    }
                    else if (cellValue.GetType() == typeof(IPlant))
                    {
                        cell.EditorType = EditorTypeEnum.DropDown;
                        List <string> cropNames = new List <string>();
                        foreach (Model crop in model.FindAllInScope <IPlant>())
                        {
                            cropNames.Add(crop.Name);
                        }

                        cell.DropDownStrings = cropNames.ToArray();
                    }
                    else if (properties[i].DataType == typeof(IPlant))
                    {
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = model.FindAllInScope <IPlant>().OfType <IModel>().Select(m => m.Name).ToArray();
                    }
                    else if (!string.IsNullOrWhiteSpace(properties[i].Display?.Values))
                    {
                        explorerPresenter.ApsimXFile.Links.Resolve(model, allLinks: true, throwOnFail: false);
                        MethodInfo method = model.GetType().GetMethod(properties[i].Display.Values);
                        string[]   values = ((IEnumerable <object>)method.Invoke(model, null))?.Select(v => v?.ToString())?.ToArray();
                        cell.EditorType      = EditorTypeEnum.DropDown;
                        cell.DropDownStrings = values;
                    }
                    else
                    {
                        cell.EditorType = EditorTypeEnum.TextBox;
                    }
                }
                cell.IsRowReadonly = !IsPropertyEnabled(i);
            }

            IGridColumn descriptionColumn = grid.GetColumn(0);

            descriptionColumn.Width    = -1;
            descriptionColumn.ReadOnly = true;

            IGridColumn valueColumn = grid.GetColumn(1);

            valueColumn.Width = -1;
        }