roketto-launch/Windows/Forms/TileForms/TileContainer.cs
Ray 1b59a4cc29 Changed to upgrade nupkg
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
2026-07-04 20:46:19 +01:00

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);
}
}
}