/// <summary> /// The heart of the program /// Returns the best available slot based on the input requirements /// </summary> /// <param name="activity">The slot type</param> /// <param name="status">Used to push aside low priority tables if needed</param> /// <returns>The best suited slot based on the requirements</returns> private Slot GetAvailableSlot(Slot.ActivityUses slotType, Table table) { Slot resultSlot = null; // Find all possible slots & order them var possibleSlots = Config.Active.ActiveProfile.Slots .Where(s => s.ActivityUse == slotType) // Match the slot type (active/inactive) .OrderBy(s => s.OccupiedBy.Count) // Pick the best slot .ThenBy(s => s.Priority) // Pick user preferred slot .ThenBy(s => s.X) // Pick left-to-right instead .ThenBy(s => s.Y); // Handle situations where no slot for this use is found if (possibleSlots.Count() == 0) { if (slotType == Slot.ActivityUses.Aside) { Logger.Log("WindowManager: Attempting to move table aside but there is no aside slot. Add one in config.", Logger.Status.Warning, showMessageBox: true); } else { Logger.Log($"WindowManager: An active or inactive slot was missing. Corrupt config?", Logger.Status.Fatal); } return(resultSlot); } // Try to find an empty or the current slot or stackable slot - filter by preferred slot resultSlot = possibleSlots .Where(s => s.OccupiedBy.Count == 0 || s.OccupiedBy.Contains(table) || s.CanStack) .OrderBy(s => s.OccupiedBy.Count) // Prefer empty slots regardless of preferred .ThenByDescending(s => table.PreferredSlot != null && s == table.PreferredSlot) // pick the table's preferred slot .ThenBy(s => s.OccupiedBy.Where(t => t.PreferredSlot == null).Count()) // Find a slot with a table without a preferred slot .FirstOrDefault(); if (resultSlot != null) { return(resultSlot); } // At this point only handle active tables if (slotType == Slot.ActivityUses.Aside) { Logger.Log($"WindowManager: Tried to find Aside slot but none were available."); return(resultSlot); // No available aside slots, do nothing. } else if (slotType == Slot.ActivityUses.Inactive) { Logger.Log($"WindowManager: No inactive slot available. " + "This should be impossible since Inactive slots must be stackable. Corrupt config?", Logger.Status.Fatal); return(resultSlot); } // Try to find an active slot with a low priority table and push it to Inactive. resultSlot = possibleSlots // Only tables with priority that's allowed to be pushed aside .Where(s => s.OccupiedBy.First().Priority <= Table.Status.NoActionRequired) // Find lowest priority table to push aside .OrderByDescending(s => s.OccupiedBy .OrderBy(x => x.Priority) .ThenByDescending(x => x.PriorityChangedTime) .First().PriorityChangedTime ) .FirstOrDefault(); // Give up if there's no table to push or // Push the table we found to inactive & return the free slot if (resultSlot != null) { Table tableToMove = resultSlot.OccupiedBy.First(); Slot anInactiveSlot = GetAvailableSlot(Slot.ActivityUses.Inactive, table); Slot previousSlot = Config.Active.ActiveProfile.Slots .Where(s => s.OccupiedBy.Contains(tableToMove)) .FirstOrDefault(); // Move table in queue MoveTable(tableToMove, anInactiveSlot, previousSlot); // Also move any double stacked tables when an inactive slot is available if (Config.Active.PreferSpreadOverStack) { // if there's a free inactive slot var freeInactiveSlots = Config.Active.ActiveProfile.Slots.Where(s => s.ActivityUse == Slot.ActivityUses.Inactive && s.OccupiedBy.Count == 0); if (freeInactiveSlots.Count() > 0) { // Find a slot with a table that should be moved, if any Slot slotWithUnnessecarilyStackedTable = Config.Active.ActiveProfile.Slots .Where(s => s.ActivityUse == Slot.ActivityUses.Inactive) .Where(s => s.OccupiedBy.Count > 1) .FirstOrDefault(); // if we found a slot, move the most approperiate table if (slotWithUnnessecarilyStackedTable != null) { Table bestTableToMove = slotWithUnnessecarilyStackedTable.OccupiedBy. OrderByDescending(t => t.PriorityChangedTime) .FirstOrDefault(); MoveTable( bestTableToMove, freeInactiveSlots.First(), slotWithUnnessecarilyStackedTable); } } } } return(resultSlot); }
public ActivityUseChangedEventArgs(Slot.ActivityUses oldActivityUse, Slot.ActivityUses newActivityUse) { OldActivityUse = oldActivityUse; NewActivityUse = newActivityUse; }