///
/// 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.IO;
using System.Windows.Forms;
using JetBrains.Omea.Base;
using JetBrains.Omea.Containers;
using JetBrains.Omea.GUIControls;
using JetBrains.Omea.OpenAPI;
using JetBrains.Omea.ResourceTools;
using JetBrains.UI.Components.ImageListButton;
namespace JetBrains.Omea
{
/**
* The collapsed version of the links pane.
*/
internal class LinksBar: LinksPaneBase
{
private const int _cSpaceAfterLinkType = 6;
private const int _cStartLinkY = 2;
private System.ComponentModel.IContainer components;
private IResource _resource;
private readonly Font _linkTypeLabelFont = new Font( "Tahoma", 8, FontStyle.Bold );
private readonly Font _actionFont = new Font( "Tahoma", 8 );
private readonly ControlPool _resourceLinkLabelPool;
private readonly ControlPool _linkTypeLabelPool;
private readonly ControlPool _actionLabelPool;
private Panel _contactThumb;
private ImageListButton _btnExpand;
private ImageList _iconImages;
private bool _expanded;
private ToolTip _toolTip;
private bool _verticalViewMode;
private bool _verticalViewExpanded;
private readonly int _defltVerticalViewLines;
private float _scaleHeight = 1.0f;
public LinksBar()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
SetStyle( ControlStyles.ResizeRedraw, true );
_linkTypeLabelPool = new ControlPool( this, OnCreateLinkTypeLabel );
_resourceLinkLabelPool = new ControlPool( this, OnCreateResourceLinkLabel );
_resourceLinkLabelPool.DisposeDelegate = OnDisposeResourceLinkLabel;
_actionLabelPool = new ControlPool( this, OnCreateActionLabel );
_defltVerticalViewLines = Core.SettingStore.ReadInt( "LinksBar", "VerticalViewLines", 3 );
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
public event EventHandler LinksPaneExpandChanged;
#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();
_toolTip = new System.Windows.Forms.ToolTip(this.components);
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(LinksBar));
this._btnExpand = new ImageListButton();
_contactThumb = new Panel();
this._iconImages = new System.Windows.Forms.ImageList(this.components);
this.SuspendLayout();
//
// _btnExpand
//
this._btnExpand.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this._btnExpand.BackColor = Color.Transparent;
this._btnExpand.ImageList = this._iconImages;
this._btnExpand.Location = new System.Drawing.Point(134, 3);
this._btnExpand.Name = "_chkExpand";
this._btnExpand.Size = new System.Drawing.Size(16, 16);
this._btnExpand.TabIndex = 0;
this._btnExpand.TabStop = false;
this._btnExpand.Click += new EventHandler(_btnExpand_OnClick);
//
// _contactThumb
//
_contactThumb.BorderStyle = BorderStyle.Fixed3D;
_contactThumb.Location = new Point(4, 4);
_contactThumb.Name = "_contactThumb";
_contactThumb.Size = new Size(48, 48);
_contactThumb.Anchor = AnchorStyles.Left | AnchorStyles.Top;
_contactThumb.BackColor = Color.FromArgb( 0, DefaultBackColor );
//
// _iconImages
//
this._iconImages.ImageSize = new System.Drawing.Size(16, 16);
this._iconImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("_iconImages.ImageStream")));
this._iconImages.TransparentColor = System.Drawing.Color.Transparent;
//
// LinksBar
//
this.Controls.Add(this._btnExpand);
this.Controls.Add(_contactThumb);
this.Name = "LinksBar";
this.Size = new System.Drawing.Size(150, 20);
this.ResumeLayout(false);
}
#endregion
protected override void ScaleCore( float dx, float dy )
{
base.ScaleCore( dx, dy );
_scaleHeight = dy;
}
public bool LinksPaneExpanded
{
get { return _expanded; }
set
{
if ( _expanded != value )
{
_expanded = value;
UpdateExpandButtonImage();
if ( LinksPaneExpandChanged != null )
{
LinksPaneExpandChanged( this, EventArgs.Empty );
}
}
}
}
[Browsable(false)]
public bool VerticalViewMode
{
get { return _verticalViewMode; }
set
{
if ( _verticalViewMode != value )
{
_verticalViewMode = value;
if ( _verticalViewMode )
{
Height = 60;
BackColor = SystemColors.Window;
}
else
{
Height = 20;
}
UpdateLinksPane();
UpdateExpandButtonImage();
}
}
}
protected override void OnColorSchemeChanged()
{
_btnExpand.ImageList = _colorScheme.GetImageList( "LinksBar.ExpandCollapse" );
UpdateExpandButtonImage();
}
private void UpdateExpandButtonImage()
{
int stateStartIndex;
if ( _verticalViewMode )
{
stateStartIndex = _verticalViewExpanded ? 0 : 3;
}
else
{
stateStartIndex = _expanded ? 0 : 3;
}
_btnExpand.NormalImageIndex = stateStartIndex;
_btnExpand.HotImageIndex = stateStartIndex + 1;
_btnExpand.PressedImageIndex = stateStartIndex + 2;
}
private void _btnExpand_OnClick( object sender, EventArgs e )
{
if ( !_verticalViewMode )
{
LinksPaneExpanded = !LinksPaneExpanded;
}
else
{
_verticalViewExpanded = !_verticalViewExpanded;
UpdateExpandButtonImage();
UpdateLinksPane();
}
}
/**
* Displays the links of the specified resource in the links bar.
*/
public void DisplayLinks( IResource res, ILinksPaneFilter filter )
{
_resource = res;
SetResourceList( res == null ? null : res.ToResourceList(), filter );
UpdateLinksPane();
}
/**
* Rebuilds the links bar.
*/
protected override void UpdateLinksPane()
{
if ( Core.State == CoreState.ShuttingDown )
{
return;
}
_linkTypeLabelPool.MoveControlsToPool();
_resourceLinkLabelPool.MoveControlsToPool();
_actionLabelPool.MoveControlsToPool();
if ( _resource != null )
{
FillLinkedThumb( _resource );
FillLinksBar( _resource );
}
_resourceLinkLabelPool.RemovePooledControls();
_linkTypeLabelPool.RemovePooledControls();
_actionLabelPool.RemovePooledControls();
}
/**
* Creates the link type and link labels for the specified resource.
*/
private void FillLinksBar( IResource res )
{
LinkSection section = BuildLinksForResource( res );
if ( _verticalViewMode )
{
BuildVerticalViewLinks( section );
}
else
{
BuildHorizontalViewLinks( section );
}
}
private void BuildHorizontalViewLinks( LinkSection section )
{
int curX = 4, curY = 0;
while( section != null )
{
int maxWidth = 0;
Label typeLabel = AddLinkTypeLabel( ref curX, ref curY, section.Name, ref maxWidth );
if ( curX > Width )
{
typeLabel.Visible = false;
break;
}
if ( !AddLinksFromSection( section, ref curX, curY ) )
{
typeLabel.Visible = false;
break;
}
curX += 12;
section = section.NextSection;
}
}
private void BuildVerticalViewLinks( LinkSection section )
{
int curY = _cStartLinkY;
int maxWidth = 0;
int lines = 0;
int curX = _contactThumb.Visible ? 4 + _contactThumb.Width : 4;
LinksPaneActionItem[] actionItems = null;
IntArrayList customPropIds = null;
if ( _verticalViewExpanded )
{
actionItems = LinksPaneActionManager.GetManager().CreateActionLinks( _resourceList, _filter );
try
{
foreach( IResource propTypeRes in ResourceTypeHelper.GetCustomProperties() )
{
int propID = propTypeRes.GetIntProp( "ID" );
if ( _resourceList [0].HasProp( propID ) )
{
if ( customPropIds == null )
{
customPropIds = IntArrayListPool.Alloc();
}
customPropIds.Add( propID );
}
}
}
finally
{
if( customPropIds != null )
{
IntArrayListPool.Dispose( customPropIds );
}
}
}
LinkSection startSection = section;
while( section != null )
{
AddLinkTypeLabel( ref curX, ref curY, section.Name, ref maxWidth );
if ( _verticalViewExpanded && section.Separator )
{
curY += 24;
}
else
{
curY += 16;
}
section = section.NextSection;
lines++;
if ( !_verticalViewExpanded && lines == _defltVerticalViewLines )
{
break;
}
}
if ( _verticalViewExpanded )
{
if ( customPropIds != null )
{
foreach( int propId in customPropIds )
{
AddLinkTypeLabel( ref curX, ref curY, Core.ResourceStore.PropTypes [propId].DisplayName, ref maxWidth );
curY += 16;
}
if ( actionItems.Length > 0 )
{
curY += 8;
}
}
if ( actionItems.Length > 0 )
{
AddLinkTypeLabel( ref curX, ref curY, "Actions", ref maxWidth );
}
}
maxWidth += _contactThumb.Visible ? _contactThumb.Width : 0;
curY = _cStartLinkY;
section = startSection;
lines = 0;
while( section != null )
{
curX = maxWidth + 20;
AddLinksFromSection( section, ref curX, curY );
if ( _verticalViewExpanded && section.Separator )
{
curY += 24;
}
else
{
curY += 16;
}
section = section.NextSection;
lines++;
if ( !_verticalViewExpanded && lines == _defltVerticalViewLines )
{
break;
}
}
if ( _verticalViewExpanded )
{
if ( customPropIds != null || actionItems.Length > 0 )
{
curY += 2; // 2 is delta in AddLinkTypeLabel()
}
if ( customPropIds != null )
{
curX = maxWidth + 20;
foreach( int propId in customPropIds )
{
AddCustomPropertyLabel( curX, curY, GetCustomPropText( _resourceList [0], propId ) );
curY += 16;
}
if ( actionItems.Length > 0 )
{
curY += 8;
}
}
if ( actionItems.Length > 0 )
{
curX = maxWidth + 20;
int midX = curX + (Width - curX) / 2;
for( int i=0; i 16 )
{
Height = curY + 6;
}
else
{
// make sure the expand/collapse button is visible when the links bar is empty
Height = 22;
}
// Update height if the amount of links is small (1 or 2).
if( _contactThumb.Visible )
Height = Math.Max( Height, _contactThumb.Height + 8 );
}
private bool AddLinksFromSection( LinkSection section, ref int curX, int curY )
{
ResourceLinkLabel lastLabel = null;
foreach( LinkItem linkItem in section.LinkItems )
{
ResourceLinkLabel lbl = AddResourceLabel( linkItem.Resource, linkItem.PropId,
ref curX, curY );
if ( curX >= Width - 20 && (!_verticalViewMode || lastLabel != null ) )
{
if ( lastLabel != null )
{
lastLabel.PostfixText = "...";
lastLabel.Width = lastLabel.PreferredWidth;
}
_resourceLinkLabelPool.MoveControlToPool( lbl );
return lastLabel != null;
}
if ( lastLabel != null )
{
lastLabel.PostfixText = ",";
lastLabel.Width = lastLabel.PreferredWidth;
}
_toolTip.SetToolTip( lbl.NameLabel, linkItem.ToolTip );
lastLabel = lbl;
}
return true;
}
/**
* Creates a link type label with the specified name.
*/
private Label AddLinkTypeLabel( ref int curX, ref int curY, string text, ref int maxWidth )
{
Label typeLabel = (Label) _linkTypeLabelPool.GetControl();
typeLabel.Text = text + ":";
typeLabel.Bounds = new Rectangle( curX, curY+2, Width-8, 15 );
typeLabel.Visible = true;
typeLabel.AutoSize = true;
if ( !_verticalViewMode )
{
curX += typeLabel.Width + _cSpaceAfterLinkType;
}
if ( typeLabel.Width > maxWidth )
{
maxWidth = typeLabel.Width;
}
return typeLabel;
}
/**
* Adds an icon and label for a single resource.
*/
private ResourceLinkLabel AddResourceLabel( IResource linkRes, int linkType, ref int curX, int curY )
{
ResourceLinkLabel linkLabel = (ResourceLinkLabel) _resourceLinkLabelPool.GetControl();
linkLabel.Resource = linkRes;
linkLabel.LinkType = Math.Abs( linkType );
int width = linkLabel.PreferredWidth;
if ( _verticalViewMode && width > Width - curX - 8 )
{
width = Width - curX - 8;
linkLabel.AutoSize = false;
linkLabel.EndEllipsis = true;
}
else
{
linkLabel.AutoSize = true;
linkLabel.EndEllipsis = false;
}
int dy = (_scaleHeight >= 1.01f) ? 2 : 1;
linkLabel.Bounds = new Rectangle( curX, curY+dy, width, 16 );
linkLabel.LinkOwnerResource = _resource;
linkLabel.PostfixText = "";
curX += width + 4;
return linkLabel;
}
private void AddActionLabel( LinksPaneActionItem actionItem, int curX, int curY )
{
JetLinkLabel lbl = (JetLinkLabel) _actionLabelPool.GetControl();
lbl.ClickableLink = true;
lbl.Enabled = actionItem.Enabled;
lbl.Text = actionItem.Text;
lbl.Tag = actionItem.Action;
lbl.BackColor = Color.FromArgb( 0, SystemColors.Control );
lbl.Location = new Point( curX, curY );
}
private void AddCustomPropertyLabel( int curX, int curY, string text )
{
JetLinkLabel lbl = (JetLinkLabel) _actionLabelPool.GetControl();
lbl.ClickableLink = false;
lbl.Enabled = true;
lbl.Text = text;
lbl.Tag = null;
lbl.BackColor = Color.FromArgb( 0, SystemColors.Control );
lbl.Location = new Point( curX, curY );
}
/**
* Creates a link type label for the pool.
*/
private Control OnCreateLinkTypeLabel()
{
Label typeLabel = new Label();
typeLabel.Font = _linkTypeLabelFont;
typeLabel.ForeColor = ColorScheme.GetColor( _colorScheme, "LinksBar.LinkTypeText",
Color.FromArgb( 96, 96, 96 ) );
typeLabel.BackColor = Color.FromArgb( 0, DefaultBackColor );
typeLabel.AutoSize = true;
return typeLabel;
}
/**
* Creates a resource link label for the pool.
*/
private Control OnCreateResourceLinkLabel()
{
ResourceLinkLabel linkLabel = new ResourceLinkLabel();
linkLabel.BackColor = Color.FromArgb( 0, DefaultBackColor );
linkLabel.ShowIcon = false;
linkLabel.LinkContextMenu += linkLabel_LinkContextMenu;
linkLabel.ResourceChanged += HandleLinkedResourceChanged;
return linkLabel;
}
private void OnDisposeResourceLinkLabel( Control ctl )
{
ResourceLinkLabel linkLabel = ctl as ResourceLinkLabel;
if ( linkLabel != null )
{
linkLabel.ResourceChanged -= HandleLinkedResourceChanged;
linkLabel.LinkContextMenu -= linkLabel_LinkContextMenu;
}
}
private Control OnCreateActionLabel()
{
JetLinkLabel lbl = new JetLinkLabel();
lbl.Click += LinksPaneActionManager.GetManager().OnActionLabelClick;
lbl.Font = _actionFont;
return lbl;
}
/**
* Fills the control with a gradient background.
*/
protected override void OnPaintBackground( PaintEventArgs pevent )
{
base.OnPaintBackground( pevent );
if ( !_verticalViewMode )
{
pevent.Graphics.FillRectangle(
ColorScheme.GetBrush( _colorScheme, "LinksBar.Background", ClientRectangle, SystemBrushes.Control ),
ClientRectangle );
}
else
{
Rectangle rc = ClientRectangle;
pevent.Graphics.FillRectangle(
ColorScheme.GetBrush( _colorScheme, "LinksBar.VerticalBackground", rc, SystemBrushes.Control ),
rc );
}
using( Pen dividerPen = new Pen( Color.FromArgb( 184, 181, 200 ) ) )
{
pevent.Graphics.DrawLine( dividerPen, 0, Height-1, Width-1, Height-1 );
}
}
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 ) || e.ChangeSet.IsDisplayNameAffected )
{
Core.UIManager.QueueUIJob( new MethodInvoker( UpdateLinksPane ) );
}
}
private void FillLinkedThumb( IResource res )
{
if( VerticalViewMode && res != null )
{
IResource from = res.GetLinkProp( Core.ContactManager.Props.LinkFrom );
_contactThumb.Visible = ( from != null && from.Type == "Contact" ) &&
from.HasProp( Core.ContactManager.Props.Picture );
if( _contactThumb.Visible )
{
Stream strm = from.GetBlobProp( Core.ContactManager.Props.Picture );
Image img = Image.FromStream( strm );
_contactThumb.BackgroundImageLayout = ImageLayout.Center;
_contactThumb.BackgroundImage = img;
}
}
else
_contactThumb.Visible = false;
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout( levent );
if ( _verticalViewMode )
{
foreach( Control ctl in Controls )
{
ResourceLinkLabel linkLabel = ctl as ResourceLinkLabel;
if ( linkLabel != null )
{
int prefWidth = linkLabel.PreferredWidth;
if ( prefWidth > Width - linkLabel.Left - 8 )
{
linkLabel.Width = Width - linkLabel.Left - 8;
linkLabel.AutoSize = false;
linkLabel.EndEllipsis = true;
}
else
{
linkLabel.Width = prefWidth;
linkLabel.AutoSize = true;
linkLabel.EndEllipsis = false;
}
}
}
}
}
}
}