///
/// 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.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Windows.Forms;
using JetBrains.Omea.GUIControls;
using JetBrains.Omea.OpenAPI;
using JetBrains.Omea.ResourceTools;
namespace JetBrains.Omea
{
/**
* Pane displaying all the links of the specified resource.
*/
internal class LinksPane: LinksPaneBase
{
private System.ComponentModel.IContainer components;
private ToolTip _toolTip;
private Panel _borderPanel;
private int _scrollY;
private readonly Font _linkTypeLabelFont = new Font( "Tahoma", 8, FontStyle.Bold );
private readonly Font _linkLabelFont = new Font( "Tahoma", 8 );
private readonly ControlPool _resourceLinkLabelPool;
private readonly ControlPool _linkTypeLabelPool;
private readonly ControlPool _actionLabelPool;
private readonly ControlPool _separatorPool;
private const int _linkTypeLabelX = 6;
private const int _linkLabelX = 14;
public LinksPane()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
_linkTypeLabelPool = new ControlPool( _borderPanel, OnCreateLinkTypeLabel );
_actionLabelPool = new ControlPool( _borderPanel, OnCreateActionLabel );
_separatorPool = new ControlPool( _borderPanel, OnCreateSeparator );
_resourceLinkLabelPool = new ControlPool( _borderPanel, OnCreateResourceLinkLabel );
_resourceLinkLabelPool.DisposeDelegate = OnDisposeResourceLinkLabel;
SetStyle( ControlStyles.UserPaint, true );
}
///
/// 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.components = new System.ComponentModel.Container();
this._toolTip = new System.Windows.Forms.ToolTip(this.components);
this._borderPanel = new System.Windows.Forms.Panel();
this._borderPanel.SuspendLayout();
this.SuspendLayout();
//
// _borderPanel
//
this._borderPanel.AutoScroll = true;
this._borderPanel.BorderStyle = BorderStyle.None;
this._borderPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this._borderPanel.Location = new System.Drawing.Point(0, 0);
this._borderPanel.Name = "_borderPanel";
this._borderPanel.Size = new System.Drawing.Size(150, 150);
this._borderPanel.TabIndex = 0;
this._borderPanel.Paint += new PaintEventHandler(_borderPanel_Paint);
//
// LinksPane
//
this.Controls.Add( _borderPanel );
this.Name = "LinksPane";
this.Layout += new System.Windows.Forms.LayoutEventHandler(this.LinksPane_Layout);
this._borderPanel.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
protected override void OnColorSchemeChanged()
{
if ( _colorScheme != null )
{
BackColor = _colorScheme.GetColor( "LinksPane.Group" );
}
}
public void DisplayLinks( IResourceList resList, ILinksPaneFilter filter )
{
SetResourceList( resList, filter );
_scrollY = 0;
SuspendLayout();
try
{
if ( _resourceList == null || _resourceList.Count == 0 )
{
RemoveAllControls();
DisposePooledControls();
_borderPanel.Invalidate();
}
else
{
UpdateLinksPane();
}
}
finally
{
ResumeLayout();
}
}
/**
* Moves to the pool or disposes the controls added to the links pane.
*/
private void RemoveAllControls()
{
_linkTypeLabelPool.MoveControlsToPool();
_resourceLinkLabelPool.MoveControlsToPool();
_actionLabelPool.MoveControlsToPool();
_separatorPool.MoveControlsToPool();
for ( int i = _borderPanel.Controls.Count-1; i >= 0; i-- )
{
Control ctl = _borderPanel.Controls [i];
if ( !_linkTypeLabelPool.IsPooledControl( ctl ) && !_resourceLinkLabelPool.IsPooledControl( ctl )
&& !_actionLabelPool.IsPooledControl( ctl ) && !_separatorPool.IsPooledControl( ctl ) )
{
_borderPanel.Controls.RemoveAt( i );
ctl.Dispose();
}
}
}
/**
* Disposes of all controls that have been moved to the pool and not reused.
*/
private void DisposePooledControls()
{
_resourceLinkLabelPool.RemovePooledControls();
_linkTypeLabelPool.RemovePooledControls();
_actionLabelPool.RemovePooledControls();
_separatorPool.RemovePooledControls();
}
protected override void UpdateLinksPane()
{
if ( Core.State == CoreState.ShuttingDown )
{
return;
}
if ( _resourceList != null && _resourceList.Count == 1 && _resourceList [0].IsDeleting )
{
return;
}
RemoveAllControls();
_borderPanel.AutoScrollPosition = new Point( 0, 0 );
if ( _resourceList != null && _resourceList.Count > 0 )
{
int curX = 0;
int curY = 4 - _scrollY;
if ( _resourceList.Count == 1 )
{
LinkSection section = BuildLinksForResource( _resourceList[ 0 ] );
ShowLinksFromSection( section, ref curX, ref curY );
ShowCustomPropertiesForResource( _resourceList[ 0 ], ref curX, ref curY );
}
else
{
AddLinkTypeLabel( ref curX, ref curY, _resourceList.Count + " resources selected" );
curY += 8;
}
LinksPaneActionItem[] actionItems = LinksPaneActionManager.GetManager().CreateActionLinks( _resourceList, _filter );
if ( actionItems.Length > 0 )
{
AddLinkTypeLabel( ref curX, ref curY, "Actions" );
foreach( LinksPaneActionItem item in actionItems )
{
JetLinkLabel lbl = (JetLinkLabel) _actionLabelPool.GetControl();
lbl.AutoSize = false;
lbl.Enabled = item.Enabled;
lbl.Text = item.Text;
lbl.Tag = item.Action;
lbl.BackColor = Color.FromArgb( 0, SystemColors.Control );
lbl.Bounds = new Rectangle( _linkLabelX, curY, Width - _linkLabelX - 4, lbl.PreferredSize.Height );
curY += 18;
}
}
UpdateLinkLabelTooltips();
}
DisposePooledControls();
_borderPanel.Invalidate();
}
/**
* Shows the custom properties for the specified resource.
*/
private void ShowCustomPropertiesForResource( IResource res, ref int curX, ref int curY )
{
foreach( IResource propTypeRes in ResourceTypeHelper.GetCustomProperties() )
{
int propID = propTypeRes.GetIntProp( "ID" );
if ( res.HasProp( propID ) )
{
AddLinkTypeLabel( ref curX, ref curY, Core.ResourceStore.PropTypes.GetPropDisplayName( propID ) );
string propText = GetCustomPropText( res, propID );
AddRegularLabel( new Rectangle( _linkLabelX, curY, Width-_linkLabelX, 16 ), propText );
curY += 16;
}
}
}
private void ShowLinksFromSection( LinkSection section, ref int curX, ref int curY )
{
while( section != null )
{
AddLinkTypeLabel( ref curX, ref curY, section.Name );
LinkItem lastLinkItem = null;
for( int i=0; i < 5 && i < section.LinkItems.Count; i++ )
{
LinkItem item = (LinkItem) section.LinkItems [i];
Control ctl = AddResourceLabel( item.Resource, item.PropId, _resourceList [0], curY );
ctl.Tag = item.ToolTip;
curY += ctl.Height;
lastLinkItem = item;
}
if ( section.LinkItems.Count > 5 )
{
JetLinkLabel seeAllLabel = AddLinkLabel( new Rectangle( _linkLabelX, curY, Width-_linkLabelX, 16 ),
"See All (" + section.LinkItems.Count + ")..." );
seeAllLabel.Tag = lastLinkItem.PropId;
seeAllLabel.Click += OnSeeAllClick;
curY += 18;
}
else
{
curY += 2;
}
if ( section.Separator )
{
AddLinkGroupSeparator( ref curY );
}
section = section.NextSection;
}
}
/**
* Creates a link type label with the specified name.
*/
private Control AddLinkTypeLabel( ref int curX, ref int curY, string text )
{
JetLinkLabel typeLabel = (JetLinkLabel) _linkTypeLabelPool.GetControl();
int typeLabelHeight = (int) ( 17 * Core.ScaleFactor.Height );
typeLabel.Text = text;
typeLabel.Bounds = new Rectangle( _linkTypeLabelX, curY, Width - _linkTypeLabelX - 4, typeLabelHeight );
typeLabel.Visible = true;
typeLabel.ForeColor = ColorScheme.GetColor( _colorScheme, "LinksPane.LinkTypeText", Color.Black );
curY += typeLabelHeight;
return typeLabel;
}
/**
* Adds an icon and label for a single resource.
*/
private ResourceLinkLabel AddResourceLabel( IResource linkRes, int linkType, IResource linkOwnerRes,
int curY )
{
ResourceLinkLabel linkLabel = (ResourceLinkLabel) _resourceLinkLabelPool.GetControl();
linkLabel.Resource = linkRes;
linkLabel.LinkOwnerResource = linkOwnerRes;
linkLabel.LinkType = Math.Abs( linkType );
linkLabel.Bounds = new Rectangle( _linkLabelX, curY, Width - _linkLabelX - 4,
(int) ( 19 * Core.ScaleFactor.Height ) );
linkLabel.EndEllipsis = true;
return linkLabel;
}
/**
* Creates a resource link label for the pool.
*/
private Control OnCreateResourceLinkLabel()
{
ResourceLinkLabel linkLabel = new ResourceLinkLabel();
linkLabel.LinkContextMenu += linkLabel_LinkContextMenu;
linkLabel.ResourceChanged += HandleLinkedResourceChanged;
linkLabel.BackColor = Color.FromArgb( 0, DefaultBackColor );
return linkLabel;
}
private void OnDisposeResourceLinkLabel( Control ctl )
{
ResourceLinkLabel linkLabel = ctl as ResourceLinkLabel;
if ( linkLabel != null )
{
linkLabel.LinkContextMenu -= linkLabel_LinkContextMenu;
linkLabel.ResourceChanged -= HandleLinkedResourceChanged;
}
}
/**
* Adds a regular label to the list of controls.
*/
private JetLinkLabel AddRegularLabel( Rectangle bounds, string text )
{
JetLinkLabel lbl = new JetLinkLabel();
lbl.Bounds = bounds;
lbl.Text = text;
lbl.AutoSize = true;
lbl.ClickableLink = false;
lbl.BackColor = Color.FromArgb( 0, DefaultBackColor );
lbl.Font = new Font( "Tahoma", 8 );
lbl.EndEllipsis = true;
_borderPanel.Controls.Add( lbl );
return lbl;
}
/**
* Adds a link-like label to the list of controls.
*/
private JetLinkLabel AddLinkLabel( Rectangle bounds, string text )
{
JetLinkLabel linkLabel = AddRegularLabel( bounds, text );
linkLabel.ClickableLink = true;
linkLabel.Font = _linkLabelFont;
return linkLabel;
}
private Control OnCreateLinkTypeLabel()
{
JetLinkLabel typeLabel = new JetLinkLabel();
typeLabel.Font = _linkTypeLabelFont;
typeLabel.AutoSize = true;
typeLabel.ClickableLink = false;
typeLabel.BackColor = Color.FromArgb( 0, DefaultBackColor );
return typeLabel;
}
private Control OnCreateSeparator()
{
GradientBar bar = new GradientBar();
bar.Size = new Size( _borderPanel.Width, 1 );
bar.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
bar.StartColor = Color.FromArgb( 184, 181, 200 );
bar.EndColor = bar.StartColor;
bar.GradientMode = LinearGradientMode.Vertical;
return bar;
}
private Control OnCreateActionLabel()
{
JetLinkLabel lbl = new JetLinkLabel();
lbl.Click += LinksPaneActionManager.GetManager().OnActionLabelClick;
lbl.Font = _linkLabelFont;
return lbl;
}
private void AddLinkGroupSeparator( ref int curY )
{
Control separator = _separatorPool.GetControl();
separator.Location = new Point( 0, curY );
curY += 3;
}
private void linkLabel_LinkContextMenu( object sender, ResourceLinkLabelEventArgs e )
{
ResourceLinkLabel linkLabel = (ResourceLinkLabel) sender;
ShowLinkContextMenu( linkLabel, e );
}
private void HandleLinkedResourceChanged( object sender, ResourcePropEventArgs e )
{
if ( e.Resource.HasProp( Core.Props.IsDeleted ) )
{
Core.UIManager.QueueUIJob( new MethodInvoker( UpdateLinksPane ) );
}
}
/**
* When the "See All..." label is clicked, displays all links of the
* specified type in the resource browser.
*/
private void OnSeeAllClick( object sender, EventArgs e )
{
if ( _resourceList != null && _resourceList.Count == 1 )
{
IResource res = _resourceList [0];
Control linkLabel = (Control) sender;
int linkType = (int) linkLabel.Tag;
IResourceList links;
if ( linkType < 0 )
{
links = res.GetLinksToLive( null, -linkType );
}
else if ( Core.ResourceStore.PropTypes [linkType].HasFlag( PropTypeFlags.DirectedLink ) )
{
links = res.GetLinksFromLive( null, linkType );
}
else
{
links = res.GetLinksOfTypeLive( null, linkType );
}
links = ResourceTypeHelper.ExcludeUnloadedPluginResources( links );
Core.UIManager.BeginUpdateSidebar();
Core.TabManager.SelectResourceTypeTab( null );
Core.UIManager.EndUpdateSidebar();
ResourceListDisplayOptions options = new ResourceListDisplayOptions();
options.Caption = _store.PropTypes.GetPropDisplayName( linkType ) + " links to " + res.DisplayName;
options.TabFilter = false;
options.SetTransientContainer( Core.ResourceTreeManager.ResourceTreeRoot,
StandardViewPanes.ViewsCategories );
Core.ResourceBrowser.DisplayResourceList( null, links, options );
Core.ResourceBrowser.FocusResourceList();
}
}
private void LinksPane_Layout( object sender, LayoutEventArgs e )
{
UpdateLinkLabelTooltips();
}
///
/// For the link labels which are wider than the links pane, shows their
/// full text in the tooltips.
///
private void UpdateLinkLabelTooltips()
{
foreach( Control control in _borderPanel.Controls )
{
if ( control is ResourceLinkLabel )
{
ResourceLinkLabel linkLabel = (ResourceLinkLabel) control;
linkLabel.NameLabel.Width = Width - 4 - linkLabel.NameLabel.Left - linkLabel.Left;
string linkTooltip = (string) linkLabel.Tag;
if ( linkTooltip != null )
{
_toolTip.SetToolTip( linkLabel.NameLabel, linkTooltip );
}
else if ( linkLabel.Left + linkLabel.PreferredWidth > this.Width )
{
_toolTip.SetToolTip( linkLabel.NameLabel, linkLabel.NameLabel.Text );
}
else
{
_toolTip.SetToolTip( linkLabel.NameLabel, null );
}
}
else if ( control is JetLinkLabel )
{
JetLinkLabel linkLabel = (JetLinkLabel) control;
linkLabel.Width = Width - 4 - linkLabel.Left;
if ( linkLabel.Left + linkLabel.PreferredWidth > this.Width )
{
_toolTip.SetToolTip( linkLabel, linkLabel.Text );
}
else
{
_toolTip.SetToolTip( linkLabel, null );
}
}
}
}
private void _borderPanel_Paint( object sender, PaintEventArgs e )
{
using( Pen dividerPen = new Pen( Color.FromArgb( 184, 181, 200 ) ) )
{
e.Graphics.DrawLine( dividerPen, 0, 0, 0, _borderPanel.Height-1 );
}
}
}
}