2020-07-16 12:54:15 +03:00
|
|
|
// Copyright (c) Microsoft Corporation
|
|
|
|
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
|
|
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
using FancyZonesEditor.Models;
|
2020-11-17 11:38:19 +03:00
|
|
|
using FancyZonesEditor.Utils;
|
2020-07-16 12:54:15 +03:00
|
|
|
|
|
|
|
|
namespace FancyZonesEditor
|
|
|
|
|
{
|
|
|
|
|
public class GridData
|
|
|
|
|
{
|
2020-09-14 10:05:28 +02:00
|
|
|
// The sum of row/column percents should be equal to this number
|
|
|
|
|
private const int _multiplier = 10000;
|
|
|
|
|
|
2020-07-16 12:54:15 +03:00
|
|
|
public class ResizeInfo
|
|
|
|
|
{
|
|
|
|
|
public ResizeInfo()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int NewPercent { get; set; }
|
|
|
|
|
|
|
|
|
|
public int AdjacentPercent { get; private set; }
|
|
|
|
|
|
|
|
|
|
public int TotalPercent { get; private set; }
|
|
|
|
|
|
|
|
|
|
public int CurrentPercent { get; set; }
|
|
|
|
|
|
|
|
|
|
public double CurrentExtent { get; set; }
|
|
|
|
|
|
|
|
|
|
public bool IsResizeAllowed
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return (NewPercent > 0) && (NewPercent < TotalPercent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CalcNewPercent(double delta)
|
|
|
|
|
{
|
|
|
|
|
double newExtent = CurrentExtent + _adjacentExtent + delta;
|
|
|
|
|
NewPercent = (int)((CurrentPercent + AdjacentPercent) * newExtent / (CurrentExtent + _adjacentExtent));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CalcAdjacentZones(int index, int size, List<RowColInfo> info, Func<int, bool> indexCmpr)
|
|
|
|
|
{
|
2020-11-18 11:47:24 -08:00
|
|
|
if (info == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException(nameof(info));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (indexCmpr == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException(nameof(indexCmpr));
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-16 12:54:15 +03:00
|
|
|
int ind = index;
|
|
|
|
|
while (ind > 0 && indexCmpr(ind))
|
|
|
|
|
{
|
|
|
|
|
ind--;
|
|
|
|
|
_adjacentExtent += info[ind].Extent;
|
|
|
|
|
AdjacentPercent += info[ind].Percent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TotalPercent = CurrentPercent + AdjacentPercent + info[index + 1].Percent;
|
|
|
|
|
|
|
|
|
|
ind = index + 2;
|
|
|
|
|
while (ind < size && indexCmpr(ind))
|
|
|
|
|
{
|
|
|
|
|
TotalPercent += info[ind].Percent;
|
|
|
|
|
ind++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void FixAccuracyError(List<RowColInfo> info, List<int> percents, int index)
|
|
|
|
|
{
|
|
|
|
|
int total = 0;
|
|
|
|
|
for (int i = 0; i < info.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
total += info[i].Percent;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-14 10:05:28 +02:00
|
|
|
int diff = total - _multiplier;
|
2020-07-16 12:54:15 +03:00
|
|
|
if (diff != 0)
|
|
|
|
|
{
|
|
|
|
|
TotalPercent -= diff;
|
|
|
|
|
|
|
|
|
|
while (index >= info.Count)
|
|
|
|
|
{
|
|
|
|
|
index--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info[index].Percent -= diff;
|
|
|
|
|
percents[index] -= diff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double _adjacentExtent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public GridData(GridLayoutModel model)
|
|
|
|
|
{
|
|
|
|
|
_model = model;
|
|
|
|
|
|
|
|
|
|
int rows = model.Rows;
|
|
|
|
|
int cols = model.Columns;
|
|
|
|
|
|
|
|
|
|
_rowInfo = new List<RowColInfo>(rows);
|
|
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
_rowInfo.Add(new RowColInfo(model.RowPercents[row]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_colInfo = new List<RowColInfo>(cols);
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
_colInfo.Add(new RowColInfo(model.ColumnPercents[col]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int ZoneCount
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
int maxIndex = 0;
|
|
|
|
|
for (int row = 0; row < _model.Rows; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < _model.Columns; col++)
|
|
|
|
|
{
|
|
|
|
|
maxIndex = Math.Max(maxIndex, _model.CellChildMap[row, col]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return maxIndex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Tuple<int, int> RowColByIndex(int index)
|
|
|
|
|
{
|
|
|
|
|
int foundRow = -1;
|
|
|
|
|
int foundCol = -1;
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < _model.Rows && foundRow == -1; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < _model.Columns && foundCol == -1; col++)
|
|
|
|
|
{
|
|
|
|
|
if (_model.CellChildMap[row, col] == index)
|
|
|
|
|
{
|
|
|
|
|
foundRow = row;
|
|
|
|
|
foundCol = col;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new Tuple<int, int>(foundRow, foundCol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetIndex(int row, int col)
|
|
|
|
|
{
|
|
|
|
|
return _model.CellChildMap[row, col];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double ColumnTop(int column)
|
|
|
|
|
{
|
|
|
|
|
return _colInfo[column].Start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double ColumnBottom(int column)
|
|
|
|
|
{
|
|
|
|
|
return _colInfo[column].End;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double RowStart(int row)
|
|
|
|
|
{
|
|
|
|
|
return _rowInfo[row].Start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double RowEnd(int row)
|
|
|
|
|
{
|
|
|
|
|
return _rowInfo[row].End;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetIndex(int row, int col, int index)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[row, col] = index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SplitColumn(int foundCol, int spliteeIndex, int newChildIndex, double space, double offset, double actualWidth)
|
|
|
|
|
{
|
|
|
|
|
int rows = _model.Rows;
|
|
|
|
|
int cols = _model.Columns + 1;
|
|
|
|
|
|
|
|
|
|
int[,] cellChildMap = _model.CellChildMap;
|
|
|
|
|
int[,] newCellChildMap = new int[rows, cols];
|
|
|
|
|
|
|
|
|
|
int sourceCol = 0;
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
if (cellChildMap[row, sourceCol] > spliteeIndex || ((col > foundCol) && (cellChildMap[row, sourceCol] == spliteeIndex)))
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[row, sourceCol] + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[row, sourceCol];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (col != foundCol)
|
|
|
|
|
{
|
|
|
|
|
sourceCol++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RowColInfo[] split = _colInfo[foundCol].Split(offset, space);
|
|
|
|
|
|
|
|
|
|
_colInfo[foundCol] = split[0];
|
|
|
|
|
_colInfo.Insert(foundCol + 1, split[1]);
|
|
|
|
|
|
|
|
|
|
_model.ColumnPercents[foundCol] = split[0].Percent;
|
|
|
|
|
_model.ColumnPercents.Insert(foundCol + 1, split[1].Percent);
|
|
|
|
|
|
|
|
|
|
double newTotalExtent = actualWidth - (space * (cols + 1));
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
if (col != foundCol && col != foundCol + 1)
|
|
|
|
|
{
|
|
|
|
|
_colInfo[col].RecalculatePercent(newTotalExtent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FixAccuracyError(_colInfo, _model.ColumnPercents);
|
|
|
|
|
_model.CellChildMap = newCellChildMap;
|
|
|
|
|
_model.Columns++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SplitRow(int foundRow, int spliteeIndex, int newChildIndex, double space, double offset, double actualHeight)
|
|
|
|
|
{
|
|
|
|
|
int rows = _model.Rows + 1;
|
|
|
|
|
int cols = _model.Columns;
|
|
|
|
|
|
|
|
|
|
int[,] cellChildMap = _model.CellChildMap;
|
|
|
|
|
int[,] newCellChildMap = new int[rows, cols];
|
|
|
|
|
|
|
|
|
|
int sourceRow = 0;
|
|
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
if (cellChildMap[sourceRow, col] > spliteeIndex || ((row > foundRow) && (cellChildMap[sourceRow, col] == spliteeIndex)))
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[sourceRow, col] + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[sourceRow, col];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (row != foundRow)
|
|
|
|
|
{
|
|
|
|
|
sourceRow++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RowColInfo[] split = _rowInfo[foundRow].Split(offset, space);
|
|
|
|
|
|
|
|
|
|
_rowInfo[foundRow] = split[0];
|
|
|
|
|
_rowInfo.Insert(foundRow + 1, split[1]);
|
|
|
|
|
|
|
|
|
|
_model.RowPercents[foundRow] = split[0].Percent;
|
|
|
|
|
_model.RowPercents.Insert(foundRow + 1, split[1].Percent);
|
|
|
|
|
|
|
|
|
|
double newTotalExtent = actualHeight - (space * (rows + 1));
|
|
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
if (row != foundRow && row != foundRow + 1)
|
|
|
|
|
{
|
|
|
|
|
_rowInfo[row].RecalculatePercent(newTotalExtent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FixAccuracyError(_rowInfo, _model.RowPercents);
|
|
|
|
|
_model.CellChildMap = newCellChildMap;
|
|
|
|
|
_model.Rows++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SplitOnDrag(GridResizer resizer, double delta, double space)
|
|
|
|
|
{
|
|
|
|
|
if (resizer.Orientation == Orientation.Vertical)
|
|
|
|
|
{
|
|
|
|
|
int rows = _model.Rows;
|
|
|
|
|
int cols = _model.Columns + 1;
|
|
|
|
|
int[,] cellChildMap = _model.CellChildMap;
|
|
|
|
|
int[,] newCellChildMap = new int[rows, cols];
|
|
|
|
|
|
|
|
|
|
int draggedResizerStartCol = resizer.StartCol;
|
|
|
|
|
|
|
|
|
|
if (delta > 0)
|
|
|
|
|
{
|
|
|
|
|
int sourceCol = 0;
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
if (col == draggedResizerStartCol + 1 && (row < resizer.StartRow || row >= resizer.EndRow))
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[row, sourceCol + 1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[row, sourceCol];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (col != draggedResizerStartCol)
|
|
|
|
|
{
|
|
|
|
|
sourceCol++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RowColInfo[] split = _colInfo[draggedResizerStartCol + 1].Split(delta, space);
|
|
|
|
|
|
|
|
|
|
_colInfo[draggedResizerStartCol + 1] = split[0];
|
|
|
|
|
_colInfo.Insert(draggedResizerStartCol + 2, split[1]);
|
|
|
|
|
|
|
|
|
|
_model.ColumnPercents[draggedResizerStartCol + 1] = split[0].Percent;
|
|
|
|
|
_model.ColumnPercents.Insert(draggedResizerStartCol + 2, split[1].Percent);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int sourceCol = 0;
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
if (col == draggedResizerStartCol + 1 && (row >= resizer.StartRow && row < resizer.EndRow))
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[row, sourceCol + 1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[row, sourceCol];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (col != draggedResizerStartCol)
|
|
|
|
|
{
|
|
|
|
|
sourceCol++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double offset = _colInfo[draggedResizerStartCol].End - _colInfo[draggedResizerStartCol].Start + delta;
|
|
|
|
|
RowColInfo[] split = _colInfo[draggedResizerStartCol].Split(offset - space, space);
|
|
|
|
|
|
|
|
|
|
_colInfo[draggedResizerStartCol] = split[1];
|
|
|
|
|
_colInfo.Insert(draggedResizerStartCol + 1, split[0]);
|
|
|
|
|
|
|
|
|
|
_model.ColumnPercents[draggedResizerStartCol] = split[1].Percent;
|
|
|
|
|
_model.ColumnPercents.Insert(draggedResizerStartCol + 1, split[0].Percent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FixAccuracyError(_colInfo, _model.ColumnPercents);
|
|
|
|
|
_model.CellChildMap = newCellChildMap;
|
|
|
|
|
_model.Columns++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int rows = _model.Rows + 1;
|
|
|
|
|
int cols = _model.Columns;
|
|
|
|
|
int[,] cellChildMap = _model.CellChildMap;
|
|
|
|
|
int[,] newCellChildMap = new int[rows, cols];
|
|
|
|
|
|
|
|
|
|
int draggedResizerStartRow = resizer.StartRow;
|
|
|
|
|
|
|
|
|
|
if (delta > 0)
|
|
|
|
|
{
|
2020-10-30 14:42:20 -04:00
|
|
|
int sourceRow = 0;
|
2020-07-16 12:54:15 +03:00
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
if (row == draggedResizerStartRow + 1 && (col < resizer.StartCol || col >= resizer.EndCol))
|
|
|
|
|
{
|
2020-10-30 14:42:20 -04:00
|
|
|
newCellChildMap[row, col] = cellChildMap[sourceRow + 1, col];
|
2020-07-16 12:54:15 +03:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-10-30 14:42:20 -04:00
|
|
|
newCellChildMap[row, col] = cellChildMap[sourceRow, col];
|
2020-07-16 12:54:15 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (row != draggedResizerStartRow)
|
|
|
|
|
{
|
2020-10-30 14:42:20 -04:00
|
|
|
sourceRow++;
|
2020-07-16 12:54:15 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RowColInfo[] split = _rowInfo[draggedResizerStartRow + 1].Split(delta, space);
|
|
|
|
|
|
|
|
|
|
_rowInfo[draggedResizerStartRow + 1] = split[0];
|
|
|
|
|
_rowInfo.Insert(draggedResizerStartRow + 2, split[1]);
|
|
|
|
|
|
|
|
|
|
_model.RowPercents[draggedResizerStartRow + 1] = split[0].Percent;
|
|
|
|
|
_model.RowPercents.Insert(draggedResizerStartRow + 2, split[1].Percent);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int sourceRow = 0;
|
|
|
|
|
for (int row = 0; row < rows; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < cols; col++)
|
|
|
|
|
{
|
|
|
|
|
if (row == draggedResizerStartRow + 1 && (col >= resizer.StartCol && col < resizer.EndCol))
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[sourceRow + 1, col];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[row, col] = cellChildMap[sourceRow, col];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (row != draggedResizerStartRow)
|
|
|
|
|
{
|
|
|
|
|
sourceRow++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double offset = _rowInfo[draggedResizerStartRow].End - _rowInfo[draggedResizerStartRow].Start + delta;
|
|
|
|
|
RowColInfo[] split = _rowInfo[draggedResizerStartRow].Split(offset - space, space);
|
|
|
|
|
|
|
|
|
|
_rowInfo[draggedResizerStartRow] = split[0];
|
|
|
|
|
_rowInfo.Insert(draggedResizerStartRow + 1, split[1]);
|
|
|
|
|
|
|
|
|
|
_model.RowPercents[draggedResizerStartRow] = split[0].Percent;
|
|
|
|
|
_model.RowPercents.Insert(draggedResizerStartRow + 1, split[1].Percent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FixAccuracyError(_rowInfo, _model.RowPercents);
|
|
|
|
|
_model.CellChildMap = newCellChildMap;
|
|
|
|
|
_model.Rows++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RecalculateZones(int spacing, Size arrangeSize)
|
|
|
|
|
{
|
|
|
|
|
int rows = _model.Rows;
|
|
|
|
|
int cols = _model.Columns;
|
|
|
|
|
|
|
|
|
|
double totalWidth = arrangeSize.Width - (spacing * (cols + 1));
|
|
|
|
|
double totalHeight = arrangeSize.Height - (spacing * (rows + 1));
|
|
|
|
|
|
|
|
|
|
double top = spacing;
|
|
|
|
|
for (int row = 0; row < _rowInfo.Count; row++)
|
|
|
|
|
{
|
|
|
|
|
double cellHeight = _rowInfo[row].Recalculate(top, totalHeight);
|
|
|
|
|
top += cellHeight + spacing;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double left = spacing;
|
|
|
|
|
for (int col = 0; col < _colInfo.Count; col++)
|
|
|
|
|
{
|
|
|
|
|
double cellWidth = _colInfo[col].Recalculate(left, totalWidth);
|
|
|
|
|
left += cellWidth + spacing;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ArrangeZones(UIElementCollection zones, int spacing)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ArrangeResizers(UIElementCollection adornerChildren, int spacing)
|
|
|
|
|
{
|
|
|
|
|
int rows = _model.Rows;
|
|
|
|
|
int cols = _model.Columns;
|
|
|
|
|
|
|
|
|
|
foreach (GridResizer resizer in adornerChildren)
|
|
|
|
|
{
|
|
|
|
|
if (resizer.Orientation == Orientation.Horizontal)
|
|
|
|
|
{
|
|
|
|
|
if (resizer.EndCol <= cols && resizer.StartRow < rows)
|
|
|
|
|
{
|
|
|
|
|
// hard coding this as (resizer.ActualHeight / 2) will still evaluate to 0 here ... a layout hasn't yet happened
|
|
|
|
|
Canvas.SetTop(resizer, _rowInfo[resizer.StartRow].End + (spacing / 2) - 24);
|
|
|
|
|
Canvas.SetLeft(resizer, (_colInfo[resizer.EndCol - 1].End + _colInfo[resizer.StartCol].Start) / 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (resizer.EndRow <= rows && resizer.StartCol < cols)
|
|
|
|
|
{
|
|
|
|
|
// hard coding this as (resizer.ActualWidth / 2) will still evaluate to 0 here ... a layout hasn't yet happened
|
|
|
|
|
Canvas.SetLeft(resizer, _colInfo[resizer.StartCol].End + (spacing / 2) - 24);
|
|
|
|
|
Canvas.SetTop(resizer, (_rowInfo[resizer.EndRow - 1].End + _rowInfo[resizer.StartRow].Start) / 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ResizeInfo CalculateResizeInfo(GridResizer resizer, double delta)
|
|
|
|
|
{
|
|
|
|
|
ResizeInfo res = new ResizeInfo();
|
|
|
|
|
|
|
|
|
|
int rowIndex = resizer.StartRow;
|
|
|
|
|
int colIndex = resizer.StartCol;
|
|
|
|
|
int[,] indices = _model.CellChildMap;
|
|
|
|
|
|
|
|
|
|
List<RowColInfo> info;
|
|
|
|
|
List<int> percents;
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
|
|
if (resizer.Orientation == Orientation.Vertical)
|
|
|
|
|
{
|
|
|
|
|
res.CurrentExtent = _colInfo[colIndex].Extent;
|
|
|
|
|
res.CurrentPercent = _colInfo[colIndex].Percent;
|
|
|
|
|
|
|
|
|
|
info = _colInfo;
|
|
|
|
|
percents = _model.ColumnPercents;
|
|
|
|
|
index = colIndex;
|
|
|
|
|
|
|
|
|
|
Func<int, bool> indexCmpr = (ind) =>
|
|
|
|
|
{
|
|
|
|
|
bool sameIndices = true;
|
|
|
|
|
for (int i = resizer.StartRow; i < resizer.EndRow && sameIndices; i++)
|
|
|
|
|
{
|
|
|
|
|
sameIndices &= indices[i, ind] == indices[i, ind - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sameIndices;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
res.CalcAdjacentZones(colIndex, _model.Columns, _colInfo, indexCmpr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res.CurrentExtent = _rowInfo[rowIndex].Extent;
|
|
|
|
|
res.CurrentPercent = _rowInfo[rowIndex].Percent;
|
|
|
|
|
|
|
|
|
|
info = _rowInfo;
|
|
|
|
|
percents = _model.RowPercents;
|
|
|
|
|
index = rowIndex;
|
|
|
|
|
|
|
|
|
|
Func<int, bool> indexCmpr = (ind) =>
|
|
|
|
|
{
|
|
|
|
|
bool sameIndices = true;
|
|
|
|
|
for (int i = resizer.StartCol; i < resizer.EndCol && sameIndices; i++)
|
|
|
|
|
{
|
|
|
|
|
sameIndices &= indices[ind, i] == indices[ind - 1, i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sameIndices;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
res.CalcAdjacentZones(rowIndex, _model.Rows, _rowInfo, indexCmpr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.FixAccuracyError(info, percents, delta > 0 ? index + 2 : index + 1);
|
|
|
|
|
res.CalcNewPercent(delta);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DragResizer(GridResizer resizer, ResizeInfo data)
|
|
|
|
|
{
|
|
|
|
|
List<RowColInfo> info;
|
|
|
|
|
List<int> percents;
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
|
|
if (resizer.Orientation == Orientation.Vertical)
|
|
|
|
|
{
|
|
|
|
|
info = _colInfo;
|
|
|
|
|
percents = _model.ColumnPercents;
|
|
|
|
|
index = resizer.StartCol;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info = _rowInfo;
|
|
|
|
|
percents = _model.RowPercents;
|
|
|
|
|
index = resizer.StartRow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nextPercent = data.CurrentPercent + data.AdjacentPercent + info[index + 1].Percent;
|
|
|
|
|
|
|
|
|
|
percents[index] = info[index].Percent = data.NewPercent - data.AdjacentPercent;
|
|
|
|
|
percents[index + 1] = info[index + 1].Percent = nextPercent - data.NewPercent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool SwapNegativePercents(Orientation orientation, int startRow, int endRow, int startCol, int endCol)
|
|
|
|
|
{
|
|
|
|
|
List<int> percents;
|
|
|
|
|
int index;
|
|
|
|
|
Action swapIndicesPrevLine, swapIndicesNextLine;
|
|
|
|
|
|
|
|
|
|
if (orientation == Orientation.Vertical)
|
|
|
|
|
{
|
|
|
|
|
percents = _model.ColumnPercents;
|
|
|
|
|
index = startCol;
|
|
|
|
|
|
|
|
|
|
swapIndicesPrevLine = () =>
|
|
|
|
|
{
|
|
|
|
|
for (int row = startRow; row < endRow; row++)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[row, startCol] = _model.CellChildMap[row, startCol + 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < _model.Rows; row++)
|
|
|
|
|
{
|
|
|
|
|
if (row < startRow || row >= endRow)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[row, startCol] = _model.CellChildMap[row, startCol - 1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
swapIndicesNextLine = () =>
|
|
|
|
|
{
|
|
|
|
|
for (int row = startRow; row < endRow; row++)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[row, startCol + 1] = _model.CellChildMap[row, startCol];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < _model.Rows; row++)
|
|
|
|
|
{
|
|
|
|
|
if (row < startRow || row >= endRow)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[row, startCol + 1] = _model.CellChildMap[row, startCol + 2];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
percents = _model.RowPercents;
|
|
|
|
|
index = startRow;
|
|
|
|
|
|
|
|
|
|
swapIndicesPrevLine = () =>
|
|
|
|
|
{
|
|
|
|
|
for (int col = startCol; col < endCol; col++)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[startRow, col] = _model.CellChildMap[startRow + 1, col];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int col = 0; col < _model.Columns; col++)
|
|
|
|
|
{
|
|
|
|
|
if (col < startCol || col >= endCol)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[startRow, col] = _model.CellChildMap[startRow - 1, col];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
swapIndicesNextLine = () =>
|
|
|
|
|
{
|
|
|
|
|
for (int col = startCol; col < endCol; col++)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[startRow + 1, col] = _model.CellChildMap[startRow, col];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int col = 0; col < _model.Columns; col++)
|
|
|
|
|
{
|
|
|
|
|
if (col < startCol || col >= endCol)
|
|
|
|
|
{
|
|
|
|
|
_model.CellChildMap[startRow + 1, col] = _model.CellChildMap[startRow + 2, col];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (percents[index] < 0)
|
|
|
|
|
{
|
|
|
|
|
swapIndicesPrevLine();
|
|
|
|
|
|
|
|
|
|
percents[index] = -percents[index];
|
|
|
|
|
percents[index - 1] = percents[index - 1] - percents[index];
|
|
|
|
|
|
|
|
|
|
if (orientation == Orientation.Vertical)
|
|
|
|
|
{
|
|
|
|
|
_colInfo[index].Percent = percents[index];
|
|
|
|
|
_colInfo[index - 1].Percent = percents[index - 1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_rowInfo[index].Percent = percents[index];
|
|
|
|
|
_rowInfo[index - 1].Percent = percents[index - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (percents[index + 1] < 0)
|
|
|
|
|
{
|
|
|
|
|
swapIndicesNextLine();
|
|
|
|
|
|
|
|
|
|
percents[index + 1] = -percents[index + 1];
|
|
|
|
|
percents[index] = percents[index] - percents[index + 1];
|
|
|
|
|
|
|
|
|
|
if (orientation == Orientation.Vertical)
|
|
|
|
|
{
|
|
|
|
|
_colInfo[index].Percent = percents[index];
|
|
|
|
|
_colInfo[index + 1].Percent = percents[index + 1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_rowInfo[index].Percent = percents[index];
|
|
|
|
|
_rowInfo[index + 1].Percent = percents[index + 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int SwappedIndexAfterResize(GridResizer resizer)
|
|
|
|
|
{
|
|
|
|
|
if (resizer.Orientation == Orientation.Horizontal)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < _model.Rows; i++)
|
|
|
|
|
{
|
|
|
|
|
if (_rowInfo[i].Percent < 0)
|
|
|
|
|
{
|
|
|
|
|
_rowInfo[i].Percent = -_rowInfo[i].Percent;
|
|
|
|
|
_rowInfo[i - 1].Percent -= _rowInfo[i].Percent;
|
|
|
|
|
_rowInfo[i + 1].Percent -= _rowInfo[i].Percent;
|
|
|
|
|
|
|
|
|
|
_model.RowPercents[i - 1] = _rowInfo[i - 1].Percent;
|
|
|
|
|
_model.RowPercents[i] = _rowInfo[i].Percent;
|
|
|
|
|
_model.RowPercents[i + 1] = _rowInfo[i + 1].Percent;
|
|
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int i = 1; i < _model.Columns; i++)
|
|
|
|
|
{
|
|
|
|
|
if (_colInfo[i].Percent < 0)
|
|
|
|
|
{
|
|
|
|
|
_colInfo[i - 1].Percent += _colInfo[i].Percent;
|
|
|
|
|
_colInfo[i].Percent = -_colInfo[i].Percent;
|
|
|
|
|
|
|
|
|
|
_model.ColumnPercents[i - 1] = _colInfo[i - 1].Percent;
|
|
|
|
|
_model.ColumnPercents[i] = _colInfo[i].Percent;
|
|
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void MergeZones(int startRow, int endRow, int startCol, int endCol, Action<int> deleteAction, int zoneCount)
|
|
|
|
|
{
|
|
|
|
|
int[,] cells = _model.CellChildMap;
|
|
|
|
|
int mergedIndex = cells[startRow, startCol];
|
|
|
|
|
|
|
|
|
|
// maintain indices order after merge
|
|
|
|
|
Dictionary<int, int> indexReplacement = new Dictionary<int, int>();
|
|
|
|
|
List<int> zoneIndices = new List<int>(zoneCount);
|
|
|
|
|
for (int i = 0; i < zoneCount; i++)
|
|
|
|
|
{
|
|
|
|
|
zoneIndices.Add(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int row = startRow; row <= endRow; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = startCol; col <= endCol; col++)
|
|
|
|
|
{
|
|
|
|
|
int childIndex = cells[row, col];
|
|
|
|
|
if (childIndex != mergedIndex)
|
|
|
|
|
{
|
|
|
|
|
indexReplacement[childIndex] = mergedIndex;
|
|
|
|
|
zoneIndices[childIndex] = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = zoneIndices.Count - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int index = zoneIndices[i];
|
|
|
|
|
if (index == -1)
|
|
|
|
|
{
|
|
|
|
|
deleteAction(i);
|
|
|
|
|
zoneIndices.RemoveAt(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = zoneIndices.Count - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
indexReplacement[zoneIndices[i]] = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReplaceIndicesToMaintainOrder(indexReplacement);
|
|
|
|
|
CollapseIndices();
|
|
|
|
|
FixAccuracyError(_rowInfo, _model.RowPercents);
|
|
|
|
|
FixAccuracyError(_colInfo, _model.ColumnPercents);
|
2020-08-17 10:00:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ReplaceIndicesToMaintainOrder(int zoneCount)
|
|
|
|
|
{
|
|
|
|
|
int[,] cells = _model.CellChildMap;
|
2020-07-16 12:54:15 +03:00
|
|
|
Dictionary<int, int> indexReplacement = new Dictionary<int, int>();
|
2020-08-17 10:00:56 -07:00
|
|
|
List<int> zoneIndices = new List<int>(zoneCount);
|
|
|
|
|
HashSet<int> zoneIndexSet = new HashSet<int>(zoneCount);
|
|
|
|
|
|
2020-07-16 12:54:15 +03:00
|
|
|
for (int i = 0; i < zoneCount; i++)
|
|
|
|
|
{
|
|
|
|
|
zoneIndices.Add(i);
|
2020-08-17 10:00:56 -07:00
|
|
|
}
|
|
|
|
|
|
2020-07-16 12:54:15 +03:00
|
|
|
for (int row = 0; row < _model.Rows; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < _model.Columns; col++)
|
|
|
|
|
{
|
|
|
|
|
zoneIndexSet.Add(cells[row, col]);
|
|
|
|
|
}
|
2020-08-17 10:00:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int j = 0;
|
|
|
|
|
foreach (int index in zoneIndexSet)
|
|
|
|
|
{
|
|
|
|
|
indexReplacement[index] = zoneIndices[j];
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReplaceIndicesToMaintainOrder(indexReplacement);
|
2020-07-16 12:54:15 +03:00
|
|
|
}
|
|
|
|
|
|
2020-08-17 10:00:56 -07:00
|
|
|
private void ReplaceIndicesToMaintainOrder(Dictionary<int, int> indexReplacement)
|
|
|
|
|
{
|
|
|
|
|
int[,] cells = _model.CellChildMap;
|
2020-07-16 12:54:15 +03:00
|
|
|
|
|
|
|
|
for (int row = 0; row < _model.Rows; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < _model.Columns; col++)
|
|
|
|
|
{
|
|
|
|
|
cells[row, col] = indexReplacement[cells[row, col]];
|
|
|
|
|
}
|
2020-08-17 10:00:56 -07:00
|
|
|
}
|
2020-07-16 12:54:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CollapseIndices()
|
|
|
|
|
{
|
|
|
|
|
List<int> rowsToRemove = new List<int>(), colsToRemove = new List<int>();
|
|
|
|
|
int[,] cellChildMap = _model.CellChildMap;
|
|
|
|
|
|
|
|
|
|
int arrayShift = 0;
|
|
|
|
|
for (int row = 1; row < _model.Rows; row++)
|
|
|
|
|
{
|
|
|
|
|
bool couldBeRemoved = true;
|
|
|
|
|
for (int col = 0; col < _model.Columns && couldBeRemoved; col++)
|
|
|
|
|
{
|
|
|
|
|
if (cellChildMap[row, col] != cellChildMap[row - 1, col])
|
|
|
|
|
{
|
|
|
|
|
couldBeRemoved = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (couldBeRemoved)
|
|
|
|
|
{
|
|
|
|
|
_rowInfo[row - 1 - arrayShift].Percent += _rowInfo[row - arrayShift].Percent;
|
|
|
|
|
_rowInfo.RemoveAt(row - arrayShift);
|
|
|
|
|
|
|
|
|
|
_model.RowPercents[row - 1 - arrayShift] += _model.RowPercents[row - arrayShift];
|
|
|
|
|
_model.RowPercents.RemoveAt(row - arrayShift);
|
|
|
|
|
|
|
|
|
|
rowsToRemove.Add(row);
|
|
|
|
|
arrayShift++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arrayShift = 0;
|
|
|
|
|
for (int col = 1; col < _model.Columns; col++)
|
|
|
|
|
{
|
|
|
|
|
bool couldBeRemoved = true;
|
|
|
|
|
for (int row = 0; row < _model.Rows && couldBeRemoved; row++)
|
|
|
|
|
{
|
|
|
|
|
if (cellChildMap[row, col] != cellChildMap[row, col - 1])
|
|
|
|
|
{
|
|
|
|
|
couldBeRemoved = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (couldBeRemoved)
|
|
|
|
|
{
|
|
|
|
|
_colInfo[col - 1 - arrayShift].Percent += _colInfo[col - arrayShift].Percent;
|
|
|
|
|
_colInfo.RemoveAt(col - arrayShift);
|
|
|
|
|
|
|
|
|
|
_model.ColumnPercents[col - 1 - arrayShift] += _model.ColumnPercents[col - arrayShift];
|
|
|
|
|
_model.ColumnPercents.RemoveAt(col - arrayShift);
|
|
|
|
|
|
|
|
|
|
colsToRemove.Add(col);
|
|
|
|
|
arrayShift++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rows = _model.Rows - rowsToRemove.Count;
|
|
|
|
|
int cols = _model.Columns - colsToRemove.Count;
|
|
|
|
|
|
|
|
|
|
if (rowsToRemove.Count > 0 || colsToRemove.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
int[,] newCellChildMap = new int[rows, cols];
|
|
|
|
|
int dstRow = 0, dstCol = 0;
|
|
|
|
|
|
|
|
|
|
int removableRowIndex = 0;
|
|
|
|
|
int removableRow = -1;
|
|
|
|
|
if (rowsToRemove.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
removableRow = rowsToRemove[removableRowIndex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < _model.Rows; row++)
|
|
|
|
|
{
|
|
|
|
|
if (row != removableRow)
|
|
|
|
|
{
|
|
|
|
|
int removableColIndex = 0;
|
|
|
|
|
int removableCol = -1;
|
|
|
|
|
if (colsToRemove.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
removableCol = colsToRemove[removableColIndex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dstCol = 0;
|
|
|
|
|
for (int col = 0; col < _model.Columns; col++)
|
|
|
|
|
{
|
|
|
|
|
if (col != removableCol)
|
|
|
|
|
{
|
|
|
|
|
newCellChildMap[dstRow, dstCol] = cellChildMap[row, col];
|
|
|
|
|
dstCol++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
removableColIndex++;
|
|
|
|
|
if (removableColIndex < colsToRemove.Count)
|
|
|
|
|
{
|
|
|
|
|
removableCol = colsToRemove[removableColIndex];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dstRow++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
removableRowIndex++;
|
|
|
|
|
if (removableRowIndex < rowsToRemove.Count)
|
|
|
|
|
{
|
|
|
|
|
removableRow = rowsToRemove[removableRowIndex];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_model.CellChildMap = newCellChildMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_model.Rows = rows;
|
|
|
|
|
_model.Columns = cols;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FixAccuracyError(List<RowColInfo> info, List<int> percents)
|
|
|
|
|
{
|
|
|
|
|
int total = 0;
|
|
|
|
|
for (int i = 0; i < info.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
total += info[i].Percent;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-14 10:05:28 +02:00
|
|
|
int prefixTotal = 0;
|
|
|
|
|
for (int i = 0; i < percents.Count; i++)
|
2020-07-16 12:54:15 +03:00
|
|
|
{
|
2020-09-14 10:05:28 +02:00
|
|
|
int first = prefixTotal * _multiplier / total;
|
|
|
|
|
prefixTotal += info[i].Percent;
|
|
|
|
|
int last = prefixTotal * _multiplier / total;
|
|
|
|
|
percents[i] = info[i].Percent = last - first;
|
2020-07-16 12:54:15 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private GridLayoutModel _model;
|
|
|
|
|
private List<RowColInfo> _rowInfo;
|
|
|
|
|
private List<RowColInfo> _colInfo;
|
|
|
|
|
}
|
|
|
|
|
}
|