850 lines
23 KiB
C#
850 lines
23 KiB
C#
|
using FizzyLauncher.Models;
|
|||
|
using RyzStudio.Windows.Forms;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Drawing;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Threading;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using System.Windows.Forms;
|
|||
|
using AppResource = FizzyLauncher.AppResource;
|
|||
|
|
|||
|
namespace FizzyLauncher.Windows.Forms
|
|||
|
{
|
|||
|
public partial class TilePanelLayout : TUserControl
|
|||
|
{
|
|||
|
public static int CalcWidth(int tileCount) => (tileCount * tileSize) + ((tileCount - 1) * margin);
|
|||
|
|
|||
|
|
|||
|
public class Item
|
|||
|
{
|
|||
|
public TilePanel Tile { get; set; }
|
|||
|
public Point Coord { get; set; } = new Point(0, 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
protected const int tileSize = 70;
|
|||
|
protected const int margin = 3;
|
|||
|
protected const int labelHeight = 20;
|
|||
|
protected const int collapseIncrement = 6;
|
|||
|
protected const int expandIncrement = 8;
|
|||
|
|
|||
|
protected TileGroupModel groupModel = null;
|
|||
|
protected List<Item> items = new List<Item>();
|
|||
|
|
|||
|
protected int collapseHeight = 0;
|
|||
|
protected int expandedHeight = 0;
|
|||
|
|
|||
|
protected bool isAnimating = false;
|
|||
|
protected bool isChecked = true;
|
|||
|
protected Point lastMousePosition = new Point();
|
|||
|
protected Point gridSize = new Point();
|
|||
|
|
|||
|
|
|||
|
public TilePanelLayout(TileGroupModel model) : base()
|
|||
|
{
|
|||
|
InitializeComponent();
|
|||
|
|
|||
|
this.AllowDrop = true;
|
|||
|
this.BackColor = Color.Transparent;
|
|||
|
|
|||
|
this.LoadModel(model);
|
|||
|
|
|||
|
label1.Location = new Point(0, 4);
|
|||
|
label1.Margin = new Padding(0);
|
|||
|
label1.Padding = new Padding(0);
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnDragDrop(DragEventArgs e)
|
|||
|
{
|
|||
|
string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
|
|||
|
|
|||
|
this.DropFileList(fileList);
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnDragOver(DragEventArgs e)
|
|||
|
{
|
|||
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
|||
|
{
|
|||
|
e.Effect = DragDropEffects.Link;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
e.Effect = DragDropEffects.None;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnLoad(EventArgs e)
|
|||
|
{
|
|||
|
base.OnLoad(e);
|
|||
|
|
|||
|
this.Margin = new Padding(0);
|
|||
|
this.Padding = new Padding(0, 0, 0, 10);
|
|||
|
}
|
|||
|
|
|||
|
protected override async void OnResize(EventArgs e)
|
|||
|
{
|
|||
|
base.OnResize(e);
|
|||
|
|
|||
|
await this.InvalidateContainer();
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnMouseClick(MouseEventArgs e)
|
|||
|
{
|
|||
|
base.OnMouseClick(e);
|
|||
|
|
|||
|
lastMousePosition = e.Location;
|
|||
|
|
|||
|
bool isLabel = ((e.Location.X >= 0) && (e.Location.X <= this.Width) && (e.Location.Y >= 0) && (e.Location.Y <= 20));
|
|||
|
|
|||
|
if (e.Button == MouseButtons.Left)
|
|||
|
{
|
|||
|
// do nothing
|
|||
|
}
|
|||
|
else if (e.Button == MouseButtons.Right)
|
|||
|
{
|
|||
|
if (isLabel)
|
|||
|
{
|
|||
|
contextMenuStrip2.Show(this, e.Location);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
contextMenuStrip1.Show(this, e.Location);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnMouseDoubleClick(MouseEventArgs e) => base.OnMouseClick(e);
|
|||
|
|
|||
|
public Point GridSize
|
|||
|
{
|
|||
|
get => gridSize;
|
|||
|
}
|
|||
|
|
|||
|
public bool EnableAnimation
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
MainForm mainForm = this.MainForm;
|
|||
|
if (mainForm == null)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (mainForm.CurrentSession == null)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
return mainForm.CurrentSession.EnableAnimation;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int CollapseHeight => labelHeight + collapseHeight;
|
|||
|
|
|||
|
public int ExpandedHeight => expandedHeight + this.Padding.Bottom;
|
|||
|
|
|||
|
public void DropFileList(string[] fileList)
|
|||
|
{
|
|||
|
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
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (string.IsNullOrWhiteSpace(model.Title))
|
|||
|
{
|
|||
|
model.Title = Path.GetFileNameWithoutExtension(fileList[0]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this.AddTile(model);
|
|||
|
}
|
|||
|
|
|||
|
public TileGroupModel Model
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
TileGroupModel rs = new TileGroupModel()
|
|||
|
{
|
|||
|
Title = groupModel.Title,
|
|||
|
GridSize = new Size(this.GridSize.X, this.GridSize.Y),
|
|||
|
IsExpanded = isChecked,
|
|||
|
IsExclusive = groupModel.IsExclusive,
|
|||
|
Items = this.Tiles
|
|||
|
};
|
|||
|
|
|||
|
return rs;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public FlowLayoutPanel FlowLayoutPanel
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
Control parentControl = this.Parent;
|
|||
|
while (true)
|
|||
|
{
|
|||
|
if (parentControl == null)
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
if (parentControl.GetType() == typeof(FlowLayoutPanel))
|
|||
|
{
|
|||
|
return parentControl as FlowLayoutPanel;
|
|||
|
}
|
|||
|
|
|||
|
parentControl = parentControl.Parent;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public MainForm MainForm
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
Control parentControl = this.FlowLayoutPanel;
|
|||
|
while (true)
|
|||
|
{
|
|||
|
if (parentControl == null)
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
if (parentControl.GetType() == typeof(MainForm))
|
|||
|
{
|
|||
|
return parentControl as MainForm;
|
|||
|
}
|
|||
|
|
|||
|
parentControl = parentControl.Parent;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public List<TileModel> Tiles
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
List<TileModel> rs = new List<TileModel>();
|
|||
|
foreach (Item item in items)
|
|||
|
{
|
|||
|
TileModel model = item.Tile.ModelInfo;
|
|||
|
model.Position = item.Coord;
|
|||
|
|
|||
|
rs.Add(model);
|
|||
|
}
|
|||
|
|
|||
|
return rs;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int TileSize => (tileSize + margin);
|
|||
|
|
|||
|
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 = tile.Position;
|
|||
|
if ((newCoord == null) || hasTile(tile.Position))
|
|||
|
{
|
|||
|
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 async Task Collapse()
|
|||
|
{
|
|||
|
await Task.Run(() =>
|
|||
|
{
|
|||
|
if (isAnimating) return;
|
|||
|
|
|||
|
isAnimating = true;
|
|||
|
isChecked = false;
|
|||
|
|
|||
|
if (this.EnableAnimation)
|
|||
|
{
|
|||
|
while (this.Height > this.CollapseHeight)
|
|||
|
{
|
|||
|
ThreadControl.SetHeight(this, (this.Height - collapseIncrement));
|
|||
|
|
|||
|
Thread.Sleep(10);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ThreadControl.SetHeight(this, this.CollapseHeight);
|
|||
|
|
|||
|
isAnimating = false;
|
|||
|
|
|||
|
this.Invalidate(this.DisplayRectangle, false);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
public async Task Expand()
|
|||
|
{
|
|||
|
await Task.Run(() =>
|
|||
|
{
|
|||
|
if (isAnimating) return;
|
|||
|
|
|||
|
isAnimating = true;
|
|||
|
isChecked = true;
|
|||
|
|
|||
|
if (this.EnableAnimation)
|
|||
|
{
|
|||
|
while (this.Height < this.ExpandedHeight)
|
|||
|
{
|
|||
|
ThreadControl.SetHeight(this, (this.Height + expandIncrement));
|
|||
|
Thread.Sleep(10);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ThreadControl.SetHeight(this, this.ExpandedHeight);
|
|||
|
|
|||
|
isAnimating = false;
|
|||
|
|
|||
|
this.Invalidate(this.DisplayRectangle, false);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
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 - labelHeight), this.TileSize));
|
|||
|
|
|||
|
if (x < 0) x = 0;
|
|||
|
if (y < 0) y = 0;
|
|||
|
|
|||
|
return new Point((x * this.TileSize), ((y * this.TileSize) + labelHeight));
|
|||
|
}
|
|||
|
|
|||
|
public async Task InvalidateContainer()
|
|||
|
{
|
|||
|
if (isAnimating)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (isChecked)
|
|||
|
{
|
|||
|
await this.Expand();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
await this.Collapse();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void AddGroup()
|
|||
|
{
|
|||
|
if (this.FlowLayoutPanel == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.FlowLayoutPanel.Controls.Add(new TilePanelLayout(new TileGroupModel()
|
|||
|
{
|
|||
|
Title = "New Group",
|
|||
|
GridSize = new Size(8, 1)
|
|||
|
}));
|
|||
|
}
|
|||
|
|
|||
|
public void AddRow() => this.SetGridSize(gridSize.X, (gridSize.Y + 1));
|
|||
|
|
|||
|
public void EditGroup() => EditGroupForm.ShowDialog(this);
|
|||
|
|
|||
|
public void LoadModel(TileGroupModel model)
|
|||
|
{
|
|||
|
groupModel = model;
|
|||
|
|
|||
|
isChecked = groupModel.IsExpanded;
|
|||
|
|
|||
|
label1.Text = " " + groupModel?.Title;
|
|||
|
label1.Image = (isChecked ? AppResource.toggle_right_ea_16 : AppResource.toggle_left_ea_16);
|
|||
|
|
|||
|
this.SetGridSize(groupModel.GridSize.Width, groupModel.GridSize.Height);
|
|||
|
this.LoadTiles(model.Items);
|
|||
|
this.SetGridSize(groupModel.GridSize.Width, groupModel.GridSize.Height);
|
|||
|
|
|||
|
this.Invalidate();
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateModel(TileGroupModel model)
|
|||
|
{
|
|||
|
groupModel = model;
|
|||
|
isChecked = groupModel.IsExpanded;
|
|||
|
|
|||
|
label1.Text = " " + groupModel?.Title;
|
|||
|
|
|||
|
this.Invalidate();
|
|||
|
}
|
|||
|
|
|||
|
public void LoadTiles(List<TileModel> 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_Nearest(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 MoveTop()
|
|||
|
{
|
|||
|
if (this.FlowLayoutPanel == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.FlowLayoutPanel.Controls.SetChildIndex(this, 0);
|
|||
|
}
|
|||
|
|
|||
|
public void MoveUp()
|
|||
|
{
|
|||
|
if (this.FlowLayoutPanel == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
int pos = this.FlowLayoutPanel.Controls.GetChildIndex(this);
|
|||
|
if (pos <= 0)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.FlowLayoutPanel.Controls.SetChildIndex(this, (pos - 1));
|
|||
|
}
|
|||
|
|
|||
|
public void MoveDown()
|
|||
|
{
|
|||
|
if (this.FlowLayoutPanel == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
int pos = this.FlowLayoutPanel.Controls.GetChildIndex(this);
|
|||
|
if (pos >= (this.FlowLayoutPanel.Controls.Count - 1))
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.FlowLayoutPanel.Controls.SetChildIndex(this, (pos + 1));
|
|||
|
}
|
|||
|
|
|||
|
public void MoveBottom()
|
|||
|
{
|
|||
|
if (this.FlowLayoutPanel == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.FlowLayoutPanel.Controls.SetChildIndex(this, (this.FlowLayoutPanel.Controls.Count - 1));
|
|||
|
}
|
|||
|
|
|||
|
public void Remove()
|
|||
|
{
|
|||
|
if (this.FlowLayoutPanel == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.FlowLayoutPanel.Controls.Remove(this);
|
|||
|
}
|
|||
|
|
|||
|
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)
|
|||
|
{
|
|||
|
gridSize = new Point(width, height);
|
|||
|
|
|||
|
groupModel.GridSize = new Size(groupModel.GridSize.Width, height);
|
|||
|
|
|||
|
expandedHeight = (this.TileSize * height) + labelHeight;
|
|||
|
|
|||
|
int w = CalcWidth(gridSize.X);
|
|||
|
|
|||
|
this.Size = new Size(w, (isChecked ? this.ExpandedHeight : this.CollapseHeight));
|
|||
|
}
|
|||
|
|
|||
|
protected Point convertCoordToLocation(Point position) => new Point((position.X * this.TileSize), ((position.Y * this.TileSize) + labelHeight));
|
|||
|
|
|||
|
protected Point convertLocationToCoord(int posX, int posY)
|
|||
|
{
|
|||
|
int x = (int)Math.Ceiling(decimal.Divide(posX, this.TileSize));
|
|||
|
int y = (int)Math.Ceiling(decimal.Divide((posY - labelHeight), this.TileSize));
|
|||
|
|
|||
|
x--;
|
|||
|
y--;
|
|||
|
|
|||
|
if (x < 0) x = 0;
|
|||
|
if (y < 0) y = 0;
|
|||
|
|
|||
|
return new Point(x, y);
|
|||
|
}
|
|||
|
|
|||
|
protected Point convertLocationToCoord_Nearest(int posX, int posY)
|
|||
|
{
|
|||
|
int x = (int)Math.Round(decimal.Divide(posX, this.TileSize));
|
|||
|
int y = (int)Math.Round(decimal.Divide((posY - labelHeight), this.TileSize));
|
|||
|
|
|||
|
if (x < 0) x = 0;
|
|||
|
if (y < 0) y = 0;
|
|||
|
|
|||
|
return new Point(x, y);
|
|||
|
}
|
|||
|
|
|||
|
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? 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 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;
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void addTileMenuItem_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Point coord = convertLocationToCoord(lastMousePosition.X, lastMousePosition.Y);
|
|||
|
|
|||
|
EditTileForm.ShowAddDialog(this, coord);
|
|||
|
}
|
|||
|
|
|||
|
private void addListTileMenuItem_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Point coord = convertLocationToCoord(lastMousePosition.X, lastMousePosition.Y);
|
|||
|
|
|||
|
EditTileFolderForm.ShowAddDialog(this, coord);
|
|||
|
}
|
|||
|
|
|||
|
private void addGroupMenuItem_Click(object sender, EventArgs e) => this.AddGroup();
|
|||
|
|
|||
|
private void addRowMenuItem_Click(object sender, EventArgs e) => this.AddRow();
|
|||
|
|
|||
|
private void editGroupMenuItem_Click(object sender, EventArgs e) => this.EditGroup();
|
|||
|
|
|||
|
private void moveTopMenuItem_Click(object sender, EventArgs e) => this.MoveTop();
|
|||
|
|
|||
|
private void moveUpMenuItem_Click(object sender, EventArgs e) => this.MoveUp();
|
|||
|
|
|||
|
private void moveDownMenuItem_Click(object sender, EventArgs e) => this.MoveDown();
|
|||
|
|
|||
|
private void moveBottomMenuItem_Click(object sender, EventArgs e) => this.MoveBottom();
|
|||
|
|
|||
|
private void removeGroupMenuItem3_Click(object sender, EventArgs e) => this.Remove();
|
|||
|
|
|||
|
private void removeRowToolStripMenuItem_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
bool rs = items.Exists(x => x.Coord.Y.Equals(gridSize.Y - 1));
|
|||
|
if (!rs)
|
|||
|
{
|
|||
|
this.SetGridSize(gridSize.X, (gridSize.Y - 1));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private async void label1_MouseClick(object sender, MouseEventArgs e)
|
|||
|
{
|
|||
|
if (isAnimating) return;
|
|||
|
|
|||
|
if (e.Button == MouseButtons.Left)
|
|||
|
{
|
|||
|
isChecked = !isChecked;
|
|||
|
|
|||
|
label1.Image = (isChecked ? AppResource.toggle_right_ea_16 : AppResource.toggle_left_ea_16);
|
|||
|
|
|||
|
this.Invalidate();
|
|||
|
|
|||
|
await this.InvalidateContainer();
|
|||
|
|
|||
|
// exclusivity
|
|||
|
if (isChecked)
|
|||
|
{
|
|||
|
if (this.Model.IsExclusive)
|
|||
|
{
|
|||
|
if (this.FlowLayoutPanel != null)
|
|||
|
{
|
|||
|
foreach (TilePanelLayout item in this.FlowLayoutPanel.Controls.OfType<TilePanelLayout>())
|
|||
|
{
|
|||
|
if (item.Equals(this))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
await item.Collapse();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
label1.Image = (isChecked ? AppResource.toggle_right_ea_16 : AppResource.toggle_left_ea_16);
|
|||
|
}
|
|||
|
else if (e.Button == MouseButtons.Right)
|
|||
|
{
|
|||
|
contextMenuStrip2.Show(this, e.Location);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|