/// /// 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.Omea.OpenAPI; using JetBrains.DataStructures; namespace JetBrains.Omea.ResourceTools { /// /// Utility class for working with root nodes of trees for various types of resources. /// public class ResourceTreeManager: IResourceTreeManager { private static IResource _rootOfRoots; private static string _resTreeRoot = "ResourceTreeRoot"; private static int _propRootResType; private IResourceStore _store; private IntHashTable _sortPropCache = new IntHashTable(); private HashSet _viewsExclusive = new HashSet(); private class TreeListenerManager { private int _parentProp; private IResourceList _resources; private IntHashTable _listeners = new IntHashTable(); // resource ID -> ArrayList private enum Operation { Added, Changed, Deleting }; public TreeListenerManager( int parentProp ) { _parentProp = parentProp; _resources = Core.ResourceStore.FindResourcesWithPropLive( null, _parentProp ); _resources.ResourceAdded += new ResourceIndexEventHandler( HandleResourceAdded ); _resources.ResourceChanged += new ResourcePropIndexEventHandler( HandleResourceChanged ); _resources.ResourceDeleting += new ResourceIndexEventHandler( HandleResourceDeleting ); _resources.ChangedResourceDeleting += new ResourcePropIndexEventHandler( HandleChangedResourceDeleting ); } public void RegisterListener( IResource parent, IResourceListListener listener ) { lock( _listeners ) { ArrayList listenerList = (ArrayList) _listeners [parent.Id]; if ( listenerList == null ) { listenerList = new ArrayList(); _listeners [parent.Id] = listenerList; } listenerList.Add( listener ); } } public void UnregisterListener( IResource parent, IResourceListListener listener ) { lock( _listeners ) { ArrayList listenerList = (ArrayList) _listeners [parent.Id]; if ( listenerList != null ) { listenerList.Remove( listener ); } } } private void HandleResourceAdded( object sender, ResourceIndexEventArgs e ) { IResource parent = e.Resource.GetLinkProp( _parentProp ); NotifyListeners( parent, Operation.Added, e.Resource, null ); } private void HandleResourceChanged( object sender, ResourcePropIndexEventArgs e ) { if ( e.ChangeSet.IsPropertyChanged( _parentProp ) ) { LinkChange[] changes = e.ChangeSet.GetLinkChanges( _parentProp ); for( int i=0; i TreeListenerManager public ResourceTreeManager( IResourceStore store ) { _store = store; RegisterTreeProps(); IResourceList rootList = store.GetAllResources( _resTreeRoot ); if ( rootList.Count == 1 && !rootList [0].HasProp( "RootResourceType") ) { rootList [0].SetProp( _propRootResType, _resTreeRoot ); } _rootOfRoots = GetRootForType( _resTreeRoot ); _rootOfRoots.SetProp( "SortPropStr", "RootSortOrder" ); } private void RegisterTreeProps() { _store.ResourceTypes.Register( _resTreeRoot, "", ResourceTypeFlags.Internal | ResourceTypeFlags.NoIndex | ResourceTypeFlags.ResourceContainer ); _store.PropTypes.Register( "SortProp", PropDataType.Int, PropTypeFlags.Internal ); _store.PropTypes.Register( "SortPropStr", PropDataType.String, PropTypeFlags.Internal ); _store.PropTypes.Register( "RootSortOrder", PropDataType.Int, PropTypeFlags.Internal ); _propRootResType = _store.PropTypes.Register( "RootResourceType", PropDataType.String, PropTypeFlags.Internal ); _store.RegisterUniqueRestriction( "ResourceTreeRoot", _propRootResType ); } public IResource ResourceTreeRoot { get { return GetRootForType( _resTreeRoot ); } } public IResource GetRootForType( string resType ) { IResourceList resList = _store.FindResources( _resTreeRoot, _propRootResType, resType ); if ( resList.Count > 0 ) { return resList [0]; } ResourceProxy proxy = ResourceProxy.BeginNewResource( _resTreeRoot ); proxy.SetProp( _propRootResType, resType ); proxy.EndUpdate(); return proxy.Resource; } public void LinkToResourceRoot( IResource res, int index ) { // First, set the user-sort-order, if appropriate, so that there were no jumping of the item after it's added if(index == int.MinValue) new UserResourceOrder(res, JobPriority.Immediate).Insert( 0, new int[]{res.OriginalId}, false, null ); // To the beginning else if(index == int.MaxValue) new UserResourceOrder(res, JobPriority.Immediate).Insert( 0, new int[]{res.OriginalId}, true, null ); // To the end else if(index < 0) throw new ArgumentOutOfRangeException("index", "The index must be a non-negative integer value, int.MinValue, or int.MaxValue."); // Insert the resource IResource rootResource = GetRootForType( _resTreeRoot ); if ( res.GetLinkProp( Core.Props.Parent ) != rootResource || res.GetIntProp( "RootSortOrder" ) != index ) { ResourceProxy proxy = new ResourceProxy( res ); proxy.BeginUpdate(); if ( rootResource != null ) { proxy.AddLink( Core.Props.Parent, rootResource ); } proxy.SetProp( "RootSortOrder", index ); proxy.EndUpdate(); } } public void SetResourceNodeSort( IResource node, string sortProps ) { if ( node.GetStringProp( "SortPropStr" ) != sortProps ) { ResourceProxy proxy = new ResourceProxy( node ); proxy.BeginUpdate(); proxy.DeleteProp( "SortProp" ); proxy.SetProp( "SortPropStr", sortProps ); proxy.EndUpdate(); } lock( _sortPropCache ) { _sortPropCache [node.Id] = sortProps; } } public string GetResourceNodeSort( IResource node ) { IResource res = node; while( res != null ) { lock( _sortPropCache ) { string sort = (string) _sortPropCache [res.Id]; if ( sort != null ) return sort; sort = node.GetStringProp( "SortPropStr" ); if ( sort != null ) { _sortPropCache [node.Id] = sort; return sort; } } res = res.GetLinkProp( Core.Props.Parent ); } return null; } public void SetViewsExclusive( string resType ) { _viewsExclusive.Add( resType ); } public bool AreViewsExclusive( string resType ) { return _viewsExclusive.Contains( resType ); } public void RegisterTreeListener( IResource parent, int parentProp, IResourceListListener listener ) { TreeListenerManager manager; lock( _treeListenerManagers ) { manager = (TreeListenerManager) _treeListenerManagers [parentProp]; if ( manager == null ) { manager = new TreeListenerManager( parentProp ); _treeListenerManagers [parentProp] = manager; } } manager.RegisterListener( parent, listener ); } public void UnregisterTreeListener( IResource parent, int parentProp, IResourceListListener listener ) { TreeListenerManager manager; lock( _treeListenerManagers ) { manager = (TreeListenerManager) _treeListenerManagers [parentProp]; } if ( manager != null ) { manager.UnregisterListener( parent, listener ); } } } }