///
/// 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.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using GUIControls.Controls;
using JetBrains.JetListViewLibrary;
using JetBrains.Omea.OpenAPI;
using JetBrains.Omea.ResourceTools;
namespace JetBrains.Omea.GUIControls
{
///
/// Implementation of IResourceTreePane based on JetListView. Does not provide any workspace
/// filtering behavior.
///
public class ResourceTreePaneBase: AbstractViewPane, IResourceTreePane, IContextProvider, ICommandProcessor, IColorSchemeable
{
private ToolStrip _toolBar;
///
/// Required designer variable.
///
private Container components = null;
protected ResourceListView2 _resourceTree;
private readonly ToolbarActionManager _toolbarManager;
private readonly UnreadNodeDecorator _unreadDecorator;
private readonly RichTextColumn _textColumn;
protected ResourceTreeDataProvider _dataProvider;
protected int _parentProperty = -1;
protected IResource _rootResource;
private string _rootResourceType;
protected string[] _workspaceFilterTypes;
private ResourceToolTipCallback _resourceToolTipCallback;
private bool _populated = false;
private ColorScheme _colorScheme;
public ResourceTreePaneBase()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
_resourceTree = new ResourceListView2();
_resourceTree.Dock = DockStyle.Fill;
_resourceTree.BorderStyle = BorderStyle.None;
_resourceTree.ContextProvider = this;
TreeStructureColumn treeStructureColumn = new TreeStructureColumn();
treeStructureColumn.Width = 20;
_resourceTree.Columns.Add( treeStructureColumn );
_resourceTree.Columns.Add( new ResourceIconColumn() );
_resourceTree.JetListView.KeyDown += HandleResourceTreeKeyDown;
_resourceTree.JetListView.ActiveNodeChanged += HandleActiveNodeChanged;
_resourceTree.KeyNavigationCompleted += HandleKeyNavigationCompleted;
_textColumn = new RichTextColumn();
_textColumn.SizeToContent = true;
_textColumn.ItemToolTipCallback = HandleToolTipCallback;
_resourceTree.Columns.Add( _textColumn );
Controls.Add( _resourceTree );
Controls.SetChildIndex( _resourceTree, 0 );
_toolbarManager = new ToolbarActionManager( _toolBar );
_toolbarManager.ContextProvider = this;
_dataProvider = new ResourceTreeDataProvider();
SetStyle( ControlStyles.Selectable, false );
UnreadManager unreadManager = (UnreadManager) Core.UnreadManager;
if ( unreadManager.Enabled )
{
_unreadDecorator = new UnreadNodeDecorator();
_textColumn.AddNodeDecorator( _unreadDecorator );
}
}
///
/// 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()
{
this._toolBar = new ToolStrip();
this.SuspendLayout();
//
// _toolBar
//
this._toolBar.Location = new System.Drawing.Point(0, 0);
this._toolBar.Name = "_toolBar";
this._toolBar.Size = new System.Drawing.Size(150, 32);
this._toolBar.TabIndex = 2;
this._toolBar.Renderer = new GradientRenderer( Color.White, SystemColors.ControlDark );
//
// JetResourceTreePane
//
this.Controls.Add(this._toolBar);
this.Name = "JetResourceTreePane";
this.ResumeLayout(false);
}
#endregion
public ResourceListView2 ResourceTree
{
get { return _resourceTree; }
}
public IResource RootResource
{
get { return _rootResource; }
set { _rootResource = value; }
}
public ResourceTreeDataProvider DataProvider
{
get { return _dataProvider; }
}
///
/// Specifies that the root of the pane is the root resource registered for the
/// specified resource type, and that when the pane is in workspace mode, it should
/// show only resources of that type connected to the workspace.
///
[DefaultValue(null)]
public string RootResourceType
{
get { return _rootResourceType; }
set
{
_rootResourceType = value;
if ( _rootResourceType != null )
{
_rootResource = Core.ResourceTreeManager.GetRootForType( _rootResourceType );
_workspaceFilterTypes = new[] { _rootResourceType };
}
}
}
[DefaultValue(-1)]
public int ParentProperty
{
get { return _parentProperty; }
set { _parentProperty = value; }
}
/**
* State of unread counters used by the unread decorator.
*/
public UnreadState UnreadState
{
get { return _unreadDecorator.UnreadState; }
set
{
if ( _unreadDecorator != null )
{
_unreadDecorator.UnreadState = value;
_textColumn.InvalidateRichText();
}
}
}
public override void Populate()
{
_populated = true;
// if ( _toolBar.Buttons.Count == 0 )
if ( _toolBar.Items.Count == 0 )
{
_toolBar.Visible = false;
}
if ( _unreadDecorator != null )
{
_unreadDecorator.UnreadState = (Core.UnreadManager as UnreadManager).CurrentUnreadState;
}
if ( _parentProperty == -1 )
{
_parentProperty = Core.Props.Parent;
}
if ( RootResource == null )
{
RootResource = Core.ResourceTreeManager.ResourceTreeRoot;
}
_resourceTree.OpenProperty = Core.Props.Open;
_dataProvider.SetRootResource( _rootResource, _parentProperty );
_resourceTree.DataProvider = _dataProvider;
}
public void RegisterToolbarAction( IAction action, Icon icon, string text, string tooltip, IActionStateFilter[] filters )
{
_toolBar.Visible = true;
_toolbarManager.RegisterAction( action, null, ListAnchor.Last, icon, text, tooltip, null, filters );
}
public void RegisterToolbarAction( IAction action, Image icon, string text, string tooltip, IActionStateFilter[] filters )
{
_toolBar.Visible = true;
_toolbarManager.RegisterAction( action, null, ListAnchor.Last, icon, text, tooltip, null, filters );
}
public void AddNodeFilter( IResourceNodeFilter nodeFilter )
{
_resourceTree.Filters.Add( new ResourceNodeFilterAdapter( nodeFilter ) );
}
public void UpdateNodeFilter( bool keepSelection )
{
_resourceTree.Filters.Update();
}
public void SelectResource( IResource res )
{
if ( !_populated )
{
return;
}
_dataProvider.SelectResource( res );
UpdateSelection();
}
public override bool SelectResource( IResource resource, bool highlightOnly )
{
if ( !_populated )
{
return false;
}
bool result = _dataProvider.SelectResource( resource );
if ( result && !highlightOnly )
{
UpdateSelection();
}
return result;
}
public void EditResourceLabel( IResource res )
{
if ( !_populated )
{
return;
}
_resourceTree.EditResourceLabel( res );
}
public void ExpandParents( IResource res )
{
// do nothing if the pane has not been populated
if ( _parentProperty != -1 )
{
_dataProvider.FindResourceNode( res );
}
}
public void EnableDropOnEmpty( IResourceUIHandler emptyDropHandler )
{
_resourceTree.EmptyDropHandler = new DragDropHandlerAdapter( emptyDropHandler );
}
public void EnableDropOnEmpty( IResourceDragDropHandler emptyDropHandler )
{
_resourceTree.EmptyDropHandler = emptyDropHandler;
}
public override IResource SelectedResource
{
get { return SelectedNode; }
}
public IResource SelectedNode
{
get
{
JetListViewNode node = _resourceTree.Selection.ActiveNode;
if ( node == null )
{
return null;
}
return (IResource) node.Data;
}
}
public override bool ShowSelection
{
get { return !_resourceTree.HideSelection; }
set { _resourceTree.HideSelection = !value; }
}
[DefaultValue( false )]
public bool SelectAddedItems
{
get { return _resourceTree.SelectAddedItems; }
set { _resourceTree.SelectAddedItems = value; }
}
public string[] WorkspaceFilterTypes
{
get { return _workspaceFilterTypes; }
set { _workspaceFilterTypes = value; }
}
public ResourceToolTipCallback ToolTipCallback
{
get { return _resourceToolTipCallback; }
set { _resourceToolTipCallback = value; }
}
public IActionContext GetContext( ActionContextKind kind )
{
ActionContext context = new ActionContext( kind, this, _resourceTree.GetSelectedResources() );
context.SetCommandProcessor( this );
return context;
}
public void AddNodeDecorator( IResourceNodeDecorator decorator )
{
_textColumn.AddNodeDecorator( decorator );
}
///
/// Method is supposed to control the order of decorators activation in
/// more flexible manner, due to the fixed (previously) position of
/// UnreadNodeDecorator handler.
///
public void InsertNodeDecorator( IResourceNodeDecorator decorator, int pos )
{
_textColumn.InsertNodeDecorator( decorator, pos );
}
private void HandleActiveNodeChanged( object sender, JetListViewNodeEventArgs e )
{
AsyncUpdateSelection();
}
protected override void OnEnter( EventArgs e )
{
base.OnEnter( e );
AsyncUpdateSelection();
}
public override void AsyncUpdateSelection()
{
Core.UIManager.QueueUIJob( new MethodInvoker( LazyUpdateSelection ) );
}
private void LazyUpdateSelection()
{
if ( Core.LeftSidebar.GetPane( Core.LeftSidebar.ActivePaneId ) != this )
{
return;
}
if ( Core.ResourceBrowser.OwnerResource != _resourceTree.ActiveResource ||
Core.ResourceBrowser.LastFilterResourceList != Core.ResourceBrowser.FilterResourceList ||
Core.ResourceBrowser.WebPageMode )
{
UpdateSelection();
}
}
public override void UpdateSelection()
{
IResource res = _resourceTree.ActiveResource;
if ( res != null && !res.IsDeleted && Core.State != CoreState.ShuttingDown &&
!_resourceTree.KeyNavigation )
{
IResourceUIHandler treeHandler = Core.PluginLoader.GetResourceUIHandler( res );
if ( treeHandler != null )
{
treeHandler.ResourceNodeSelected( res );
}
else
{
Core.ResourceBrowser.DisplayResourceList( null, Core.ResourceStore.EmptyResourceList,
res.DisplayName, null );
}
}
else if ( res == null && _resourceTree.VisibleItemCount == 0 )
{
Core.ResourceBrowser.DisplayResourceList( null, Core.ResourceStore.EmptyResourceList,
"No resource selected", null );
}
Core.UserInterfaceAP.CancelJobs( new MethodInvoker( LazyUpdateSelection ) );
}
private void HandleKeyNavigationCompleted( object sender, EventArgs e )
{
UpdateSelection();
}
#region Goto Prev/Next Simple/Unread
public override bool GotoPrevView( IResource view )
{
IResource res = _resourceTree.LocatePrevResource( view, MatchAny, true, true );
if ( res != null )
{
// make sure synchronous selection update is performed
ExpandParents( res );
SelectResource( res, false );
return true;
}
return false;
}
public override bool GotoPrevUnreadView( IResource view )
{
IResource res = _resourceTree.LocatePrevResource( view, MatchUnreadCount, true, true );
if ( res != null )
{
// make sure synchronous selection update is performed
ExpandParents( res );
SelectResource( res, false );
return true;
}
return false;
}
public override bool GotoNextView( IResource view )
{
IResource res = _resourceTree.LocateNextResource( view, MatchAny, true, true );
if ( res != null )
{
// make sure synchronous selection update is performed
ExpandParents( res );
SelectResource( res, false );
return true;
}
return false;
}
public override bool GotoNextUnreadView( IResource view )
{
IResource res = _resourceTree.LocateNextResource( view, MatchUnreadCount, true, true );
if ( res != null )
{
// make sure synchronous selection update is performed
ExpandParents( res );
SelectResource( res, false );
return true;
}
return false;
}
private static bool MatchUnreadCount( IResource res )
{
return Core.UnreadManager.GetUnreadCount( res ) > 0;
}
private static bool MatchAny( IResource res )
{
return (res.GetLinksTo( null, Core.Props.Parent ).Count == 0);
}
#endregion Goto Prev/Next Simple/Unread
private void HandleResourceTreeKeyDown( object sender, KeyEventArgs e )
{
if ( e.KeyCode == Keys.Space )
{
IResource res = SelectedResource;
if ( Core.ResourceBrowser.GotoNextUnread() || GotoNextUnreadView( res ) )
{
e.Handled = true;
Core.ResourceBrowser.FocusResourceList();
}
}
}
private string HandleToolTipCallback( object item )
{
if ( _resourceToolTipCallback != null )
{
IResource res = (IResource) item;
return _resourceToolTipCallback( res );
}
return null;
}
public bool CanExecuteCommand( string command )
{
return _resourceTree.CanExecuteCommand( command );
}
public void ExecuteCommand( string command )
{
_resourceTree.ExecuteCommand( command );
}
public ColorScheme ColorScheme
{
get { return _colorScheme; }
set
{
_colorScheme = value;
/*
_toolBar.GradientStartColor = ColorScheme.GetStartColor( _colorScheme, "Toolbar.Background", Color.White );
_toolBar.GradientEndColor = ColorScheme.GetEndColor( _colorScheme, "Toolbar.Background", SystemColors.ControlDark );
*/
}
}
}
internal class DragDropHandlerAdapter : IResourceDragDropHandler
{
private readonly IResourceUIHandler _handler;
public DragDropHandlerAdapter( IResourceUIHandler handler )
{
_handler = handler;
}
public void AddResourceDragData( IResourceList dragResources, IDataObject dataObject )
{
}
public DragDropEffects DragOver( IResource targetResource, IDataObject data, DragDropEffects allowedEffect,
int keyState )
{
IResourceList resList = (IResourceList) data.GetData( typeof(IResourceList) );
if ( resList != null && resList.Count > 0 && !resList.Contains( targetResource ) )
{
if ( _handler.CanDropResources( targetResource, resList ) )
{
return DragDropEffects.Link;
}
}
return DragDropEffects.None;
}
public void Drop( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState )
{
IResourceList resList = (IResourceList) data.GetData( typeof(IResourceList) );
if ( resList != null && resList.Count > 0 && !resList.Contains( targetResource ) )
{
_handler.ResourcesDropped( targetResource, resList );
}
}
}
internal class ResourceNodeFilterAdapter: IJetListViewNodeFilter
{
private IResourceNodeFilter _filter;
public ResourceNodeFilterAdapter( IResourceNodeFilter filter )
{
_filter = filter;
}
public bool AcceptNode( JetListViewNode node )
{
return _filter.AcceptNode( (IResource) node.Data, node.Level );
}
public event EventHandler FilterChanged;
}
}