///
/// 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.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using JetBrains.DataStructures;
using JetBrains.Omea.GUIControls;
using JetBrains.Omea.OpenAPI;
namespace JetBrains.Omea
{
///
/// Control which manages creating sidebars for each tab and showing/hiding them
/// when tabs are switched.
///
internal class SidebarSwitcher : UserControl, IContextProvider, ISidebarSwitcher
{
///
/// Required designer variable.
///
private Container components = null;
private readonly Hashtable _tabSidebars = new Hashtable(); // tab ID -> VerticalSidebar
private readonly HashSet _populatedSidebars = new HashSet();
private readonly Hashtable _resourceStructurePanes = new Hashtable(); // tab ID -> pane ID of resource structure pane
private VerticalSidebar _activeSidebar;
private VerticalSidebar _newActiveSidebar;
private bool _expanded;
private int _expandedWidth;
private Image _defaultPaneImage;
private string _currentTabID;
private ColorScheme _colorScheme;
private readonly Hashtable _paneActivateActions = new Hashtable(); // AbstractViewPane -> IAction
public SidebarSwitcher()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
SetStyle( ControlStyles.Selectable, false );
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
components = new Container();
}
#endregion
public event EventHandler ExpandedChanged;
public bool Expanded
{
get { return _expanded; }
set
{
_expanded = value;
if ( ExpandedChanged != null )
{
ExpandedChanged( this, EventArgs.Empty );
}
}
}
public Image DefaultPaneIcon
{
get { return _defaultPaneImage; }
set { _defaultPaneImage = value; }
}
public int ExpandedWidth
{
get { return _expandedWidth; }
set
{
_expandedWidth = value;
if ( Expanded )
{
Width = _expandedWidth;
}
}
}
public ColorScheme ColorScheme
{
get { return _colorScheme; }
set
{
_colorScheme = value;
foreach( VerticalSidebar ctl in Controls )
{
ctl.ColorScheme = _colorScheme;
}
}
}
protected override void OnSizeChanged( EventArgs e )
{
base.OnSizeChanged( e );
VerticalSidebar sidebar = _newActiveSidebar ?? _activeSidebar;
if ( sidebar != null && sidebar.Expanded )
{
ExpandedWidth = Width;
}
}
/**
* Registers a tab and creates a sidebar for it.
*/
public void RegisterTab( string tabId, string[] resourceTypes, int linkType )
{
VerticalSidebar sidebar = new VerticalSidebar();
sidebar.Dock = DockStyle.Fill;
sidebar.Side = SidebarSide.Left;
sidebar.ColorScheme = _colorScheme;
sidebar.Visible = false;
Controls.Add( sidebar );
sidebar.Size = ClientSize;
_tabSidebars [tabId] = sidebar;
CreateDefaultPane( tabId, resourceTypes, linkType );
}
/**
* Creates a default view pane for the specified tab ID.
*/
private void CreateDefaultPane( string tabId, string[] tabResourceTypes, int tabLinkType )
{
ViewsCategoriesPane pane = new ViewsCategoriesPane();
pane.RootResource = Core.ResourceTreeManager.ResourceTreeRoot;
ContentTypeFilter filter = new ContentTypeFilter();
if ( tabResourceTypes != null )
{
string[] filterTypes = new string [tabResourceTypes.Length+1];
filterTypes [0] = "WorkspaceOtherView";
Array.Copy( tabResourceTypes, 0, filterTypes, 1, tabResourceTypes.Length );
filter.SetFilter( filterTypes, tabLinkType );
}
else
{
filter.SetFilter( tabResourceTypes, tabLinkType );
}
pane.AddContentTypes( tabResourceTypes );
pane.AddNodeFilter( filter );
pane.ShowWorkspaceOtherView = true;
AddPane( tabId, StandardViewPanes.ViewsCategories, pane, "Views and Categories", _defaultPaneImage );
}
/**
* Registers an activate action for the specified viewpane.
*/
public void RegisterActivateAction( string tabID, string paneID, string caption )
{
if ( _paneActivateActions.ContainsKey( paneID ) )
{
return;
}
IAction activateAction = new ActivateViewPaneAction( tabID, paneID );
// order of actions matches the order of tabs
Core.ActionManager.RegisterMainMenuAction( activateAction, ActionGroups.VIEW_VIEWPANE_ACTIONS,
ListAnchor.Last, caption, null, null, null );
_paneActivateActions [paneID] = activateAction;
}
/**
* Registers a view pane that will be shown in the sidebar.
*/
public void RegisterViewPane( string paneID, string tabID, string caption, Image icon, AbstractViewPane viewPane )
{
RegisterActivateAction( tabID, paneID, caption );
AddPane( tabID, paneID, viewPane, caption, icon );
}
/**
* Register a view pane that displays a portion of the resource tree.
*/
public IResourceTreePane RegisterTreeViewPane( string paneID, string tabName, string caption, Image icon, IResource rootResource )
{
JetResourceTreePane pane = new JetResourceTreePane();
pane.RootResource = rootResource;
RegisterViewPane( paneID, tabName, caption, icon, pane );
return pane;
}
/**
* Registers a resource pane that will display the resource structure (and will
* be combined with the "Views and Categories" pane) on the specified resource type tab.
*/
public void RegisterResourceStructurePane( string paneId, string tabId, string caption,
Image icon, AbstractViewPane viewPane )
{
RegisterActivateAction( tabId, paneId, caption );
AddPane( tabId, paneId, viewPane, caption, icon );
RegisterResourceStructurePane( tabId, paneId );
if ( viewPane is JetResourceTreePane )
{
ViewsCategoriesPane viewsCategoriesPane = (ViewsCategoriesPane) GetPane( tabId, StandardViewPanes.ViewsCategories );
viewsCategoriesPane.ShowWorkspaceOtherView = false;
}
}
/**
* Registers a resource structure pane based on a ResourceTreeView.
*/
public IResourceTreePane RegisterResourceStructureTreePane( string paneId, string tabId, string caption,
Image icon, IResource rootResource )
{
JetResourceTreePane pane = new JetResourceTreePane();
pane.RootResource = rootResource;
pane.RootResourceType = null;
RegisterResourceStructurePane( paneId, tabId, caption, icon, pane );
ViewsCategoriesPane viewsCategoriesPane = (ViewsCategoriesPane) GetPane( tabId, StandardViewPanes.ViewsCategories );
viewsCategoriesPane.ShowWorkspaceOtherView = false;
return pane;
}
/**
* Registers a resource structure pane which has the root of the specified type
* as the root of the ResourceTreeView.
*/
public IResourceTreePane RegisterResourceStructureTreePane( string paneId, string tabId, string caption,
Image icon, string rootResType )
{
JetResourceTreePane treePane = (JetResourceTreePane) RegisterResourceStructureTreePane( paneId, tabId, caption, icon,
Core.ResourceTreeManager.GetRootForType( rootResType ) );
treePane.RootResourceType = rootResType;
return treePane;
}
/**
* Sets the keyboard activation shortcut for the specified pane.
*/
public void RegisterViewPaneShortcut( string paneID, Keys shortcut )
{
IAction action = (IAction) _paneActivateActions [paneID];
if ( action != null )
{
Core.ActionManager.RegisterKeyboardAction( action, shortcut, null, null );
}
}
/**
* Registers a pane to be shown in the sidebar for the specified tab.
*/
public void AddPane( string tabID, string paneID, AbstractViewPane viewPane, string caption, Image icon )
{
VerticalSidebar sidebar = GetSidebar( tabID );
sidebar.RegisterPane( viewPane, paneID, caption, icon );
}
/**
* Registers the specified pane as the resource structure pane for the
* specified tab.
*/
public void RegisterResourceStructurePane( string tabId, string paneId )
{
_resourceStructurePanes [tabId] = paneId;
}
/**
* Returns the ID of the resource structure pane registered for the specified tab.
*/
public string GetResourceStructurePaneId( string tabID )
{
return (string) _resourceStructurePanes [tabID];
}
/**
* Returns the default pane for the current tab.
*/
public IResourceTreePane DefaultViewPane
{
get
{
if ( _activeSidebar == null )
return null;
return (IResourceTreePane) _activeSidebar.GetPane( StandardViewPanes.ViewsCategories );
}
}
/**
* Returns the resource structure pane for the current tab.
*/
public AbstractViewPane ResourceStructurePane
{
get
{
string paneID = GetResourceStructurePaneId( _currentTabID );
if ( paneID == null )
return null;
return _activeSidebar.GetPane( paneID );
}
}
/**
* Returns the pane with the specified ID from the current sidebar.
*/
public AbstractViewPane GetPane( string paneID )
{
if ( _activeSidebar == null )
{
return null;
}
return _activeSidebar.GetPane( paneID );
}
public AbstractViewPane GetPane( string tabId, string paneId )
{
return GetSidebar( tabId ).GetPane( paneId );
}
internal SidebarState CurrentState
{
get { return _activeSidebar.CurrentState; }
set { _activeSidebar.CurrentState = value; }
}
public VerticalSidebar ActiveSidebar
{
get { return _activeSidebar; }
}
/**
* Returns the ID of the currently active view pane.
*/
public string ActivePaneId
{
get
{
if ( _activeSidebar == null )
{
return null;
}
return _activeSidebar.ActivePaneId;
}
}
/**
* Ensures that the view pane with the specified ID is visible and sets the focus to it.
*/
public void ActivateViewPane( string paneId )
{
if ( _activeSidebar != null )
{
if ( !_activeSidebar.ContainsPane( paneId ) )
{
throw new ArgumentException( "Pane ID " + paneId + " not found in sidebar of tab " + GetSidebarTab( _activeSidebar ) );
}
_activeSidebar.ActivatePane( paneId );
}
}
public AbstractViewPane ActivateViewPane( string tabId, string paneId )
{
VerticalSidebar sidebar = _activeSidebar;
if ( sidebar == null || sidebar != _tabSidebars [tabId] )
{
return null;
}
AbstractViewPane pane = sidebar.GetPane( paneId );
if ( pane == null )
{
return null;
}
sidebar.ActivatePane( paneId );
if ( _activeSidebar != sidebar )
{
// one more check for tab switch caused by message processing during activation
return null;
}
return pane;
}
/**
* Returns the sidebar instance for the specified tab.
*/
private VerticalSidebar GetSidebar( string tabId )
{
VerticalSidebar sidebar = (VerticalSidebar) _tabSidebars [tabId];
if ( sidebar == null )
{
throw new ArgumentException( "Invalid tab ID " + tabId, "tabId" );
}
return sidebar;
}
/**
* Returns the tab ID for the specified sidebar instance.
*/
private string GetSidebarTab( VerticalSidebar sidebar )
{
foreach( DictionaryEntry de in _tabSidebars )
{
if ( de.Value == sidebar )
{
return (string) de.Key;
}
}
return "";
}
///
/// Shows the sidebar for the specified tab.
///
public void ShowPanesForTab( string tabId, SidebarState state )
{
_currentTabID = tabId;
Core.UIManager.BeginUpdateSidebar();
VerticalSidebar sidebar = GetSidebar( tabId );
if ( sidebar != _activeSidebar )
{
_newActiveSidebar = sidebar;
if ( !_populatedSidebars.Contains( tabId ) )
{
_populatedSidebars.Add( tabId );
sidebar.PopulateViewPanes();
if ( state == null )
{
sidebar.BeginUpdate();
AbstractViewPane pane = sidebar.GetPane( StandardViewPanes.ViewsCategories );
if ( pane != null )
{
sidebar.ActivatePane( StandardViewPanes.ViewsCategories );
}
string structurePaneID = (string) _resourceStructurePanes [tabId];
if ( structurePaneID != null )
{
sidebar.ActivatePane( structurePaneID );
}
sidebar.EndUpdate();
}
}
sidebar.UpdateActiveWorkspace();
if ( state != null )
{
sidebar.CurrentState = state;
}
if ( _activeSidebar != null )
{
_activeSidebar.ExpandedChanged -= OnActiveSidebarExpandedChanged;
}
sidebar.ExpandedChanged += OnActiveSidebarExpandedChanged;
Expanded = sidebar.Expanded;
// Width = Expanded ? ExpandedWidth : sidebar.CollapsedWidth;
Width = Expanded ? ExpandedWidth : 0;
}
else
{
sidebar.UpdateActiveWorkspace();
if ( state != null )
{
sidebar.CurrentState = state;
}
}
if ( sidebar != _activeSidebar )
{
sidebar.Visible = true;
if ( _activeSidebar != null )
{
_activeSidebar.Visible = false;
}
_activeSidebar = sidebar;
if ( ContainsFocus )
{
_activeSidebar.FocusActivePane();
}
}
Core.UIManager.EndUpdateSidebar();
_newActiveSidebar = null;
}
/**
* Adjusts the width of the sidebar switcher when the active sidebar is
* expanded or collapsed.
*/
private void OnActiveSidebarExpandedChanged( object sender, EventArgs e )
{
if ( !_activeSidebar.Expanded )
{
ExpandedWidth = Width;
}
Expanded = _activeSidebar.Expanded;
// Width = Expanded ? ExpandedWidth : _activeSidebar.CollapsedWidth;
Width = Expanded ? ExpandedWidth : 0;
}
public IActionContext GetContext( ActionContextKind kind )
{
if ( _activeSidebar != null )
{
return _activeSidebar.GetContext( kind );
}
return null;
}
}
///
/// Action to activate the specified view pane.
///
public class ActivateViewPaneAction: SimpleAction
{
private readonly string _tabId;
private readonly string _paneId;
internal ActivateViewPaneAction( string tabID, string paneID )
{
_tabId = tabID;
_paneId = paneID;
}
public override void Execute( IActionContext context )
{
Core.UIManager.LeftSidebarExpanded = true;
if ( Core.LeftSidebar.GetPane( _paneId ) == null && _tabId != null )
{
if ( !Core.TabManager.ActivateTab( _tabId ) )
{
return;
}
}
if ( _tabId != null )
{
Core.LeftSidebar.ActivateViewPane( _tabId, _paneId );
}
else
{
Core.LeftSidebar.ActivateViewPane( _paneId );
}
}
}
}