using AppLauncher.Models; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Windows.Forms; namespace AppLauncher.Windows.Forms { public class TileLayoutPanel : AUserControl { public class Item { public TilePanel Tile { get; set; } public Point Coord { get; set; } = new Point(0, 0); } protected readonly int tileSize = 70; protected readonly int margin = 3; protected int collapseHeight = 0; protected int expandedHeight = 0; protected List items = new List(); public TileLayoutPanel() : base() { InitializeComponent(); this.AllowDrop = true; this.BackColor = System.Drawing.Color.Transparent; } private void InitializeComponent() { this.SuspendLayout(); // // TileLayoutPanel // this.Name = "TileLayoutPanel"; this.DragDrop += new System.Windows.Forms.DragEventHandler(this.panel_DragDrop); this.DragOver += new System.Windows.Forms.DragEventHandler(this.panel_DragOver); this.ResumeLayout(false); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); OnResize(e); } public Point GridSize { get { int w = (int)Math.Floor(decimal.Divide(this.Width, this.TileSize)); int h = (int)Math.Floor(decimal.Divide(this.Height, this.TileSize)); return new Point(w, h); } } public TileContainer TileContainer { get { if (this.Parent == null) { return null; } if (this.Parent.GetType() != typeof(TileContainer)) { return null; } return (TileContainer)this.Parent; } } public int TileSize => (tileSize + margin); public int CollapseHeight => collapseHeight; public int ExpandedHeight => expandedHeight; public List Tiles { get { List rs = new List(); foreach (Item item in items) { TileModel model = item.Tile.ModelInfo; model.Position = item.Coord; rs.Add(model); } return rs; } } public void AddTile(TileModel tile) { Point gridSize = this.GridSize; if (items.Count >= (gridSize.X * gridSize.Y)) { this.SetGridSize(gridSize.X, (gridSize.Y + 1)); } Point? newCoord = findLastFreeCoord(); if (newCoord == null) { return; } tile.Position = newCoord.Value; TilePanel panel = new TilePanel(); panel.LoadInfo(tile); panel.Location = convertCoordToLocation(tile.Position); items.Add(new Item() { Tile = panel, Coord = tile.Position }); this.Controls.Add(panel); } public void Clear() { this.Controls.Clear(); } public Point GetTilePosition(int posX, int posY) { int x = (int)Math.Round(decimal.Divide(posX, this.TileSize)); int y = (int)Math.Round(decimal.Divide(posY, this.TileSize)); if (x < 0) x = 0; if (y < 0) y = 0; return new Point((x * this.TileSize), (y * this.TileSize)); } public void LoadTiles(List tiles) { if (tiles == null) { return; } if (tiles.Count() <= 0) { return; } foreach (TileModel item in tiles) { // resolve final grid position Point? confirmedPosition = resolveCoord(item.Position); if (confirmedPosition == null) { continue; } // place control TilePanel panel = new TilePanel(); panel.LoadInfo(item); panel.Location = convertCoordToLocation(confirmedPosition.Value); items.Add(new Item() { Tile = panel, Coord = confirmedPosition.Value }); this.Controls.Add(panel); } } public void MoveTile(TilePanel panel, int posX, int posY) { Item item = items.Where(x => x.Tile.Equals(panel)).FirstOrDefault(); if (item == null) { return; } Point newPosition = convertLocationToCoord(posX, posY); if (!isTileInBounds(newPosition)) { return; } if (hasTile(newPosition)) { Item swapItem = items.Where(x => x.Coord.Equals(newPosition)).FirstOrDefault(); if (swapItem != null) { swapItem.Coord = item.Coord; swapItem.Tile.Location = convertCoordToLocation(item.Coord); } item.Coord = newPosition; panel.Location = convertCoordToLocation(newPosition); } else { item.Coord = newPosition; panel.Location = convertCoordToLocation(newPosition); } } public void Remove(TilePanel panel) { Item m = items.Where(x => x.Tile.Equals(panel)).FirstOrDefault(); if (m != null) { items.Remove(m); } this.Controls.Remove(panel); } public void SetGridSize(int width, int height) { expandedHeight = (this.TileSize * height); this.Size = new Size((this.TileSize * width), expandedHeight); } protected Point convertCoordToLocation(Point position) => new Point((position.X * this.TileSize), (position.Y * this.TileSize)); protected Point convertLocationToCoord(int posX, int posY) { int x = (int)Math.Round(decimal.Divide(posX, this.TileSize)); int y = (int)Math.Round(decimal.Divide(posY, this.TileSize)); if (x < 0) x = 0; if (y < 0) y = 0; return new Point(x, y); } protected Point? findLastFreeCoord() { Point gridSize = this.GridSize; // none available if (items.Count >= (gridSize.X * gridSize.Y)) { return null; } if (items.Count <= 0) { return findFirstFreeCoord(); } // only one available if (items.Count >= ((gridSize.X * gridSize.Y) - 1)) { return findFirstFreeCoord(); } Point? rv = null; for (int y = (gridSize.Y - 1); y >= 0; y--) { for (int x = (gridSize.X - 1); x >= 0; x--) { if (hasTile(new Point(x, y))) { if (rv.HasValue) { return rv; } } else { rv = new Point(x, y); } } } return null; } protected Point? findFirstFreeCoord() { Point gridSize = this.GridSize; for (int y = 0; y < gridSize.Y; y++) { for (int x = 0; x < gridSize.X; x++) { if (hasTile(new Point(x, y))) { continue; } return new Point(x, y); } } return null; } protected Point? resolveCoord(Point coord) { if (!isTileInBounds(coord)) { return null; } if (!hasTile(coord)) { return coord; } return resolveNextCoord(coord); } protected Point? resolveNextCoord(Point coord) { Point gridSize = this.GridSize; Point newCoord = coord; while (true) { newCoord.X++; if (newCoord.X >= gridSize.X) { newCoord.Y++; newCoord.X = 0; } if (!isTileInBounds(newCoord)) { return null; } if (hasTile(newCoord)) { continue; } return newCoord; } } protected bool hasTile(Point position) { if (items == null) { return false; } if (items.Count <= 0) { return false; } return (items.Count(x => x.Coord.Equals(position)) > 0); } protected bool isTileInBounds(Point position) { Point gridSize = this.GridSize; if (position.X >= gridSize.X) { return false; } if (position.Y >= gridSize.Y) { return false; } return true; } private void panel_DragOver(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Link; } else { e.Effect = DragDropEffects.None; } } private void panel_DragDrop(object sender, DragEventArgs e) { string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[]; if (fileList == null) { return; } if (fileList.Length <= 0) { return; } if (string.IsNullOrWhiteSpace(fileList[0])) { return; } TileModel model = new TileModel() { ProcessFilename = fileList[0], Title = Path.GetFileName(fileList[0]) }; // exe if (Path.GetExtension(fileList[0]).Equals(".exe", StringComparison.CurrentCultureIgnoreCase)) { if (File.Exists(fileList[0])) { try { FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(fileList[0]); if (fvi != null) { model.Title = fvi.ProductName; } } catch { // do nothing } } } this.AddTile(model); } } }