public static DecimalPoint AddPoint(this DecimalPoint p, DecimalPoint q) { return(new DecimalPoint(p.X + q.X, p.Y + q.Y)); }
public static decimal LineLength(this DecimalPoint p, DecimalPoint q) { return((decimal)Math.Sqrt(Math.Pow((double)p.X - (double)q.X, 2) + Math.Pow((double)p.Y + (double)q.Y, 2))); }
public static decimal LineHeight(this DecimalPoint p, DecimalPoint q) { return(Math.Abs(p.Y - q.Y)); }
public Rect PlaceControl(UIElement child) { var finalSize = child.DesiredSize; if (finalSize.Width == 0 || finalSize.Height == 0) { return(new Rect(0, 0, 0, 0)); } this.OptimizePoints(); var sortedPointsLeftFirst = from p in this.Points orderby p.Key.X, p.Key.Y ascending select p; var sortedPointsTopFirst = from p in this.Points orderby p.Key.Y, p.Key.X ascending select p; Rect finalRect = new Rect(); for (int i = 0; i < sortedPointsLeftFirst.Count(); i++) { var entry = sortedPointsLeftFirst.ElementAt(i); var upperPoint = entry.Key; var lowerPoint = entry.Value; if ((decimal)finalSize.Height <= upperPoint.LineHeight(lowerPoint)) { // Case 1: The tile is shorter or equal to the current line finalRect = new Rect(upperPoint.ToPoint(), finalSize); // Split line var newUpperPoint1 = new DecimalPoint(upperPoint.X + (decimal)finalSize.Width, upperPoint.Y); var newLowerPoint1 = new DecimalPoint(upperPoint.X + (decimal)finalSize.Width, upperPoint.Y + (decimal)finalSize.Height); this.Points.Remove(upperPoint); this.Points.Add(newUpperPoint1, newLowerPoint1); if ((decimal)finalSize.Height < upperPoint.LineHeight(lowerPoint)) { var newUpperPoint2 = new DecimalPoint(lowerPoint.X, upperPoint.Y + (decimal)finalSize.Height); var newLowerPoint2 = lowerPoint; this.Points.Add(newUpperPoint2, newLowerPoint2); } break; } else { // Case 2:The tile is longer than the current line var lowerNeighbors = new Dictionary <DecimalPoint, DecimalPoint>(); decimal sum = upperPoint.LineHeight(lowerPoint); foreach (var neighbor in from p in sortedPointsTopFirst where p.Key.Y >= lowerPoint.Y select p) { lowerNeighbors.Add(neighbor.Key, neighbor.Value); sum += neighbor.Key.LineHeight(neighbor.Value); if (sum >= (decimal)finalSize.Height) { break; } } if (sum < (decimal)finalSize.Height) { // We would leak outside the view at the bottom continue; } // Now we do have all lower neighbors if (lowerNeighbors.Count > 0) { // Do we have place or not? bool cont = false; foreach (var neighbor in lowerNeighbors) { if (neighbor.Key.X > upperPoint.X) { // We have no space! cont = true; break; } } if (cont) { continue; } } else { continue; } // We have space finalRect = new Rect(new Point((double)upperPoint.X, (double)upperPoint.Y), finalSize); var lowestNeighbor = lowerNeighbors.Last(); // Remove all lower neighbor points for (int j = 0; j < lowerNeighbors.Count; j++) { this.Points.Remove(lowerNeighbors.ElementAt(j).Key); } this.Points.Remove(upperPoint); // Add the necessary points var newUpperPoint1 = new DecimalPoint(upperPoint.X + (decimal)finalSize.Width, upperPoint.Y); var newLowerPoint1 = new DecimalPoint(upperPoint.X + (decimal)finalSize.Width, upperPoint.Y + (decimal)finalSize.Height); var newUpperPoint2 = new DecimalPoint(lowestNeighbor.Key.X, upperPoint.Y + (decimal)finalSize.Height); var newLowerPoint2 = lowestNeighbor.Value; this.Points.Add(newUpperPoint1, newLowerPoint1); this.Points.Add(newUpperPoint2, newLowerPoint2); return(finalRect); } } if (finalRect == new Rect()) { var right = this.Points.Max(p => p.Key.X); var topPoint = (from p in this.Points where p.Key.Y == 0 select p).First(); this.Points.Remove(topPoint.Key); this.Points.Add(new DecimalPoint(right, topPoint.Key.Y), new DecimalPoint(right, topPoint.Value.Y)); this.OptimizePoints(); return(this.PlaceControl(child)); } return(finalRect); }