using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Tango.Core.Helpers;
using Tango.SharedUI.Shapes;
namespace Tango.SharedUI.Controls
{
///
/// Interaction logic for HiveControl.xaml
///
public partial class HiveControl : UserControl
{
public event EventHandler HexagonSelected;
public event EventHandler HiveGenerated;
public ObservableCollection Hexagons
{
get { return (ObservableCollection)GetValue(HexagonsProperty); }
set { SetValue(HexagonsProperty, value); }
}
public static readonly DependencyProperty HexagonsProperty =
DependencyProperty.Register("Hexagons", typeof(ObservableCollection), typeof(HiveControl), new PropertyMetadata(null));
public ObservableCollection SelectedHexagons
{
get { return (ObservableCollection)GetValue(SelectedHexagonsProperty); }
set { SetValue(SelectedHexagonsProperty, value); }
}
public static readonly DependencyProperty SelectedHexagonsProperty =
DependencyProperty.Register("SelectedHexagons", typeof(ObservableCollection), typeof(HiveControl), new PropertyMetadata(null));
public int MaxSelections
{
get { return (int)GetValue(MaxSelectionsProperty); }
set { SetValue(MaxSelectionsProperty, value); }
}
public static readonly DependencyProperty MaxSelectionsProperty =
DependencyProperty.Register("MaxSelections", typeof(int), typeof(HiveControl), new PropertyMetadata(3));
public bool DisplayGridPosition
{
get { return (bool)GetValue(DisplayGridPositionProperty); }
set { SetValue(DisplayGridPositionProperty, value); }
}
public static readonly DependencyProperty DisplayGridPositionProperty =
DependencyProperty.Register("DisplayGridPosition", typeof(bool), typeof(HiveControl), new PropertyMetadata(false));
public HexagonControl CenterHexagon
{
get { return (HexagonControl)GetValue(CenterHexagonProperty); }
set { SetValue(CenterHexagonProperty, value); }
}
public static readonly DependencyProperty CenterHexagonProperty =
DependencyProperty.Register("CenterHexagon", typeof(HexagonControl), typeof(HiveControl), new PropertyMetadata(null));
public int HiveWidth
{
get { return (int)GetValue(HiveWidthProperty); }
set { SetValue(HiveWidthProperty, value); }
}
public static readonly DependencyProperty HiveWidthProperty =
DependencyProperty.Register("HiveWidth", typeof(int), typeof(HiveControl), new PropertyMetadata(5));
public int HiveHeight
{
get { return (int)GetValue(HiveHeightProperty); }
set { SetValue(HiveHeightProperty, value); }
}
public static readonly DependencyProperty HiveHeightProperty =
DependencyProperty.Register("HiveHeight", typeof(int), typeof(HiveControl), new PropertyMetadata(5));
public HiveControl()
{
Hexagons = new ObservableCollection();
SelectedHexagons = new ObservableCollection();
InitializeComponent();
HiveHeight = 5;
HiveWidth = 5;
this.Loaded += HiveControl_Loaded;
}
private void HiveControl_Loaded(object sender, RoutedEventArgs e)
{
GenerateHive();
HiveGenerated?.Invoke(this,new EventArgs());
}
private void GenerateHive()
{
Hexagons.Clear();
SelectedHexagons.Clear();
canvas.Children.Clear();
double width = ActualWidth;
double height = ActualHeight;
double hexHeight = height / (double)HiveHeight;
int gap = (int)((Math.Round(HiveHeight / 2d, MidpointRounding.AwayFromZero)) / 2d);
for (int column = 0; column < HiveWidth / 2; column++)
{
for (int row = gap; row < HiveHeight - (gap % 2 != 0 ? gap : gap + 1); row++)
{
AddHexagon(hexHeight, row, column);
}
gap--;
}
int centerColumn = (int)Math.Round(HiveHeight / 2d, MidpointRounding.ToEven);
for (int row = 0; row < HiveHeight; row++)
{
AddHexagon(hexHeight, row, centerColumn);
}
gap = 0;
for (int column = centerColumn + 1; column < HiveWidth; column++)
{
for (int row = gap; row < HiveHeight - (gap % 2 != 0 ? gap : gap + 1); row++)
{
AddHexagon(hexHeight, row, column);
}
gap++;
}
Width = Hexagons.Max(x => x.Points.Max(y => y.X));
CenterHexagon = GetHexagon((int)Math.Round(HiveWidth / 2d, MidpointRounding.ToEven), (int)Math.Round(HiveHeight / 2d, MidpointRounding.ToEven));
}
private void AddHexagon(double hexHeight, int row, int col)
{
Point[] points = HexToPoints(hexHeight, row, col);
HexagonControl hexagon = new HexagonControl(points, row, col);
hexagon.HorizontalAlignment = HorizontalAlignment.Center;
hexagon.VerticalAlignment = VerticalAlignment.Center;
hexagon.Stroke = Brushes.Black;
hexagon.StrokeThickness = 1;
hexagon.Fill = new SolidColorBrush(ColorHelper.GetRandomGrayscaleColor());
canvas.Children.Add(hexagon);
Hexagons.Add(hexagon);
hexagon.Bind(HexagonControl.DisplayGridPositionProperty, this, DisplayGridPositionProperty, BindingMode.OneWay);
hexagon.MouseEnter += Hexagon_MouseEnter;
hexagon.MouseUp += Hexagon_MouseUp;
}
private void Hexagon_MouseUp(object sender, MouseButtonEventArgs e)
{
HexagonControl hexagon = sender as HexagonControl;
ToggleHexagonSelection(hexagon);
}
public void SelectHexagon(HexagonControl hexagon)
{
SelectedHexagons.Clear();
SelectedHexagons.Add(hexagon);
Hexagons.ToList().ForEach(x => x.IsSelected = false);
hexagon.IsSelected = true;
HexagonSelected?.Invoke(this, hexagon);
}
private void ToggleHexagonSelection(HexagonControl hexagon)
{
bool selected = !hexagon.IsSelected;
if (MaxSelections > Hexagons.Where(x => x.IsSelected).Count())
{
hexagon.IsSelected = selected;
}
else
{
if (selected)
{
SelectedHexagons.First().IsSelected = false;
SelectedHexagons.Remove(SelectedHexagons.First());
hexagon.IsSelected = true;
}
else
{
hexagon.IsSelected = false;
}
}
if (selected)
{
SelectedHexagons.Add(hexagon);
HexagonSelected?.Invoke(this, hexagon);
}
else
{
SelectedHexagons.Remove(hexagon);
}
}
private void Hexagon_MouseEnter(object sender, MouseEventArgs e)
{
Canvas.SetZIndex(sender as FrameworkElement, canvas.Children.OfType().Where(x => !x.IsSelected).Max(x => Canvas.GetZIndex(x)) + 1);
foreach (var item in canvas.Children.OfType().Where(x => x.IsSelected))
{
Canvas.SetZIndex(item, canvas.Children.OfType().Max(x => Canvas.GetZIndex(x)) + 1);
}
}
private Point[] HexToPoints(double height, float row, float col)
{
// Start with the leftmost corner of the upper left hexagon.
double width = HexWidth(height);
double y = height / 2;
double x = 0;
// Move down the required number of rows.
y += row * height;
// If the column is odd, move down half a hex more.
if (col % 2 == 1) y += height / 2;
// Move over for the column number.
x += col * (width * 0.75f);
// Generate the points.
return new Point[]
{
new Point(x, y),
new Point(x + width * 0.25f, y - height / 2),
new Point(x + width * 0.75f, y - height / 2),
new Point(x + width, y),
new Point(x + width * 0.75f, y + height / 2),
new Point(x + width * 0.25f, y + height / 2),
};
}
private double HexWidth(double height)
{
return (double)(4 * (height / 2 / Math.Sqrt(3)));
}
public HexagonControl GetHexagon(int row, int column)
{
return Hexagons.Where(x => x.Row == row && x.Column == column).FirstOrDefault();
}
}
}