using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Diagnostics;
//using BindableEditableObject;
using EasiReports.Metadata;
namespace SortedViewNamespace
{
public class SortedView : IBindingList
{
private IList mList = null;
private bool mSupportsBinding = false;
private IBindingList mBindingList = null;
private bool mSorted = false;
private PropertyDescriptor mSortBy = null;
private ListSortDirection mSortOrder = ListSortDirection.Ascending;
private ArrayList mSortIndex = new ArrayList();
private object AddNewObject = null;
public IList List
{
get
{
return mList;
}
}
public SortedView( IList list )
{
mList = list;
if ( mList is IBindingList )
{
mSupportsBinding = true;
mBindingList = (IBindingList) mList;
mBindingList.ListChanged += new ListChangedEventHandler( SourceChanged );
}
if ( ItemIsBindableEditableObject )
{
foreach ( IBindableEditableObject o in mList )
o.EditCalled += new EditCalledEventHandler( EditCalled );
}
}
private void EditCalled( object sender, EditCalledEventArgs e )
{
switch ( e.EditCalledType )
{
case EditCalledType.BeginEdit :
Debug.WriteLine( "*BeginEdit*" );
break;
case EditCalledType.CancelEdit :
Debug.WriteLine( "*CancelEdit*" );
if ( sender == AddNewObject )
{
( (IList) this ).Remove( AddNewObject );
AddNewObject = null;
}
break;
case EditCalledType.EndEdit :
Debug.WriteLine( "*EndEdit*" );
if ( AddNewObject == null || sender == AddNewObject )
{
if ( mSorted ) DoSort();
else
{
int index = ( (IList) this ).IndexOf( sender );
if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.ItemChanged, index ) );
}
AddNewObject = null;
}
break;
}
}
private void SourceChanged( object sender, ListChangedEventArgs e )
{
if ( mSorted )
{
if ( e.ListChangedType == ListChangedType.ItemAdded )
{
object oNew = mList[ e.NewIndex ];
ListItem item = new ListItem( mSortBy.GetValue( oNew ), oNew );
if ( mSortOrder == ListSortDirection.Ascending )
{
mSortIndex.Add( item );
}
else
{
mSortIndex.Insert( 0, item );
}
if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.ItemAdded, mSortIndex.Count - 1 ) );
}
else
DoSort();
}
else
if ( ListChanged != null ) ListChanged( this, e );
}
//-----------------------------------------------------------------------------
// Sort/Unsort
private void DoSort()
{
mSortIndex.Clear();
if ( mSortBy == null )
{
foreach ( object o in mList )
mSortIndex.Add( new ListItem( o, o ) );
}
else
{
foreach ( object o in mList )
mSortIndex.Add( new ListItem( mSortBy.GetValue( o ), o ) );
}
mSortIndex.Sort();
mSorted = true;
if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.Reset, 0 ) );
}
private void UndoSort()
{
mSortIndex.Clear();
mSortBy = null;
mSortOrder = ListSortDirection.Ascending;
mSorted = false;
if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.Reset, 0 ) );
}
//-----------------------------------------------------------------------------
// IList
IEnumerator IEnumerable.GetEnumerator()
{
if ( mSorted ) return new SortedEnumerator( mSortIndex, mSortOrder );
return mList.GetEnumerator();
}
void ICollection.CopyTo( Array array, int index )
{
mList.CopyTo( array, index );
}
int ICollection.Count
{
get
{
return mList.Count;
}
}
bool ICollection.IsSynchronized
{
get
{
return mList.IsSynchronized;
}
}
object ICollection.SyncRoot
{
get
{
return mList.SyncRoot;
}
}
int IList.Add( object value )
{
return mList.Add( value );
}
void IList.Clear()
{
mList.Clear();
}
bool IList.Contains( object value )
{
return mList.Contains( value );
}
int IList.IndexOf( object value )
{
if ( mSorted )
{
int index = 0;
foreach ( ListItem item in mSortIndex )
{
if ( item.Item.Equals( value ) )
return index;
index++;
}
return -1;
}
else
return mList.IndexOf( value );
}
void IList.Insert( int index, object value )
{
mList.Insert( index, value );
}
bool IList.IsFixedSize
{
get
{
return mList.IsFixedSize;
}
}
bool IList.IsReadOnly
{
get
{
// return true;
return mList.IsReadOnly;
}
}
object IList.this[ int index ]
{
get
{
Debug.Assert( index < mList.Count );
if ( mSorted ) return GetSortedItem( index );
return mList[ index ];
}
set
{
Debug.Assert( index < mList.Count );
if ( mSorted )
{
int pos = mList.IndexOf( GetSortedItem( index ) );
mList[ pos ] = value;
if ( ! mSupportsBinding ) DoSort();
}
else
mList[ index ] = value;
}
}
private object GetSortedItem( int index )
{
if ( mSortOrder == ListSortDirection.Ascending )
return ( (ListItem) mSortIndex[ index ] ).Item;
else
return ( (ListItem) mSortIndex[ mSortIndex.Count - 1 - index ] ).Item;
}
void IList.Remove( object value )
{
IBindableEditableObject beo = value as IBindableEditableObject;
if ( beo != null ) beo.EditCalled -= new EditCalledEventHandler( EditCalled );
mList.Remove( value );
if ( ! mSupportsBinding )
{
int index = mList.IndexOf( value );
SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemDeleted, index ) );
}
}
void IList.RemoveAt( int index )
{
if ( mSorted )
{
object o = GetSortedItem( index );
IBindableEditableObject beo = o as IBindableEditableObject;
if ( beo != null ) beo.EditCalled -= new EditCalledEventHandler( EditCalled );
int pos = mList.IndexOf( o );
mList.RemoveAt( pos );
if ( ! mSupportsBinding )
SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemDeleted, pos ) );
}
else
{
object o = mList[ index ];
IBindableEditableObject beo = o as IBindableEditableObject;
if ( beo != null ) beo.EditCalled -= new EditCalledEventHandler( EditCalled );
mList.RemoveAt( index );
if ( ! mSupportsBinding )
SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemDeleted, index ) );
}
}
//-----------------------------------------------------------------------------
// IBindingList
void IBindingList.AddIndex( PropertyDescriptor property )
{
if ( mSupportsBinding )
mBindingList.AddIndex( property );
else
throw new NotSupportedException();
}
int x = 1;
object IBindingList.AddNew()
{
Debug.WriteLine( "AddNew" + x++ );
if ( mSupportsBinding )
return mBindingList.AddNew();
Type t = ItemType;
AddNewObject = Activator.CreateInstance( t );
IBindableEditableObject beo = AddNewObject as IBindableEditableObject;
if ( beo != null ) beo.EditCalled += new EditCalledEventHandler( EditCalled );
int iNewObject = mList.Add( AddNewObject );
// if ( ListChanged != null ) ListChanged( this, new ListChangedEventArgs( ListChangedType.ItemAdded, mList.Count - 1 ) );
if ( ! mSupportsBinding )
SourceChanged( this, new ListChangedEventArgs( ListChangedType.ItemAdded, iNewObject ) );
return AddNewObject;
}
bool IBindingList.AllowEdit
{
get
{
if ( mSupportsBinding )
return mBindingList.AllowEdit;
// return false;
return true;
}
}
bool IBindingList.AllowNew
{
get
{
if ( mSupportsBinding )
return mBindingList.AllowNew;
// return false;
return ItemIsBindableEditableObject;
}
}
bool IBindingList.AllowRemove
{
get
{
if ( mSupportsBinding )
return mBindingList.AllowRemove;
// return false;
return true;
}
}
public bool ItemIsBindableEditableObject
{
get
{
return ItemType.GetInterface( "IBindableEditableObject" ) != null;
}
}
public Type ItemType
{
get
{
Type t = ( (object) mList ).GetType();
MemberInfo[] defs = t.GetDefaultMembers();
foreach ( MemberInfo member in defs )
{
if ( member.MemberType == MemberTypes.Property )
{
Type itemType = ( (PropertyInfo) member ).GetGetMethod().ReturnType;
return itemType;
}
}
if ( mList.Count > 0 )
{
Type itemType = mList[ 0 ].GetType();
return itemType;
}
throw new Exception( "Cannot determine collection item type" );
}
}
public void ApplySort( string property, ListSortDirection direction )
{
if ( property.Length > 0 )
{
Type itemType = ItemType;
PropertyDescriptorCollection props = TypeDescriptor.GetProperties( itemType );
foreach ( PropertyDescriptor prop in props )
{
if ( prop.Name == property )
{
mSortBy = prop;
break;
}
}
}
( (IBindingList) this ).ApplySort( mSortBy, direction );
}
void IBindingList.ApplySort( PropertyDescriptor property, ListSortDirection direction )
{
mSortBy = property;
mSortOrder = direction;
DoSort();
}
int IBindingList.Find( PropertyDescriptor property, object key )
{
if ( mSupportsBinding )
return mBindingList.Find( property, key );
throw new NotSupportedException();
}
bool IBindingList.IsSorted
{
get
{
return mSorted;
}
}
public event ListChangedEventHandler ListChanged;
void IBindingList.RemoveIndex( PropertyDescriptor property )
{
if ( mSupportsBinding )
mBindingList.RemoveIndex( property );
else
throw new NotSupportedException();
}
void IBindingList.RemoveSort()
{
UndoSort();
}
ListSortDirection IBindingList.SortDirection
{
get
{
return mSortOrder;
}
}
PropertyDescriptor IBindingList.SortProperty
{
get
{
return mSortBy;
}
}
bool IBindingList.SupportsChangeNotification
{
get
{
return true;
}
}
bool IBindingList.SupportsSearching
{
get
{
if ( mSupportsBinding )
return mBindingList.SupportsSearching;
return false;
}
}
bool IBindingList.SupportsSorting
{
get
{
return true;
}
}
//-----------------------------------------------------------------------------
private class ListItem : IComparable
{
public object Key;
public object Item;
public ListItem( object key, object item )
{
this.Key = key;
this.Item = item;
}
int IComparable.CompareTo( object o )
{
object target = ( (ListItem) o ).Key;
if ( Key is IComparable ) return ( (IComparable) Key ).CompareTo( target );
if ( Key.Equals( target ) ) return 0;
return Key.ToString().CompareTo( target.ToString() );
}
public override string ToString()
{
return Key.ToString ();
}
}
//-----------------------------------------------------------------------------
private class SortedEnumerator : IEnumerator
{
private ArrayList mSortIndex;
private ListSortDirection mSortOrder;
private int index;
public SortedEnumerator( ArrayList SortIndex, ListSortDirection Direction )
{
mSortIndex = SortIndex;
mSortOrder = Direction;
( (IEnumerator) this ).Reset();
}
void IEnumerator.Reset()
{
if ( mSortOrder == ListSortDirection.Ascending )
index = -1;
else index = mSortIndex.Count;
}
bool IEnumerator.MoveNext()
{
if ( mSortOrder == ListSortDirection.Ascending )
{
if ( index < mSortIndex.Count - 1 )
{
index++;
return true;
}
return false;
}
if ( index > 0 )
{
index--;
return true;
}
return false;
}
object IEnumerator.Current
{
get
{
return ( (ListItem) mSortIndex[ index ] ).Item;
}
}
}
//-----------------------------------------------------------------------------
}
}