/// /// 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.Windows.Forms; using JetBrains.JetListViewLibrary; using JetBrains.Omea.Conversations; using JetBrains.Omea.OpenAPI; using JetBrains.UI.Interop; namespace JetBrains.Omea.GUIControls { /// /// The column which draws the resource icon. /// public class ResourceIconColumn: ResourcePropsColumn { public ResourceIconColumn() : base( new int[] { ResourceProps.Type } ) { Width = 18; FixedSize = true; MouseDown += OnMouseClick; } protected override void DrawItem( Graphics g, Rectangle rc, object item, RowState state, string highlightText ) { IResource res = item as IResource; if ( res != null ) { DrawResourceIcon( g, res, rc, state ); } } internal void DrawResourceIcon( Graphics g, IResource res, Rectangle rc, RowState state ) { int midPointX = rc.Left + Width / 2; int midPointY = (rc.Top + rc.Bottom) / 2; int index = Core.ResourceIconManager.GetIconIndex( res ); DrawSingleIcon( state, g, index, rc, midPointX, midPointY ); int[] overlayIcons = Core.ResourceIconManager.GetOverlayIconIndices( res ); for( int i=0; i= Core.ResourceIconManager.ImageList.Images.Count ) { // possible on shutdown (OM-8972) return; } RectangleF rcClip = g.ClipBounds; rcClip.Intersect( new RectangleF( rcCol.Left, rcCol.Top, rcCol.Width, rcCol.Height ) ); IntPtr hdc = g.GetHdc(); try { IntPtr clipRgn = Win32Declarations.CreateRectRgn( 0, 0, 0, 0 ); if ( Win32Declarations.GetClipRgn( hdc, clipRgn ) != 1 ) { Win32Declarations.DeleteObject( clipRgn ); clipRgn = IntPtr.Zero; } Win32Declarations.IntersectClipRect( hdc, (int) rcClip.Left, (int) rcClip.Top, (int) rcClip.Right, (int) rcClip.Bottom ); int ildState = ( ( state & RowState.ActiveSelected ) != 0 ) ? Win32Declarations.ILD_SELECTED : Win32Declarations.ILD_NORMAL; Win32Declarations.ImageList_Draw( Core.ResourceIconManager.ImageList.Handle, index, hdc, midPointX - 8, midPointY - 8, ildState ); Win32Declarations.SelectClipRgn( hdc, clipRgn ); Win32Declarations.DeleteObject( clipRgn ); } finally { g.ReleaseHdc( hdc ); } } protected override string GetItemText( object item ) { return ""; } public override string GetToolTip( JetListViewNode node, Rectangle rc, ref bool needPlace ) { return null; } private void OnMouseClick(object sender, ItemMouseEventArgs e) { IResource res = (IResource) e.Item; IResourceType type = Core.ResourceStore.ResourceTypes[ res.Type ]; if( type.HasFlag( ResourceTypeFlags.CanBeUnread ) ) { bool unreadState = res.HasProp( Core.Props.IsUnread ); SetResourceUnreadState( res, unreadState ); // If there is a command to propagate the reading status over // the whole thread (conversation) we need to set exactly the // same flag on all resources, not just toggle their flags // forward. if( (Control.ModifierKeys & Keys.Control) > 0 ) { PropagateUnreadState2Thread( res, unreadState ); } e.Handled = false; } } private delegate void AssignStatusDelegate( bool status, IResourceList list ); public void PropagateUnreadState2Thread( IResource res, bool state ) { IResourceList subTree = ConversationBuilder.UnrollConversationFromCurrent( res ); subTree = subTree.Minus( res.ToResourceList() ); Core.ResourceAP.QueueJob( new AssignStatusDelegate( SetListUnreadState ), state, subTree ); } private static void SetListUnreadState( bool state, IResourceList list ) { foreach( IResource res in list ) SetResourceUnreadState( res, state ); } private static void SetResourceUnreadState( IResource res, bool state ) { if( state ) new ResourceProxy( res ).DeleteProp( Core.Props.IsUnread ); else new ResourceProxy( res ).SetProp( Core.Props.IsUnread, true ); } } }