private int AddZone() { GridZone zone; if (Model != null) { IList <int> freeZones = Model.FreeZones; // first check free list if (freeZones.Count > 0) { int freeIndex = freeZones[0]; freeZones.RemoveAt(0); zone = (GridZone)Preview.Children[freeIndex]; zone.Visibility = Visibility.Visible; return(freeIndex); } } zone = new GridZone(); zone.Split += OnSplit; zone.MergeDrag += OnMergeDrag; zone.MergeComplete += OnMergeComplete; zone.FullSplit += OnFullSplit; Preview.Children.Add(zone); return(Preview.Children.Count - 1); }
private void HandleGridZoneKeyUp(GridZone gridZone, KeyEventArgs e) { if (e.Key != Key.S) { return; } Orientation orient = Orientation.Horizontal; Debug.Assert(Preview.Children.Count > Preview.Children.IndexOf(gridZone), "Zone index out of range"); int offset; if (((App)Application.Current).MainWindowSettings.IsShiftKeyPressed) { orient = Orientation.Vertical; offset = gridZone.SnapAtHalfX(); } else { offset = gridZone.SnapAtHalfY(); } gridZone.DoSplit(orient, offset); }
private void SetZonePanelSize(GridZone panel, GridData.Zone zone) { Size actualSize = WorkAreaSize(); double spacing = Model.ShowSpacing ? Model.Spacing : 0; double topSpacing = zone.Top == 0 ? spacing : spacing / 2; double bottomSpacing = zone.Bottom == GridData.Multiplier ? spacing : spacing / 2; double leftSpacing = zone.Left == 0 ? spacing : spacing / 2; double rightSpacing = zone.Right == GridData.Multiplier ? spacing : spacing / 2; Canvas.SetTop(panel, (actualSize.Height * zone.Top / GridData.Multiplier) + topSpacing); Canvas.SetLeft(panel, (actualSize.Width * zone.Left / GridData.Multiplier) + leftSpacing); panel.MinWidth = Math.Max(1, (actualSize.Width * (zone.Right - zone.Left) / GridData.Multiplier) - leftSpacing - rightSpacing); panel.MinHeight = Math.Max(1, (actualSize.Height * (zone.Bottom - zone.Top) / GridData.Multiplier) - topSpacing - bottomSpacing); }
private void DeleteZone(int index) { IList <int> freeZones = Model.FreeZones; if (freeZones.Contains(index)) { return; } freeZones.Add(index); GridZone zone = (GridZone)Preview.Children[index]; zone.Visibility = Visibility.Hidden; zone.MinHeight = 0; zone.MinWidth = 0; }
public void ArrangeZones(UIElementCollection zones, int spacing) { if (zones.Count == 0) { return; } int rows = _model.Rows; int cols = _model.Columns; int[,] cells = _model.CellChildMap; if (cells.Length < rows * cols) { // Merge was not finished yet, rows and cols values are invalid return; } double left, top; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { int i = cells[row, col]; if (((row == 0) || (cells[row - 1, col] != i)) && ((col == 0) || (cells[row, col - 1] != i))) { // this is not a continuation of a span GridZone zone = (GridZone)zones[i]; left = _colInfo[col].Start; top = _rowInfo[row].Start; Canvas.SetLeft(zone, left); Canvas.SetTop(zone, top); zone.LabelID.Content = i + 1; int maxRow = row; while (((maxRow + 1) < rows) && (cells[maxRow + 1, col] == i)) { maxRow++; } zone.HorizontalSnapPoints = null; if (maxRow > row) { zone.HorizontalSnapPoints = new double[maxRow - row]; int pointsIndex = 0; for (int walk = row; walk < maxRow; walk++) { zone.HorizontalSnapPoints[pointsIndex++] = _rowInfo[walk].End + (spacing / 2) - top; } } int maxCol = col; while (((maxCol + 1) < cols) && (cells[row, maxCol + 1] == i)) { maxCol++; } zone.VerticalSnapPoints = null; if (maxCol > col) { zone.VerticalSnapPoints = new double[maxCol - col]; int pointsIndex = 0; for (int walk = col; walk < maxCol; walk++) { zone.VerticalSnapPoints[pointsIndex++] = _colInfo[walk].End + (spacing / 2) - left; } } zone.MinWidth = _colInfo[maxCol].End - left; zone.MinHeight = _rowInfo[maxRow].End - top; } } } }
private void OnSplit(object o, SplitEventArgs e) { MergeCancelClick(null, null); UIElementCollection previewChildren = Preview.Children; GridZone splitee = (GridZone)o; int spliteeIndex = previewChildren.IndexOf(splitee); GridLayoutModel model = Model; int rows = model.Rows; int cols = model.Columns; Tuple <int, int> rowCol = _data.RowColByIndex(spliteeIndex); int foundRow = rowCol.Item1; int foundCol = rowCol.Item2; int newChildIndex = AddZone(); double offset = e.Offset; double space = e.Space; if (e.Orientation == Orientation.Vertical) { if (splitee.VerticalSnapPoints != null) { offset += Canvas.GetLeft(splitee); int count = splitee.VerticalSnapPoints.Length; bool foundExistingSplit = false; int splitCol = foundCol; for (int i = 0; i <= count; i++) { if (foundExistingSplit) { int walkRow = foundRow; while ((walkRow < rows) && (_data.GetIndex(walkRow, foundCol + i) == spliteeIndex)) { _data.SetIndex(walkRow++, foundCol + i, newChildIndex); } } if (_data.ColumnBottom(foundCol + i) == offset) { foundExistingSplit = true; splitCol = foundCol + i; // use existing division } } if (foundExistingSplit) { _data.ReplaceIndicesToMaintainOrder(Preview.Children.Count); _dragHandles.UpdateForExistingVerticalSplit(model, foundRow, splitCol); OnGridDimensionsChanged(); return; } while (_data.ColumnBottom(foundCol) < offset) { foundCol++; } offset -= _data.ColumnTop(foundCol); } _dragHandles.UpdateAfterVerticalSplit(foundCol); _data.SplitColumn(foundCol, spliteeIndex, newChildIndex, space, offset, ActualWidth); _dragHandles.AddDragHandle(Orientation.Vertical, foundRow, foundCol, model); } else { // Horizontal if (splitee.HorizontalSnapPoints != null) { offset += Canvas.GetTop(splitee); int count = splitee.HorizontalSnapPoints.Length; bool foundExistingSplit = false; int splitRow = foundRow; for (int i = 0; i <= count; i++) { if (foundExistingSplit) { int walkCol = foundCol; while ((walkCol < cols) && (_data.GetIndex(foundRow + i, walkCol) == spliteeIndex)) { _data.SetIndex(foundRow + i, walkCol++, newChildIndex); } } if (_data.RowEnd(foundRow + i) == offset) { foundExistingSplit = true; splitRow = foundRow + i; // use existing division } } if (foundExistingSplit) { _data.ReplaceIndicesToMaintainOrder(Preview.Children.Count); _dragHandles.UpdateForExistingHorizontalSplit(model, splitRow, foundCol); OnGridDimensionsChanged(); return; } while (_data.RowEnd(foundRow) < offset) { foundRow++; } offset -= _data.RowStart(foundRow); } _dragHandles.UpdateAfterHorizontalSplit(foundRow); _data.SplitRow(foundRow, spliteeIndex, newChildIndex, space, offset, ActualHeight); _dragHandles.AddDragHandle(Orientation.Horizontal, foundRow, foundCol, model); } Size actualSize = new Size(ActualWidth, ActualHeight); ArrangeGridRects(actualSize); }
private void SetupUI() { Size actualSize = WorkAreaSize(); if (actualSize.Width < 1 || _data == null || _data.Zones == null || Model == null) { return; } int spacing = Model.ShowSpacing ? Model.Spacing : 0; _data.MinZoneWidth = Convert.ToInt32(GridData.Multiplier / actualSize.Width * (MinZoneSize + (2 * spacing))); _data.MinZoneHeight = Convert.ToInt32(GridData.Multiplier / actualSize.Height * (MinZoneSize + (2 * spacing))); Preview.Children.Clear(); AdornerLayer.Children.Clear(); Preview.Width = actualSize.Width; Preview.Height = actualSize.Height; MagneticSnap snapX = new MagneticSnap(GridData.PrefixSum(Model.ColumnPercents).GetRange(1, Model.ColumnPercents.Count - 1), actualSize.Width); MagneticSnap snapY = new MagneticSnap(GridData.PrefixSum(Model.RowPercents).GetRange(1, Model.RowPercents.Count - 1), actualSize.Height); for (int zoneIndex = 0; zoneIndex < _data.Zones.Count; zoneIndex++) { // this is needed for the lambda int zoneIndexCopy = zoneIndex; var zone = _data.Zones[zoneIndex]; var zonePanel = new GridZone(spacing, snapX, snapY, (orientation, offset) => _data.CanSplit(zoneIndexCopy, offset, orientation), zone); zonePanel.UpdateShiftState(((App)Application.Current).MainWindowSettings.IsShiftKeyPressed); Preview.Children.Add(zonePanel); zonePanel.Split += OnSplit; zonePanel.MergeDrag += OnMergeDrag; zonePanel.MergeComplete += OnMergeComplete; SetZonePanelSize(zonePanel, zone); zonePanel.LabelID.Content = zoneIndex + 1; } foreach (var resizer in _data.Resizers) { var resizerThumb = new GridResizer(); resizerThumb.DragStarted += Resizer_DragStarted; resizerThumb.DragDelta += Resizer_DragDelta; resizerThumb.DragCompleted += Resizer_DragCompleted; resizerThumb.Orientation = resizer.Orientation; AdornerLayer.Children.Add(resizerThumb); if (resizer.Orientation == Orientation.Horizontal) { resizerThumb.LeftReferenceZone = resizer.PositiveSideIndices[0]; resizerThumb.RightReferenceZone = resizer.PositiveSideIndices.Last(); resizerThumb.TopReferenceZone = resizer.PositiveSideIndices[0]; resizerThumb.BottomReferenceZone = resizer.NegativeSideIndices[0]; } else { resizerThumb.LeftReferenceZone = resizer.PositiveSideIndices[0]; resizerThumb.RightReferenceZone = resizer.NegativeSideIndices[0]; resizerThumb.TopReferenceZone = resizer.PositiveSideIndices[0]; resizerThumb.BottomReferenceZone = resizer.PositiveSideIndices.Last(); } PlaceResizer(resizerThumb); } }
private void ArrangeGridRects(Size arrangeSize) { GridLayoutModel model = Model; if (model == null) { return; } Settings settings = ((App)Application.Current).ZoneSettings; int spacing, gutter; spacing = gutter = settings.ShowSpacing ? settings.Spacing : 0; int cols = model.Columns; int rows = model.Rows; double totalWidth = arrangeSize.Width - (gutter * 2) - (spacing * (cols - 1)); double totalHeight = arrangeSize.Height - (gutter * 2) - (spacing * (rows - 1)); double top = gutter; for (int row = 0; row < rows; row++) { double cellHeight = _rowInfo[row].Recalculate(top, totalHeight); top += cellHeight + spacing; } double left = gutter; for (int col = 0; col < cols; col++) { double cellWidth = _colInfo[col].Recalculate(left, totalWidth); left += cellWidth + spacing; } for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { int i = model.CellChildMap[row, col]; if (((row == 0) || (model.CellChildMap[row - 1, col] != i)) && ((col == 0) || (model.CellChildMap[row, col - 1] != i))) { // this is not a continuation of a span GridZone zone = (GridZone)Preview.Children[i]; left = _colInfo[col].Start; top = _rowInfo[row].Start; Canvas.SetLeft(zone, left); Canvas.SetTop(zone, top); int maxRow = row; while (((maxRow + 1) < rows) && (model.CellChildMap[maxRow + 1, col] == i)) { maxRow++; } zone.HorizontalSnapPoints = null; if (maxRow > row) { zone.HorizontalSnapPoints = new double[maxRow - row]; int pointsIndex = 0; for (int walk = row; walk < maxRow; walk++) { zone.HorizontalSnapPoints[pointsIndex++] = _rowInfo[walk].End + (spacing / 2) - top; } } int maxCol = col; while (((maxCol + 1) < cols) && (model.CellChildMap[row, maxCol + 1] == i)) { maxCol++; } zone.VerticalSnapPoints = null; if (maxCol > col) { zone.VerticalSnapPoints = new double[maxCol - col]; int pointsIndex = 0; for (int walk = col; walk < maxCol; walk++) { zone.VerticalSnapPoints[pointsIndex++] = _colInfo[walk].End + (spacing / 2) - left; } } zone.MinWidth = _colInfo[maxCol].End - left; zone.MinHeight = _rowInfo[maxRow].End - top; } } } AddDragHandles(); int childIndex = 0; UIElementCollection adornerChildren = AdornerLayer.Children; for (int row = 0; row < rows - 1; row++) { GridResizer resizer = (GridResizer)adornerChildren[childIndex++]; int startCol = -1; int endCol = cols - 1; for (int col = 0; col < cols; col++) { if ((startCol == -1) && (model.CellChildMap[row, col] != model.CellChildMap[row + 1, col])) { startCol = col; } else if ((startCol != -1) && (model.CellChildMap[row, col] == model.CellChildMap[row + 1, col])) { endCol = col - 1; break; } } if (startCol != -1) { // hard coding this as (resizer.ActualHeight / 2) will still evaluate to 0 here ... a layout hasn't yet happened Canvas.SetTop(resizer, _rowInfo[row].End + (spacing / 2) - 24); Canvas.SetLeft(resizer, (_colInfo[endCol].End + _colInfo[startCol].Start) / 2); } else { resizer.Visibility = Visibility.Collapsed; } } for (int col = 0; col < cols - 1; col++) { GridResizer resizer = (GridResizer)adornerChildren[childIndex++]; int startRow = -1; int endRow = rows - 1; for (int row = 0; row < rows; row++) { if ((startRow == -1) && (model.CellChildMap[row, col] != model.CellChildMap[row, col + 1])) { startRow = row; } else if ((startRow != -1) && (model.CellChildMap[row, col] == model.CellChildMap[row, col + 1])) { endRow = row - 1; break; } } if (startRow != -1) { Canvas.SetLeft(resizer, _colInfo[col].End + (spacing / 2) - 24); // hard coding this as (resizer.ActualWidth / 2) will still evaluate to 0 here ... a layout hasn't yet happened Canvas.SetTop(resizer, (_rowInfo[endRow].End + _rowInfo[startRow].Start) / 2); } else { resizer.Visibility = Visibility.Collapsed; } } }
private void OnSplit(object o, SplitEventArgs e) { UIElementCollection previewChildren = Preview.Children; GridZone splitee = (GridZone)o; int spliteeIndex = previewChildren.IndexOf(splitee); GridLayoutModel model = Model; int rows = model.Rows; int cols = model.Columns; int foundRow = -1; int foundCol = -1; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { if (model.CellChildMap[row, col] == spliteeIndex) { foundRow = row; foundCol = col; break; } } if (foundRow != -1) { break; } } int newChildIndex = AddZone(); double offset = e.Offset; if (e.Orientation == Orientation.Vertical) { if (splitee.VerticalSnapPoints != null) { offset += Canvas.GetLeft(splitee); int count = splitee.VerticalSnapPoints.Length; bool foundExistingSplit = false; for (int i = 0; i <= count; i++) { if (foundExistingSplit) { int walkRow = foundRow; while ((walkRow < rows) && (model.CellChildMap[walkRow, foundCol + i] == spliteeIndex)) { model.CellChildMap[walkRow++, foundCol + i] = newChildIndex; } } if (_colInfo[foundCol + i].End == offset) { foundExistingSplit = true; // use existing division } } if (foundExistingSplit) { OnGridDimensionsChanged(); return; } while (_colInfo[foundCol].End < offset) { foundCol++; } offset -= _colInfo[foundCol].Start; } AddDragHandle(Orientation.Vertical, cols - 1); cols++; int[,] newCellChildMap = new int[rows, cols]; int[] newColPercents = new int[cols]; RowColInfo[] newColInfo = new RowColInfo[cols]; int sourceCol = 0; for (int col = 0; col < cols; col++) { for (int row = 0; row < rows; row++) { if ((col > foundCol) && (model.CellChildMap[row, sourceCol] == spliteeIndex)) { newCellChildMap[row, col] = newChildIndex; } else { newCellChildMap[row, col] = model.CellChildMap[row, sourceCol]; } } if (col != foundCol) { sourceCol++; } } model.CellChildMap = newCellChildMap; sourceCol = 0; for (int col = 0; col < cols; col++) { if (col == foundCol) { RowColInfo[] split = _colInfo[col].Split(offset); newColPercents[col] = split[0].Percent; newColInfo[col++] = split[0]; newColPercents[col] = split[1].Percent; newColInfo[col] = split[1]; sourceCol++; } else { newColPercents[col] = model.ColumnPercents[sourceCol]; newColInfo[col] = _colInfo[sourceCol++]; } } _colInfo = newColInfo; model.ColumnPercents = newColPercents; model.Columns++; } else { // Horizontal if (splitee.HorizontalSnapPoints != null) { offset += Canvas.GetTop(splitee); int count = splitee.HorizontalSnapPoints.Length; bool foundExistingSplit = false; for (int i = 0; i <= count; i++) { if (foundExistingSplit) { int walkCol = foundCol; while ((walkCol < cols) && (model.CellChildMap[foundRow + i, walkCol] == spliteeIndex)) { model.CellChildMap[foundRow + i, walkCol] = newChildIndex; } } if (_rowInfo[foundRow + i].End == offset) { foundExistingSplit = true; // use existing division } } if (foundExistingSplit) { OnGridDimensionsChanged(); return; } while (_rowInfo[foundRow].End < offset) { foundRow++; } offset -= _rowInfo[foundRow].Start; } AddDragHandle(Orientation.Horizontal, rows - 1); rows++; int[,] newCellChildMap = new int[rows, cols]; int[] newRowPercents = new int[rows]; RowColInfo[] newRowInfo = new RowColInfo[rows]; int sourceRow = 0; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { if ((row > foundRow) && (model.CellChildMap[sourceRow, col] == spliteeIndex)) { newCellChildMap[row, col] = newChildIndex; } else { newCellChildMap[row, col] = model.CellChildMap[sourceRow, col]; } } if (row != foundRow) { sourceRow++; } } model.CellChildMap = newCellChildMap; sourceRow = 0; for (int row = 0; row < rows; row++) { if (row == foundRow) { RowColInfo[] split = _rowInfo[row].Split(offset); newRowPercents[row] = split[0].Percent; newRowInfo[row++] = split[0]; newRowPercents[row] = split[1].Percent; newRowInfo[row] = split[1]; sourceRow++; } else { newRowPercents[row] = model.RowPercents[sourceRow]; newRowInfo[row] = _rowInfo[sourceRow++]; } } _rowInfo = newRowInfo; model.RowPercents = newRowPercents; model.Rows++; } }