/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.Collections; using JetBrains.JetListViewLibrary; using JetBrains.Omea.Base; using JetBrains.Omea.Containers; using JetBrains.Omea.OpenAPI; using JetBrains.Omea.ResourceStore; namespace JetBrains.Omea.GUIControls { /// /// Fills ResourceListView2 with data from a plain resource list. /// public class ResourceListDataProvider: IResourceDataProvider { protected JetListView _listView; protected IResourceList _resourceList; protected ResourceComparer _lastComparer; private ResourcePropsColumn _lastSortColumn; protected bool _disposed; private bool _nodesAdded = false; private readonly Hashtable _lastSortDirections = new Hashtable(); private SortSettings _curSortSettings; public ResourceListDataProvider( IResourceList resourceList ) { Guard.NullArgument( resourceList, "resourceList" ); _resourceList = resourceList; } public IResourceList ResourceList { get { return _resourceList; } } public void SetInitialSort( SortSettings sortSettings ) { if ( _listView != null ) { throw new InvalidOperationException( "SetInitialSort() must be called before FillResources()" ); } _curSortSettings = sortSettings; } public SortSettings SortSettings { get { return _curSortSettings; } } public event EventHandler ResourceCountChanged; public event EventHandler SortChanged; public void FillResources( ResourceListView2 listView ) { if ( _listView != null ) { throw new InvalidOperationException( "Attempt to attach a ResourceListDataProvider which is already attached" ); } _listView = listView.JetListView; ApplySortSettings( listView.JetListView, _curSortSettings ); lock( _resourceList ) { AddResourceNodes(); _nodesAdded = true; _resourceList.ResourceAdded += HandleResourceAdded; _resourceList.ResourceChanged += HandleResourceChanged; _resourceList.ResourceDeleting += HandleResourceDeleting; } _listView.ColumnClick += HandleColumnClick; } public void ApplySortSettings( JetListView listView, SortSettings sortSettings ) { if ( sortSettings != null ) { _curSortSettings = sortSettings; bool foundComparerColumn = false; foreach( JetListViewColumn col in listView.Columns ) { ResourcePropsColumn propsCol = col as ResourcePropsColumn; if ( propsCol != null && propsCol.PropIdsEqual( sortSettings.SortProps ) ) { _lastComparer = CreateColumnComparer( propsCol, sortSettings ); propsCol.SortIcon = sortSettings.SortAscending ? SortIcon.Ascending : SortIcon.Descending; _lastSortColumn = propsCol; _listView.GroupProvider = _lastSortColumn.GroupProvider; foundComparerColumn = true; } else { col.SortIcon = SortIcon.None; } } if ( !foundComparerColumn ) { _lastComparer = new ResourceComparer( _resourceList, _curSortSettings, true ); } if ( _lastComparer != null ) { _listView.NodeCollection.SetItemComparer( null, _lastComparer ); if ( _nodesAdded ) { _listView.NodeCollection.Sort(); } } } } public void UpdateSortColumn() { if ( _curSortSettings != null ) { foreach( JetListViewColumn col in _listView.Columns ) { ResourcePropsColumn rlvCol = col as ResourcePropsColumn; if ( rlvCol != null && rlvCol.PropIdsEqual( _curSortSettings.SortProps ) ) { rlvCol.SortIcon = _curSortSettings.SortAscending ? SortIcon.Ascending : SortIcon.Descending; _lastSortColumn = rlvCol; _listView.GroupProvider = _lastSortColumn.GroupProvider; break; } } } } protected virtual void AddResourceNodes() { for( int i=0; i<_resourceList.Count; i++ ) { _listView.Nodes.Add( _resourceList [i] ); } } protected void OnResourceCountChanged() { if ( ResourceCountChanged != null ) { ResourceCountChanged( this, EventArgs.Empty ); } } protected void OnSortChanged() { if ( SortChanged != null ) { SortChanged( this, EventArgs.Empty ); } } protected virtual void HandleResourceAdded( object sender, ResourceIndexEventArgs e ) { if ( !_disposed ) { _listView.Nodes.Add( e.Resource ); OnResourceCountChanged(); } } protected virtual void HandleResourceChanged( object sender, ResourcePropIndexEventArgs e ) { if ( !_disposed ) { // UpdateItemSafe() is necessary because in some cases (OM-8629) some plugin performs // a resource change from the ResourceAdded event handler, which causes // JetListView to receive ResourceChanged notification for a resource before it // has received a ResourceAdded notification for the same resource. _listView.UpdateItemSafe( e.Resource ); } } protected virtual void HandleResourceDeleting( object sender, ResourceIndexEventArgs e ) { if ( !_disposed && e.Resource != null ) { // it's possible that a just added resource can be moved in the resource list and // we receive a delete notification before an add notification (OM-10510) if ( _listView.NodeCollection.NodeFromItem( e.Resource ) != null ) { _listView.Nodes.Remove( e.Resource ); OnResourceCountChanged(); } } } public virtual void Dispose() { if ( !_disposed ) { _disposed = true; if( _listView != null ) { _listView.ColumnClick -= HandleColumnClick; lock( _resourceList ) { _resourceList.ResourceAdded -= HandleResourceAdded; _resourceList.ResourceChanged -= HandleResourceChanged; _resourceList.ResourceDeleting -= HandleResourceDeleting; _resourceList = null; _listView = null; } } } } public virtual bool FindResourceNode( IResource res ) { return _resourceList.Contains( res ); } private void HandleColumnClick( object sender, ColumnEventArgs e ) { ResourcePropsColumn col = e.Column as ResourcePropsColumn; if ( col != null && _listView != null ) { HandeColumnClick( col ); } } public void HandeColumnClick( ResourcePropsColumn col ) { ComparableArrayList propList = new ComparableArrayList( col.PropIds ); if ( _lastComparer != null && col == _lastSortColumn ) { Guard.NullMember( _curSortSettings, "_curSortSettings" ); _curSortSettings = _curSortSettings.Reverse(); _lastSortDirections [propList] = (col.SortIcon == SortIcon.Descending ); // reverse } else { bool sortAscending = true; if ( _lastSortDirections.ContainsKey( propList ) ) { sortAscending = (bool) _lastSortDirections [propList]; } _curSortSettings = new SortSettings( col.PropIds, sortAscending ); if ( _lastSortColumn != null ) { _lastSortColumn.SortIcon = SortIcon.None; } _lastSortColumn = col; } _lastComparer = CreateColumnComparer( col, _curSortSettings ); Guard.NullMember( _lastSortColumn, "_lastSortColumn" ); _lastSortColumn.SortIcon = _curSortSettings.SortAscending ? SortIcon.Ascending : SortIcon.Descending; Guard.NullMember( _listView, "_listView" ); _listView.NodeCollection.SetItemComparer( null, _lastComparer ); _listView.NodeCollection.Sort(); _listView.GroupProvider = _lastSortColumn.GroupProvider; OnSortChanged(); } private ResourceComparer CreateColumnComparer( ResourcePropsColumn col, SortSettings sortSettings ) { if ( col.CustomComparer != null ) { return new ResourceComparer( _resourceList, col.CustomComparer, sortSettings.SortAscending ); } else { return new ResourceComparer( _resourceList, sortSettings, true ); } } } }