/// /// 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 System.Diagnostics; using System.Windows.Forms; using JetBrains.Omea.OpenAPI; namespace JetBrains.Omea { internal class BrowseStack: IDisposable { private ResourceBrowser _owner; private ArrayList _browseStack = new ArrayList(); private int _browseStackPos = -1; private static int _maxBrowseStackSize = 10; private bool _showingState = false; public BrowseStack( ResourceBrowser owner ) { _owner = owner; } public void Clear() { _browseStack.Clear(); _browseStackPos = -1; } public void Dispose() { foreach( AbstractBrowseState state in _browseStack ) { state.Dispose(); } } public int Count { get { return _browseStackPos+1; } } public static int MaxBrowseStackSize { get { return _maxBrowseStackSize; } set { _maxBrowseStackSize = value; if ( _maxBrowseStackSize < 2 ) _maxBrowseStackSize = 2; } } /** * Pushes a browse state to the browse stack. */ internal void Push( AbstractBrowseState state ) { if ( _showingState ) return; // remove entries on the top of the stack int removeCount = _browseStack.Count - _browseStackPos - 1; if ( removeCount > 0 ) { for( int i=_browseStackPos + 1; i < _browseStack.Count; i++ ) { AbstractBrowseState oldState = (AbstractBrowseState) _browseStack [i]; oldState.Dispose(); } _browseStack.RemoveRange( _browseStackPos + 1, removeCount ); } while ( _browseStack.Count > _maxBrowseStackSize ) { AbstractBrowseState oldState = (AbstractBrowseState) _browseStack [0]; oldState.Dispose(); _browseStack.RemoveAt( 0 ); _browseStackPos--; } if ( _browseStack.Count > 0 ) { SaveSelectedResource( _browseStack.Count-1 ); } _browseStack.Add( state ); _browseStackPos++; } /** * Save the currently selected resource at the specified position * in the browse stack. */ private void SaveSelectedResource( int browseStackPos ) { if ( browseStackPos < 0 || browseStackPos >= _browseStack.Count ) { return; } AbstractBrowseState browseState = (AbstractBrowseState) _browseStack [browseStackPos]; IResourceList selection = _owner.SelectedResources; if ( selection.Count > 0 && selection.ResourceIds [0] != -1 ) { browseState.SetSelectedResource( selection [0] ); } else { browseState.SetSelectedResource( null ); } } /** * Shows the browse state at the current stack position, or the previous * valid browse state. */ internal void ShowCurrentBrowseState() { _showingState = true; try { while ( _browseStackPos >= 0 ) { AbstractBrowseState state = (AbstractBrowseState) _browseStack [_browseStackPos]; // if the state failed to show, switch to previous state if ( state.Show( _owner ) ) break; _browseStack.Remove( state ); _browseStackPos--; } } finally { _showingState = false; } } public void GoBack() { Debug.WriteLine( "BrowseStack.GoBack: before back: _browseStackPos=" + _browseStackPos ); if ( _browseStackPos > 0 ) { SaveSelectedResource( _browseStackPos ); _browseStackPos--; ShowCurrentBrowseState(); Debug.WriteLine( "BrowseStack.GoBack: after back: _browseStackPos=" + _browseStackPos ); } } public bool CanBack() { return _browseStackPos > 0; } public void GoForward() { if ( _browseStackPos < _browseStack.Count-1 ) { SaveSelectedResource( _browseStackPos ); _browseStackPos++; ShowCurrentBrowseState(); } } public bool CanForward() { return _browseStackPos < _browseStack.Count-1; } internal void DropTop() { GoBack(); if ( _browseStack.Count > 1 ) { _browseStack.RemoveAt( _browseStack.Count-1 ); } } internal AbstractBrowseState Peek( int depth ) { return (AbstractBrowseState) _browseStack [_browseStackPos-depth]; } internal void Drop( int count ) { _browseStackPos -= count; ShowCurrentBrowseState(); } /// /// Discards the top entry from the browse stack without showing any other entry. /// public void DiscardTop() { Peek( 0 ).MarkDiscarded(); } } internal abstract class AbstractBrowseState: IDisposable { private string _activeTab; private string _activeSidebarPane; protected IResource _selectedResource; protected IResource _ownerResource; private object _tag; private bool _discarded; protected AbstractBrowseState( IResource ownerResource ) { _activeTab = Core.TabManager.CurrentTabId; string activePaneID = Core.LeftSidebar.ActivePaneId; if ( activePaneID != null ) { AbstractViewPane viewPane = Core.LeftSidebar.GetPane( activePaneID ); if ( viewPane != null && viewPane.SelectedResource == ownerResource ) { _activeSidebarPane = activePaneID; } } _ownerResource = ownerResource; _tag = null; } public virtual void Dispose() { } public object Tag { get { return _tag; } set { _tag = value; } } internal void MarkDiscarded() { _discarded = true; } public bool Show( ResourceBrowser owner ) { if ( _discarded ) return false; Core.UIManager.BeginUpdateSidebar(); if ( !Core.TabManager.ActivateTab( _activeTab ) ) { Core.UIManager.EndUpdateSidebar(); return false; } if ( _ownerResource != null && _activeSidebarPane != null ) { AbstractViewPane pane = Core.LeftSidebar.ActivateViewPane( _activeTab, _activeSidebarPane ); Core.UIManager.EndUpdateSidebar(); if ( pane == null ) { // DoEvents() could have happened when activating pane and caused switch to other pane // (OM-11136) return false; } pane.SelectResource( _ownerResource, false ); if ( _selectedResource != null ) { owner.SelectResource( _selectedResource ); } return true; } else { Core.UIManager.EndUpdateSidebar(); return DoShow( owner ); } } protected abstract bool DoShow( ResourceBrowser owner ); public void SetSelectedResource( IResource res ) { _selectedResource = res; } } internal class ResourceListBrowseState: AbstractBrowseState { private IResourceList _resourceList; private ResourceListDisplayOptions _options; internal ResourceListBrowseState( IResource ownerResource, IResourceList resourceList, ResourceListDisplayOptions options ) : base( ownerResource ) { _resourceList = resourceList; _options = options; } public override void Dispose() { _resourceList.Dispose(); } protected override bool DoShow( ResourceBrowser owner ) { owner.DoShowResources( _ownerResource, _resourceList, _options ); return true; } } internal class ResourceBrowseState: AbstractBrowseState { private IResource _resource; private bool _backOnDelete; internal ResourceBrowseState( IResource resource, bool backOnDelete ) : base( resource ) { _resource = resource; _backOnDelete = backOnDelete; } protected override bool DoShow( ResourceBrowser owner ) { if ( _resource.IsDeleted ) return false; owner.DoShowResource( _resource, _backOnDelete ); return true; } } }