--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Base/DataBinding/CIDBModel.cs Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,303 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.Reflection;
+using System.ComponentModel;
+
+namespace CrashItemLib.Crash.Base.DataBinding
+{
+ public class CIDBModel : IEnumerable<CIDBRow>
+ {
+ #region Constructors
+ public CIDBModel( CIElement aElement, bool aAutoPopulate )
+ {
+ iElement = aElement;
+ iAutoPopulate = aAutoPopulate;
+ }
+ #endregion
+
+ #region API
+ public void Add( CIDBColumn aColumn )
+ {
+ aColumn.Model = this;
+ iColumns.Add( aColumn );
+ }
+
+ public void Add( CIDBRow aRow )
+ {
+ aRow.Model = this;
+ iRows.Add( aRow );
+ }
+
+ public void Add( params CIDBCell[] aCells )
+ {
+ CIDBRow row = new CIDBRow( aCells );
+ Add( row );
+ }
+
+ public void ClearRows()
+ {
+ iRows.Clear();
+ }
+
+ public void ClearColumns()
+ {
+ iColumns.Clear();
+ }
+
+ public void TryAutoPopulateColumns( CIElement aElement )
+ {
+ Type customAttributeType = typeof( CIDBAttributeColumn );
+ Type thisObjectType = aElement.GetType();
+
+ object[] attribs = thisObjectType.GetCustomAttributes( customAttributeType, true );
+ if ( attribs != null && attribs.Length > 0 )
+ {
+ ExtractAttributeColumns( attribs, aElement );
+ }
+ }
+
+ public void TryAutoPopulateCells( CIElement aElement )
+ {
+ if ( AutoPopulate )
+ {
+ SortedDictionary<int, CIDBRow> rows = new SortedDictionary<int, CIDBRow>();
+
+ Type customAttributeType = typeof( CIDBAttributeCell );
+ Type thisObjectType = aElement.GetType();
+
+ // Get properties featuring the CIDBAttribute
+ PropertyInfo[] propertyInfo = thisObjectType.GetProperties();
+ foreach ( PropertyInfo p in propertyInfo )
+ {
+ object[] attribs = p.GetCustomAttributes( customAttributeType, true );
+ if ( attribs != null && attribs.Length > 0 )
+ {
+ object propertyValue = p.GetValue( aElement, null );
+ ExtractAttributeCells( p.ToString(), aElement, attribs, propertyValue, rows );
+ }
+ }
+
+ // Same, but get methods featuring the CIDBAttribute
+ MethodInfo[] methodInfo = thisObjectType.GetMethods();
+ foreach ( MethodInfo m in methodInfo )
+ {
+ object[] attribs = m.GetCustomAttributes( customAttributeType, true );
+ if ( attribs != null && attribs.Length > 0 )
+ {
+ // We only support this attribute on methods that don't contain
+ // any arguments
+ int paramCount = m.GetParameters().Length;
+ if ( paramCount != 0 )
+ {
+ throw new NotSupportedException( "Method: " + m.ToString() + " has CIDBAttribute but non-empty parameter list -> Not supported" );
+ }
+
+ // Get property value
+ object propertyValue = m.Invoke( aElement, null );
+ ExtractAttributeCells( m.ToString(), aElement, attribs, propertyValue, rows );
+ }
+ }
+
+ // Since the list is already sorted for us, just add the items in order
+ foreach ( KeyValuePair<int, CIDBRow> kvp in rows )
+ {
+ this.Add( kvp.Value );
+ }
+ }
+ }
+ #endregion
+
+ #region Properties
+ public bool AutoPopulate
+ {
+ get { return iAutoPopulate; }
+ }
+
+ public CIElement Element
+ {
+ get { return iElement; }
+ }
+
+ public List<CIDBColumn> Columns
+ {
+ get { return iColumns; }
+ }
+
+ public List<CIDBRow> Rows
+ {
+ get { return iRows; }
+ }
+ #endregion
+
+ #region Internal methods
+ private void ExtractAttributeColumns( object[] aColumnAttributes, CIElement aElement )
+ {
+ bool foundColumnAttributes = false;
+ SortedDictionary<int, CIDBColumn> columns = new SortedDictionary<int,CIDBColumn>();
+
+ foreach ( object obj in aColumnAttributes )
+ {
+ if ( obj is CIDBAttributeColumn )
+ {
+ CIDBAttributeColumn attribute = (CIDBAttributeColumn) obj;
+
+ // Make a column
+ CIDBColumn col = new CIDBColumn( attribute.Caption );
+ col.Width = attribute.Width;
+ col.WidthSet = attribute.WidthSet;
+ col.TakesUpSlack = attribute.TakesUpSlack;
+
+ if ( columns.ContainsKey( attribute.Order ) )
+ {
+ throw new Exception( string.Format( "Column: [{0}] in element: [{1}] specifies order: {2} which is already in use",
+ attribute.Caption, aElement, attribute.Order ) );
+ }
+
+ columns.Add( attribute.Order, col );
+ foundColumnAttributes = true;
+ }
+ }
+
+ // Since the list is already sorted for us, just add the items in order
+ foreach ( KeyValuePair<int, CIDBColumn> kvp in columns )
+ {
+ this.Add( kvp.Value );
+ }
+
+ // We'll override the auto populate feature if we find a valid
+ // column attribute
+ iAutoPopulate = foundColumnAttributes;
+ }
+
+ private void ExtractAttributeCells( string aEntityName, CIElement aElement, object[] aCIDBAttributeEntries, object aValue, SortedDictionary<int, CIDBRow> aRows )
+ {
+ foreach ( object obj in aCIDBAttributeEntries )
+ {
+ if ( obj is CIDBAttributeCell )
+ {
+ CIDBAttributeCell attribute = (CIDBAttributeCell) obj;
+
+ // If the property is an 'auto expand' entry, then don't look at this
+ // property, but instead look at the object itself
+ if ( attribute.Options == CIDBAttributeCell.TOptions.EAutoExpand )
+ {
+ // The object must be an element
+ CIElement element = aValue as CIElement;
+ if ( element == null )
+ {
+ throw new ArgumentException( "CIDBAttributeCell(TOptions.EAutoExpand) may only be applied to CIElement objects" );
+ }
+
+ TryAutoPopulateCells( element );
+ }
+ else
+ {
+ // Whether or not to create a row
+ bool makeRow = true;
+
+ // Convert attribute value to string. If the object is an enum, we'll check if it has
+ // a System.ComponentModel.Description attached to it, and use that in preference to a raw
+ // value.
+ string defaultValueString = ( attribute.DefaultValue != null ) ? attribute.DefaultValue.ToString() : null;
+ string propertyValueString = aValue.ToString();
+ if ( aValue.GetType().BaseType == typeof( Enum ) )
+ {
+ // Check if it supports System.ComponentModel.Description
+ FieldInfo fi = aValue.GetType().GetField( propertyValueString );
+ if ( fi != null )
+ {
+ DescriptionAttribute[] attributes = (DescriptionAttribute[]) fi.GetCustomAttributes( typeof( DescriptionAttribute ), false );
+ if ( attributes != null && attributes.Length > 0 )
+ {
+ propertyValueString = attributes[ 0 ].Description;
+ }
+ }
+ }
+ else if ( attribute.Format.Length > 0 && aValue is IFormattable )
+ {
+ string formatSpec = attribute.Format;
+ IFormattable formattable = (IFormattable) aValue;
+ propertyValueString = formattable.ToString( formatSpec, null );
+
+ // Also get the default value if available
+ bool defaultIsFormattable = attribute.DefaultValue is IFormattable;
+ if ( attribute.DefaultValue != null && defaultIsFormattable )
+ {
+ formattable = (IFormattable) attribute.DefaultValue;
+ defaultValueString = formattable.ToString( formatSpec, null );
+ }
+ }
+
+ // If the value of the property is the same as the default, then don't
+ // show it.
+ if ( defaultValueString != null )
+ {
+ makeRow = ( defaultValueString.CompareTo( propertyValueString ) != 0 );
+ }
+
+ // Make a row
+ if ( makeRow )
+ {
+ CIDBRow row = new CIDBRow();
+ row.Add( new CIDBCell( attribute.Caption ) );
+ row.Add( new CIDBCell( propertyValueString, attribute.ForeColor, attribute.BackColor, attribute.Format ) );
+
+ // Add the row if it doesn't exist. If it does, then that implies
+ // duplicate ordering, which we treat as a programming error.
+ if ( aRows.ContainsKey( attribute.Order ) )
+ {
+ throw new Exception( string.Format( "Entity: [{0}] in element: [{1}] specifies order: {2} which is already in use",
+ aEntityName, aElement, attribute.Order ) );
+ }
+
+ aRows.Add( attribute.Order, row );
+ }
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region From IEnumerable<CIDBRow>
+ public IEnumerator<CIDBRow> GetEnumerator()
+ {
+ foreach ( CIDBRow row in iRows )
+ {
+ yield return row;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ foreach ( CIDBRow row in iRows )
+ {
+ yield return row;
+ }
+ }
+ #endregion
+
+ #region Data members
+ private readonly CIElement iElement;
+ private bool iAutoPopulate = false;
+ private List<CIDBColumn> iColumns = new List<CIDBColumn>();
+ private List<CIDBRow> iRows = new List<CIDBRow>();
+ #endregion
+ }
+}