Added prompts for drag-drop on tiles Added drag-drop on tile layout container Changed drag icon for tile movement and file drop Changed to remove legacy TileContainer
311 lines
8.8 KiB
C#
311 lines
8.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using RyzStudio.Windows.Forms;
|
|
|
|
namespace RyzStudio.Windows.TileForms
|
|
{
|
|
public class TileContainer : RyzStudio.Windows.Forms.TTogglePanel
|
|
{
|
|
public TileContainer()
|
|
{
|
|
this.AllowDrop = true;
|
|
this.ForeColor = Color.FromArgb(31, 31, 31);
|
|
this.HeaderPadding = new Padding(10, 0, 0, 0);
|
|
}
|
|
|
|
private const int PADDING_BOTTOM = 10;
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
public Size TileSize { get; set; } = new Size(70, 70);
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
public int TileMargin { get; set; } = 3;
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
public bool AutoSizeHeight { get; set; } = false;
|
|
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
public List<Tuple<System.Windows.Forms.Control, Point>> TileCollection { get; set; } = new List<Tuple<System.Windows.Forms.Control, Point>>();
|
|
|
|
public int ColumnCount
|
|
{
|
|
get
|
|
{
|
|
if (this.TileCollection.Count <= 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return (this.TileCollection?.Max(x => x.Item2.X) ?? 0) + 1;
|
|
}
|
|
}
|
|
|
|
public int RowCount
|
|
{
|
|
get
|
|
{
|
|
if (this.TileCollection.Count <= 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return (this.TileCollection?.Max(x => x.Item2.Y) ?? 0) + 1;
|
|
}
|
|
}
|
|
|
|
public Size HotRectangle
|
|
{
|
|
get => new Size((this.ContentRectangle.Width - SystemInformation.VerticalScrollBarWidth), this.ContentRectangle.Height);
|
|
}
|
|
|
|
public Size GridSize
|
|
{
|
|
get
|
|
{
|
|
var tileWidth = TileSize.Width + TileMargin;
|
|
var tileHeight = TileSize.Height + TileMargin;
|
|
|
|
var columns = (int)Math.Floor(decimal.Divide(this.HotRectangle.Width, tileWidth));
|
|
var rows = (int)Math.Floor(decimal.Divide(this.HotRectangle.Height, tileHeight));
|
|
|
|
return new Size(columns, rows);
|
|
}
|
|
}
|
|
|
|
|
|
protected override void OnControlAdded(ControlEventArgs e)
|
|
{
|
|
base.OnControlAdded(e);
|
|
|
|
if (e.Control == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!(e.Control is Tile))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var newTile = (Tile)e.Control;
|
|
newTile.OnMoved += (object sender, EventArgs e) =>
|
|
{
|
|
var control = (System.Windows.Forms.Control)sender;
|
|
|
|
var coord = this.GetCoord(control);
|
|
coord = this.ValidateCoord(coord);
|
|
|
|
MoveTile(control, coord);
|
|
};
|
|
|
|
var coord = GetCoord(e.Control);
|
|
|
|
MoveTile(e.Control, coord);
|
|
}
|
|
|
|
protected override void OnControlRemoved(ControlEventArgs e)
|
|
{
|
|
base.OnControlRemoved(e);
|
|
|
|
var n = this.TileCollection.FindIndex(x => x.Item1 == e.Control);
|
|
|
|
this.TileCollection.RemoveAt(n);
|
|
}
|
|
|
|
|
|
public void Add(Control control, int x, int y)
|
|
{
|
|
var pos = GetLocation(new Point(x, y));
|
|
|
|
control.Location = pos;
|
|
|
|
UIControl.Invoke(this, (x) => this.Controls.Add(control));
|
|
}
|
|
|
|
public void AddRow()
|
|
{
|
|
var gridSize = this.GridSize;
|
|
|
|
this.AutoSize(gridSize.Width, (gridSize.Height + 1));
|
|
}
|
|
|
|
public void RemoveRow()
|
|
{
|
|
var gridSize = this.GridSize;
|
|
var minGridSize = this.GetMinGridSize();
|
|
|
|
var y = Math.Max((gridSize.Height - 1), minGridSize.Height);
|
|
|
|
this.AutoSize(gridSize.Width, y);
|
|
}
|
|
|
|
public new void AutoSize(int x, int y)
|
|
{
|
|
var tileWidth = TileSize.Width + TileMargin;
|
|
var tileHeight = TileSize.Height + TileMargin;
|
|
|
|
var w = (tileWidth * x) + this.ContentRectangle.Left + SystemInformation.VerticalScrollBarWidth;
|
|
var h = (tileHeight * y) + this.ContentRectangle.Top;
|
|
h += PADDING_BOTTOM;
|
|
|
|
this.ExpandedHeight = h;
|
|
|
|
UIControl.Invoke(this, (x) => this.Size = new Size(w, h));
|
|
|
|
this.IsOpen = this.IsOpen;
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
if (this.TileCollection == null)
|
|
{
|
|
this.TileCollection = new List<Tuple<System.Windows.Forms.Control, Point>>();
|
|
}
|
|
|
|
this.Controls.Clear();
|
|
this.TileCollection.Clear();
|
|
}
|
|
|
|
public Point GetCoord(System.Windows.Forms.Control control)
|
|
{
|
|
var tileWidth = TileSize.Width + TileMargin;
|
|
var tileHeight = TileSize.Height + TileMargin;
|
|
|
|
var x = control.Left - this.ContentRectangle.Left;
|
|
var y = control.Top - this.ContentRectangle.Top;
|
|
|
|
var colX = (int)Math.Floor(decimal.Divide(x, tileWidth));
|
|
var colY = (int)Math.Floor(decimal.Divide(y, tileHeight));
|
|
|
|
colX = Math.Max(colX, 0);
|
|
colY = Math.Max(colY, 0);
|
|
|
|
return new Point(colX, colY);
|
|
}
|
|
|
|
public Size GetMinGridSize()
|
|
{
|
|
var x = Math.Max(this.ColumnCount, 1);
|
|
var y = Math.Max(this.RowCount, 1);
|
|
|
|
return new Size(x, y);
|
|
}
|
|
|
|
public Point GetNextCoord()
|
|
{
|
|
var y = Math.Max(this.RowCount, 1) - 1;
|
|
var x = -1;
|
|
|
|
if (this.TileCollection.Count > 0)
|
|
{
|
|
x = (this.TileCollection?.Where(x => x.Item2.Y == y)?.Max(x => x.Item2.X) ?? 0);
|
|
}
|
|
|
|
return GetNextCoord(new Point(x, y));
|
|
}
|
|
|
|
public Point GetNextCoord(Point coord)
|
|
{
|
|
var gridSize = this.GridSize;
|
|
|
|
var x = (coord.X + 1);
|
|
var y = coord.Y;
|
|
|
|
if (x >= gridSize.Width)
|
|
{
|
|
x = 0;
|
|
y++;
|
|
}
|
|
|
|
return new Point(x, y);
|
|
}
|
|
|
|
public new void Invalidate()
|
|
{
|
|
base.Invalidate();
|
|
|
|
if (this.TileCollection == null)
|
|
{
|
|
this.TileCollection = new List<Tuple<System.Windows.Forms.Control, Point>>();
|
|
}
|
|
|
|
this.TileCollection.Clear();
|
|
|
|
foreach (var item in this.Controls)
|
|
{
|
|
var control = (System.Windows.Forms.Control)item;
|
|
var coord = GetCoord(control);
|
|
|
|
MoveTile(control, coord);
|
|
}
|
|
}
|
|
|
|
public void MoveTile(System.Windows.Forms.Control control, Point newCoord)
|
|
{
|
|
var n = this.TileCollection.FindIndex(x => x.Item1 == control);
|
|
if (n < 0)
|
|
{
|
|
// Add to collection
|
|
this.TileCollection.Add(new Tuple<System.Windows.Forms.Control, Point>(control, newCoord));
|
|
|
|
n = this.TileCollection.FindIndex(x => x.Item1 == control);
|
|
}
|
|
|
|
this.TileCollection[n] = new Tuple<Control, Point>(control, newCoord);
|
|
|
|
var newLocation = GetLocation(newCoord);
|
|
control.Location = new Point(newLocation.X, newLocation.Y);
|
|
|
|
// Auto-resize for height
|
|
if (this.AutoSizeHeight)
|
|
{
|
|
var gridSize = this.GridSize;
|
|
var newHeight = (this.TileCollection?.Max(x => x.Item2.Y) ?? 0) + 1;
|
|
|
|
this.AutoSize(gridSize.Width, Math.Max(gridSize.Height, newHeight));
|
|
}
|
|
|
|
// Handle displaced tile
|
|
var duplicateTile = this.TileCollection.Where(x => ((x.Item1 != control) && (x.Item2 == newCoord))).FirstOrDefault();
|
|
if (duplicateTile != null)
|
|
{
|
|
var nextCoord = GetNextCoord(newCoord);
|
|
|
|
MoveTile(duplicateTile.Item1, nextCoord);
|
|
}
|
|
}
|
|
|
|
public Point ValidateCoord(Point coord)
|
|
{
|
|
var gridSize = this.GridSize;
|
|
|
|
var x = coord.X;
|
|
var y = coord.Y;
|
|
|
|
if (x >= gridSize.Width)
|
|
{
|
|
x = 0;
|
|
y++;
|
|
}
|
|
|
|
return new Point(x, y);
|
|
}
|
|
|
|
|
|
protected Point GetLocation(Point coord)
|
|
{
|
|
var tileWidth = TileSize.Width + TileMargin;
|
|
var tileHeight = TileSize.Height + TileMargin;
|
|
|
|
var posX = (coord.X * tileWidth) + this.ContentRectangle.Left;
|
|
var posY = (coord.Y * tileHeight) + this.ContentRectangle.Top;
|
|
|
|
return new Point(posX, posY);
|
|
}
|
|
|
|
}
|
|
} |