Skip to content

Commit

Permalink
Added a cancellable DropItems event. Fixes oozcitak#170. Fixed oozcit…
Browse files Browse the repository at this point in the history
  • Loading branch information
oozcitak committed Dec 10, 2018
1 parent b46f6db commit f772b34
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 146 deletions.
43 changes: 42 additions & 1 deletion ImageListView/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ namespace Manina.Windows.Forms
[EditorBrowsable(EditorBrowsableState.Never)]
public delegate void DropFilesEventHandler(object sender, DropFileEventArgs e);
/// <summary>
/// Represents the method that will handle the DropItems event.
/// </summary>
/// <param name="sender">The ImageListView object that is the source of the event.</param>
/// <param name="e">A DropItemEventArgs that contains event data.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public delegate void DropItemsEventHandler(object sender, DropItemEventArgs e);
/// <summary>
/// Represents the method that will handle the ColumnClick event.
/// </summary>
/// <param name="sender">The ImageListView object that is the source of the event.</param>
Expand Down Expand Up @@ -166,7 +173,7 @@ public CacheErrorEventArgs(ImageListViewItem item, Exception error, CacheThread
}
}
/// <summary>
/// Represents the event arguments for column related events.
/// Represents the event arguments for external drag&drop events.
/// </summary>
[Serializable, ComVisible(true)]
public class DropFileEventArgs
Expand Down Expand Up @@ -200,6 +207,40 @@ public DropFileEventArgs(int index, string[] fileNames)
}
}
/// <summary>
/// Represents the event arguments for internal drag&drop events.
/// </summary>
[Serializable, ComVisible(true)]
public class DropItemEventArgs
{
/// <summary>
/// Gets or sets whether default event code will be processed.
/// When set to true, the control will automatically insert the new items.
/// Otherwise, the control will not process the dropped items.
/// </summary>
public bool Cancel { get; set; }
/// <summary>
/// Gets the position of the insertion caret.
/// This determines where the new items will be inserted.
/// </summary>
public int Index { get; private set; }
/// <summary>
/// Gets the array of items droppped on the control.
/// </summary>
public ImageListViewItem[] Items { get; private set; }

/// <summary>
/// Initializes a new instance of the DropItemEventArgs class.
/// </summary>
/// <param name="index">The position of the insertion caret.</param>
/// <param name="fileNames">The array of items droppped on the control.</param>
public DropItemEventArgs(int index, ImageListViewItem[] items)
{
Cancel = false;
Index = index;
Items = items;
}
}
/// <summary>
/// Represents the event arguments for column related events.
/// </summary>
[Serializable, ComVisible(true)]
Expand Down
57 changes: 47 additions & 10 deletions ImageListView/ImageListView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1779,16 +1779,6 @@ protected override void OnDragDrop(DragEventArgs e)
navigationManager.DragDrop(e);
base.OnDragDrop(e);
}
/// <summary>
/// Handles the GiveFeedback event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.GiveFeedbackEventArgs"/> that contains the event data.</param>
protected override void OnGiveFeedback(GiveFeedbackEventArgs e)
{
navigationManager.GiveFeedback(e);
base.OnGiveFeedback(e);
}

/// <summary>
/// Handles the Scroll event of the vScrollBar control.
/// </summary>
Expand Down Expand Up @@ -2098,6 +2088,48 @@ protected virtual void OnDropFiles(DropFileEventArgs e)
EnsureVisible(firstItemIndex);
OnSelectionChangedInternal();
}

/// <summary>
/// Raises the DropItems event.
/// </summary>
/// <param name="e">A DropItemEventArgs that contains event data.</param>
protected virtual void OnDropItems(DropItemEventArgs e)
{
if (DropItems != null)
DropItems(this, e);

if (e.Cancel)
return;

int index = e.Index;
mSelectedItems.Clear(false);

foreach (ImageListViewItem item in e.Items)
{
if (item.Index < index) index--;
Items.RemoveInternal(item, false);
}
if (index < 0) index = 0;
if (index > Items.Count) index = Items.Count;

// Add items
bool first = true;
foreach (ImageListViewItem item in e.Items)
{
if (first || MultiSelect)
{
item.mSelected = true;
first = false;
}

bool inserted = Items.InsertInternal(index, item, item.Adaptor);

if (inserted)
index++;
}

OnSelectionChangedInternal();
}
/// <summary>
/// Raises the ColumnWidthChanged event.
/// </summary>
Expand Down Expand Up @@ -2293,6 +2325,11 @@ protected virtual void OnItemCollectionChanged(ItemCollectionChangedEventArgs e)
[Category("Drag Drop"), Browsable(true), Description("Occurs after the user drops files on to the control.")]
public event DropFilesEventHandler DropFiles;
/// <summary>
/// Occurs after the user drops items on to the control.
/// </summary>
[Category("Drag Drop"), Browsable(true), Description("Occurs after the user drops items on to the control.")]
public event DropItemsEventHandler DropItems;
/// <summary>
/// Occurs after the user successfully resized a column header.
/// </summary>
[Category("Action"), Browsable(true), Description("Occurs after the user successfully resized a column header.")]
Expand Down
143 changes: 11 additions & 132 deletions ImageListView/ImageListViewNavigationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ internal class ImageListViewNavigationManager : IDisposable
private bool lastMouseDownOverPaneBorder;

private bool selfDragging;
private Cursor selfDragCursor;
private DragDropEffects selfDragEffect;

private System.Windows.Forms.Timer scrollTimer;
#endregion
Expand Down Expand Up @@ -444,7 +442,6 @@ public void MouseMove(MouseEventArgs e)
selfDragging = true;
mImageListView.DoDragDrop(data, DragDropEffects.All);
selfDragging = false;
DestroySelfDragCursor();

// Since the MouseUp event will be eaten by DoDragDrop we will not receive
// the MouseUp event. We need to manually update mouse button flags after
Expand Down Expand Up @@ -833,25 +830,21 @@ public void DragDrop(DragEventArgs e)

if (selfDragging)
{
// Reorder items
List<ImageListViewItem> draggedItems = new List<ImageListViewItem>();
int i = -1;
if (DropTarget != null) i = DropTarget.Index;
int index = -1;
if (DropTarget != null) index = DropTarget.Index;
if (DropToRight) index++;
if (index > mImageListView.Items.Count)
index = mImageListView.Items.Count;

int i = 0;
ImageListViewItem[] draggedItems = new ImageListViewItem[mImageListView.SelectedItems.Count];
foreach (ImageListViewItem item in mImageListView.SelectedItems)
{
if (item.Index <= i) i--;
draggedItems.Add(item);
mImageListView.Items.RemoveInternal(item, false);
}
if (i < 0) i = 0;
if (i > mImageListView.Items.Count - 1) i = mImageListView.Items.Count - 1;
if (DropToRight) i++;
foreach (ImageListViewItem item in draggedItems)
{
mImageListView.Items.InsertInternal(i, item, item.Adaptor);
draggedItems[i] = item;
i++;
}
mImageListView.OnSelectionChangedInternal();

mImageListView.OnDropItems(new DropItemEventArgs(index, draggedItems));
}
else
{
Expand Down Expand Up @@ -883,22 +876,6 @@ public void DragEnter(DragEventArgs e)
e.Effect = DragDropEffects.None;
}
/// <summary>
/// Handles control's GiveFeedback event.
/// </summary>
public void GiveFeedback(GiveFeedbackEventArgs e)
{
if (selfDragging)
{
e.UseDefaultCursors = false;
CreateSelfDragCursor(e.Effect);
}
else
{
DestroySelfDragCursor();
e.UseDefaultCursors = true;
}
}
/// <summary>
/// Handles control's DragOver event.
/// </summary>
public void DragOver(DragEventArgs e)
Expand Down Expand Up @@ -1103,104 +1080,6 @@ private int ApplyNavKey(int index, Keys key)

return index;
}

/// <summary>
/// Sets the cursor of the control to a shadow image of dragged items.
/// </summary>
/// <param name="effect">The effect to apply to the cursor.</param>
/// <returns>A cursor of shadow items</returns>
private void CreateSelfDragCursor(DragDropEffects effect)
{
if (selfDragCursor == null || (effect != selfDragEffect))
{
selfDragEffect = effect;

if (selfDragCursor != null)
{
selfDragCursor.Dispose();
selfDragCursor = null;
}

Size itemSize = mImageListView.layoutManager.ItemSize;

var resources = new ResourceManager("Manina.Windows.Forms.ImageListViewResources", typeof(ImageListView).Assembly);
var effectCursorName = (effect == DragDropEffects.Copy ? "DragDropCursor_Copy" : effect == DragDropEffects.Move ? "DragDropCursor_Move" : "DragDropCursor_No");

// Color matrix to scale alpha values
float[][] matrixItems = {
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, 0.8f, 0},
new float[] {0, 0, 0, 0, 1}};
ColorMatrix colorMatrix = new ColorMatrix(matrixItems);

using (Stream effectCursorStream = new MemoryStream((byte[])resources.GetObject(effectCursorName)))
using (Cursor effectCursor = new Cursor(effectCursorStream))
using (var bitmap = new Bitmap(128 + effectCursor.Size.Height / 2, 128 + effectCursor.Size.Height / 2, PixelFormat.Format32bppArgb))
using (ImageAttributes imageAtt = new ImageAttributes())
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.Clear(Color.Yellow);
//bitmap.MakeTransparent();

Point effectCursorLocation = new Point(bitmap.Width / 2 - effectCursor.Size.Width / 2, bitmap.Height - effectCursor.Size.Height);

imageAtt.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

int count = 0;
Point itemLocation = new Point(0, 0);
foreach (var item in mImageListView.SelectedItems)
{
using (var itemBitmap = new Bitmap(itemSize.Width, itemSize.Height, PixelFormat.Format32bppArgb))
using (var itemGraphics = Graphics.FromImage(itemBitmap))
{
mImageListView.mRenderer.DrawItem(itemGraphics, item, ItemState.None, new Rectangle(new Point(0, 0), itemSize));
graphics.DrawImage(itemBitmap, new Rectangle(itemLocation, itemSize), 0, 0, itemSize.Width, itemSize.Height, GraphicsUnit.Pixel);//, imageAtt);
}
itemLocation += new Size(8, 8);
count++;
if (count == 5) break;
}

// Draw the drag effect cursor over
effectCursor.Draw(graphics, new Rectangle(effectCursorLocation.X, effectCursorLocation.Y, effectCursor.Size.Width, effectCursor.Size.Height));

// Overwrite the hotspot
effectCursorStream.Seek(10, SeekOrigin.Begin);
byte[] buffer = new byte[4];
effectCursorStream.Read(buffer, 0, 4);
short hotspotX = BitConverter.ToInt16(buffer, 0);
short hotspotY = BitConverter.ToInt16(buffer, 2);
var icon = Icon.FromHandle(bitmap.GetHicon());
using (MemoryStream stream = new MemoryStream())
{
icon.Save(stream);

stream.Seek(10, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((short)effectCursorLocation.X + hotspotX), 0, 2);
stream.Write(BitConverter.GetBytes((short)effectCursorLocation.Y + hotspotY), 0, 2);

stream.Seek(0, SeekOrigin.Begin);
selfDragCursor = new Cursor(stream);
}
}

mImageListView.Cursor = selfDragCursor;
}
}
/// <summary>
/// Destroys the self drag cursor.
/// </summary>
private void DestroySelfDragCursor()
{
if (selfDragCursor != null)
{
mImageListView.Cursor = mImageListView.DefaultCursor;
selfDragCursor.Dispose();
selfDragCursor = null;
}
}
#endregion

#region Scroll Timer
Expand Down
2 changes: 0 additions & 2 deletions ImageListViewDemo/DemoForm.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ImageListViewDemo/DemoForm.resx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADi
CgAAAk1TRnQBSQFMAgEBBAEAAQQBAQEEAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
CgAAAk1TRnQBSQFMAgEBBAEAAQwBAQEMAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
Expand Down

0 comments on commit f772b34

Please sign in to comment.