namespace Tickypip { using Gnome; using Gdk; using System; public abstract class Cell : Gnome.CanvasGroup { public static uint WIDTH = 30; public static uint HEIGHT = 30; private bool[] mActiveSources; private int mSourceCount; private int mActiveCount; private uint mColumn, mRow; private Board mBoard; private Direction mDirection; public delegate void ActiveChangedEventHandler(Cell cell); public delegate void ClickedEventHandler(Cell cell); public delegate void DirectionChangedEventHandler(Cell cell); public event ActiveChangedEventHandler ActiveChanged; public event ClickedEventHandler Clicked; public new event DirectionChangedEventHandler DirectionChanged; public Cell(Board board) : base(board.Root()) { mDirection = Direction.North; mBoard = board; mActiveSources = new bool[(int)Direction.Count]; for (Direction dir = 0; dir < Direction.Count; dir++) SetActiveSource(dir, false); DrawBackground(); CanvasEvent += new CanvasEventHandler(Canvas_Event); } public abstract bool HasConnector(Direction dir); public uint Column { get { return mColumn; } set { mColumn = value; } } public uint Row { get { return mRow; } set { mRow = value; } } public Board Board { get { return mBoard; } } public void RotateRight() { Direction = DirectionUtil.RotateRight(Direction); } public void RotateLeft() { Direction = DirectionUtil.RotateLeft(Direction); } public virtual Direction Direction { get { return mDirection; } set { bool oldActive = Active; mDirection = value; mSourceCount = 0; for (Direction dir = 0; dir < Direction.Count; dir++) { Cell cell = Board.GetNearCell(this, dir); if (cell != null && ConnectedWith(cell) && cell.Active && !cell.IsSource(DirectionUtil.Opposite(dir))) { SetActiveSource(dir, true); mSourceCount++; } else { SetActiveSource(dir, false); } } for (Direction dir = 0; dir < Direction.Count; dir++) { Cell cell = Board.GetNearCell(this, dir); if (cell != null && !IsSource(dir)) { cell.SetSource(DirectionUtil.Opposite(dir), ConnectedWith(cell) && Active); } } if (DirectionChanged != null) DirectionChanged(this); if (Active != oldActive && ActiveChanged != null) ActiveChanged(this); } } public bool ConnectedWith(Cell cell) { if (cell == null) return false; for (Direction dir = 0; dir < Direction.Count; dir++) { if (cell == Board.GetNearCell(this, dir)) { return (HasConnector(dir) && cell.HasConnector(DirectionUtil.Opposite(dir))); } } return false; } public virtual bool Active { get { return Board != null && mSourceCount > 0; } } public void SetSource(Direction dir, bool source) { if (source == GetActiveSource(dir)) return; bool oldActive = Active; if (source) mSourceCount++; else mSourceCount--; SetActiveSource(dir, source); for (Direction tempDir = 0; tempDir < Direction.Count; tempDir++) { Cell cell = Board.GetNearCell(this, tempDir); if (cell != null && cell.ConnectedWith(this) && (Active ? !IsSource(tempDir) : cell.IsSource(DirectionUtil.Opposite(tempDir)))) { cell.SetSource(DirectionUtil.Opposite(tempDir), Active); } } if (Active != oldActive && ActiveChanged != null) ActiveChanged(this); } public bool IsSource(Direction dir) { return Board != null && GetActiveSource(dir); } private void SetActiveSource(int index, bool active) { mActiveSources[index] = active; } private void SetActiveSource(Direction dir, bool active) { SetActiveSource((int)dir, active); } private bool GetActiveSource(int index) { return mActiveSources[index]; } private bool GetActiveSource(Direction dir) { return GetActiveSource((int)dir); } protected virtual void DrawBackground() { CanvasRect rect = new CanvasRect(this); rect.FillColorGdk = new Gdk.Color(230, 230, 230); rect.X1 = 0; rect.Y1 = 0; rect.X2 = WIDTH - 1; rect.Y2 = HEIGHT - 1; } private void Canvas_Event(object o, CanvasEventArgs args) { if (args.Event.Type == EventType.ButtonPress && Clicked != null) Clicked(this); } } }