internal void FinalRefreshAfterUpdate() { UpdateBackgroundGrid(); PlaceWordStatus status = RecolorizeAllWords(); viewModel.UpdateStatus(status); }
private void RecolorizeWord(WordAndCanvas wac, PlaceWordStatus status) { bool isInSelection = m_Sel.WordAndCanvasList?.Contains(wac) ?? false; switch (status) { case PlaceWordStatus.Valid: if (isInSelection) { wac.WordCanvas.SetColor(SelectedValidForeground, SelectedValidBackground); } else { wac.WordCanvas.SetColor(NormalValidForeground, NormalValidBackground); } break; case PlaceWordStatus.TooClose: if (isInSelection) { wac.WordCanvas.SetColor(SelectedTooCloseForeground, SelectedTooCloseBackground); } else { wac.WordCanvas.SetColor(NormalTooCloseForeground, NormalTooCloseBackground); } break; case PlaceWordStatus.Invalid: if (isInSelection) { wac.WordCanvas.SetColor(SelectedInvalidForeground, SelectedInvalidBackground); } else { wac.WordCanvas.SetColor(NormalInvalidForeground, NormalInvalidBackground); } break; default: throw new ArgumentOutOfRangeException(nameof(status), status, null); } }
internal PlaceWordStatus RecolorizeWordAndCanvasList(List <WordAndCanvas> wordAndCanvasList) { PlaceWordStatus result = PlaceWordStatus.Valid; foreach (WordAndCanvas wac in wordAndCanvasList) { var layout = viewModel.GetLayoutExcludingWordPosition(wac.WordPosition); PlaceWordStatus status = EditorViewModel.CanPlaceWordInLayout(layout, wac); RecolorizeWord(wac, status); if (status == PlaceWordStatus.TooClose && result == PlaceWordStatus.Valid) { result = PlaceWordStatus.TooClose; } else if (status == PlaceWordStatus.Invalid && result != PlaceWordStatus.Invalid) { result = PlaceWordStatus.Invalid; } } return(result); }
// Separate from MainGrid_MouseDown to reduce complexity private Action <Point> GetMouseDownMoveAction() { // Need a layout without moved word to validate placement m_FixedLayout = viewModel.GetLayoutExcludingWordPositionList(m_Sel.WordAndCanvasList.Select(wac => wac.WordPosition)); // Reverse-transform mouse Grid coordinates into DrawingCanvas coordinates Matrix m = MainMatrixTransform.Matrix; m.Invert(); // To convert from screen transformed coordinates into ideal grid // coordinates starting at (0,0) with a square side of UnitSize List <Vector> clickOffsetList = new List <Vector>(m_Sel.WordAndCanvasList.Count); clickOffsetList.AddRange(m_Sel.WordAndCanvasList .Select(wac => new Point((double)wac.WordCanvas.GetValue(Canvas.LeftProperty), (double)wac.WordCanvas.GetValue(Canvas.TopProperty))) .Select(canvasTopLeft => canvasTopLeft - m.Transform(previousMousePosition))); // When moving, point is current mouse in ideal grid coordinates return(point => { // Just move selected WordCanvas for (int i = 0; i < m_Sel.WordAndCanvasList.Count; i++) { double preciseTop = point.Y + clickOffsetList[i].Y; double preciseLeft = point.X + clickOffsetList[i].X; WordCanvas wc = m_Sel.WordAndCanvasList[i].WordCanvas; wc.SetValue(Canvas.TopProperty, preciseTop); wc.SetValue(Canvas.LeftProperty, preciseLeft); // Round position to closest square on the grid int top = (int)Math.Floor(preciseTop / UnitSize + 0.5); int left = (int)Math.Floor(preciseLeft / UnitSize + 0.5); PlaceWordStatus status = EditorViewModel.CanPlaceWordAtPositionInLayout(m_FixedLayout, m_Sel.WordAndCanvasList[i].WordPosition, new PositionOrientation(top, left, m_Sel.WordAndCanvasList[i].WordPosition.IsVertical)); RecolorizeWord(m_Sel.WordAndCanvasList[i], status); } }); }
// Helper to reduce cyclomatic complexity private PlaceWordStatus CanPlaceHorizontalWord(WordPosition wordPosition, bool withTooClose) { PlaceWordStatus result = PlaceWordStatus.Valid; int row = wordPosition.StartRow; int column = wordPosition.StartColumn; // Free cell left if (IsOccupiedSquare(row, column - 1)) { if (withTooClose) { result = PlaceWordStatus.TooClose; } else { return(PlaceWordStatus.Invalid); } } // Free cell right if (IsOccupiedSquare(row, column + wordPosition.Word.Length)) { if (withTooClose) { result = PlaceWordStatus.TooClose; } else { return(PlaceWordStatus.Invalid); } } for (int i = 0; i < wordPosition.Word.Length; i++) { char l = GetLetter(row, column + i); if (l == wordPosition.Word[i]) { // It's OK to already have a matching letter only if it only belongs to a crossing word (of opposite direction) foreach (WordPosition loop in GetWordPositionsFromSquare(row, column + i)) { if (loop.IsVertical == wordPosition.IsVertical) { return(PlaceWordStatus.Invalid); } } } else { // We need an empty cell for this letter if (l != '\0') { return(PlaceWordStatus.Invalid); } // We need a free cell above and below, or else we're too close if (IsOccupiedSquare(row - 1, column + i) || IsOccupiedSquare(row + 1, column + i)) { if (withTooClose) { result = PlaceWordStatus.TooClose; } else { return(PlaceWordStatus.Invalid); } } } } return(result); }