diff --git a/SLC_LayoutEditor/Controls/CabinDeckControl.xaml.cs b/SLC_LayoutEditor/Controls/CabinDeckControl.xaml.cs index e01f319..50c9230 100644 --- a/SLC_LayoutEditor/Controls/CabinDeckControl.xaml.cs +++ b/SLC_LayoutEditor/Controls/CabinDeckControl.xaml.cs @@ -113,6 +113,14 @@ public CabinDeckControl() renderer?.SelectAllSlots(); } }, ViewModelMessage.Keybind_SelectAllSlotsOnDeck); + + Mediator.Instance.Register(o => + { + if (o is CabinDeck cabinDeck && cabinDeck != CabinDeck) + { + renderer.DeselectAllSlots(false); + } + }, ViewModelMessage.DeselectOther_Deck); } public void RefreshCabinDeckLayout() @@ -146,6 +154,11 @@ public void RefreshCabinDeckLayout() Logger.Default.WriteLog("Cabin deck rendered in {0} seconds", Math.Round((double)sw.ElapsedMilliseconds / 1000, 3)); } + public void SelectAllSlots(bool fireEvent) + { + renderer.SelectAllSlots(fireEvent); + } + private void Renderer_CloseTooltip(object sender, EventArgs e) { if (tooltip != null) diff --git a/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml b/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml index f72b403..80422a8 100644 --- a/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml +++ b/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml @@ -45,39 +45,39 @@ - - - - - - + + + + + diff --git a/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml.cs b/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml.cs index 4de8608..90bf817 100644 --- a/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml.cs +++ b/SLC_LayoutEditor/Controls/CabinLayoutControl.xaml.cs @@ -66,14 +66,11 @@ protected void InvokePropertyChanged(params string[] propertyNames) public event EventHandler Changed; public event EventHandler TemplatingModeToggled; public event EventHandler TemplateCreated; - public event EventHandler SelectedDeckChanged; public event EventHandler CabinDeckChanged; private CabinDeck currentRemoveTarget; - private CabinDeckControl selectedDeck; - #region CabinLayout property public CabinLayout CabinLayout { @@ -106,18 +103,6 @@ private static string GetCabinLayoutValueForLog(CabinLayout cabinLayout) } #endregion - #region SelectedCabinSlots property - public List SelectedCabinSlots - { - get { return (List)GetValue(SelectedCabinSlotsProperty); } - set { SetValue(SelectedCabinSlotsProperty, value); } - } - - // Using a DependencyProperty as the backing store for SelectedCabinSlots. This enables animation, styling, binding, etc... - public static readonly DependencyProperty SelectedCabinSlotsProperty = - DependencyProperty.Register("SelectedCabinSlots", typeof(List), typeof(CabinLayoutControl), new PropertyMetadata(new List())); - #endregion - public ContextMenu GuideMenu { get { return (ContextMenu)GetValue(GuideMenuProperty); } @@ -138,18 +123,6 @@ public ContextMenu GuideMenu public bool IsVerticalScrollBarVisible => deck_scroll.ComputedVerticalScrollBarVisibility == Visibility.Visible; - #region SelectedCabinSlotFloor property - public int SelectedCabinSlotFloor - { - get { return (int)GetValue(SelectedCabinSlotFloorProperty); } - set { SetValue(SelectedCabinSlotFloorProperty, value); } - } - - // Using a DependencyProperty as the backing store for SelectedCabinSlotFloor. This enables animation, styling, binding, etc... - public static readonly DependencyProperty SelectedCabinSlotFloorProperty = - DependencyProperty.Register("SelectedCabinSlotFloor", typeof(int), typeof(CabinLayoutControl), new PropertyMetadata(0)); - #endregion - #region SelectedMultiSlotTypeIndex properties public int SelectedMultiSlotTypeIndex { @@ -216,6 +189,24 @@ public CabinLayoutControl() { StartReloadLayout(); }, ViewModelMessage.Keybind_ReloadLayout); + + Mediator.Instance.Register(o => + { + foreach (CabinDeckControl deckLayoutControl in container_decks.Children.OfType()) + { + deckLayoutControl.SelectAllSlots(true); + } + }, ViewModelMessage.SelectAll_Layout); + + Mediator.Instance.Register(o => + { + if (o is int floor) + { + container_decks.Children.OfType() + .FirstOrDefault(x => x.CabinDeck.Floor == floor) + ?.SelectAllSlots(true); + } + }, ViewModelMessage.SelectAll_Deck); } public void GenerateThumbnailForLayout(bool overwrite = false) @@ -324,23 +315,15 @@ private void AddCabinDeckToUI(CabinDeck cabinDeck) public void DeselectSlots() { - selectedDeck?.DeselectSlots(); + foreach (CabinDeckControl cabinDeckControl in container_decks.Children.OfType()) + { + cabinDeckControl.DeselectSlots(); + } } private void CabinDeckControl_SelectedSlotsChanged(object sender, SelectedSlotsChangedEventArgs e) { - if (selectedDeck != null && - selectedDeck.CabinDeck.Floor != e.DeckControl.CabinDeck.Floor) - { - DeselectSlots(); - } - - SelectedCabinSlots = e.NewSelection.ToList(); - SelectedCabinSlotFloor = e.Floor; - selectedDeck = e.DeckControl; - OnSelectedSlotsChanged(e); - OnSelectedDeckChanged(new SelectedDeckChangedEventArgs(selectedDeck)); } private void CabinDeckControl_DeckRendered(object sender, EventArgs e) @@ -504,8 +487,6 @@ private void ReloadDeck_DialogClosing(object sender, DialogClosingEventArgs e) private void ReloadLayout() { - SelectedCabinSlots.Clear(); - selectedDeck?.SelectSlots(SelectedCabinSlots); CabinLayout.LoadCabinLayoutFromFile(true); RefreshCabinLayout(false); OnLayoutReloaded(EventArgs.Empty); @@ -633,11 +614,6 @@ private void EditCabinLayoutName_Click(object sender, RoutedEventArgs e) Mediator.Instance.NotifyColleagues(ViewModelMessage.EditLayoutNameRequested, CabinLayout); } - protected virtual void OnSelectedDeckChanged(SelectedDeckChangedEventArgs e) - { - SelectedDeckChanged?.Invoke(this, e); - } - protected virtual void OnSelectedSlotsChanged(SelectedSlotsChangedEventArgs e) { SelectedSlotsChanged?.Invoke(this, e); diff --git a/SLC_LayoutEditor/Controls/IssueTracker.xaml b/SLC_LayoutEditor/Controls/IssueTracker.xaml index ebfa690..c68ddbd 100644 --- a/SLC_LayoutEditor/Controls/IssueTracker.xaml +++ b/SLC_LayoutEditor/Controls/IssueTracker.xaml @@ -72,6 +72,35 @@ ShowAutoFix="True" AutoFixApplying="DuplicateDoors_AutoFixApplying" Description="Make sure that each door has a unique number across all decks"/> + + + + + + + + + 0 ? + string.Format("{0} non-aisle slots have been overridden while fixing {1} stairway positions.", result.FailCount, result.SuccessCount) : + string.Format("Fixed {0} stairway positions.", result.SuccessCount); + + result.SendNotification(message); } } @@ -123,7 +129,9 @@ private void Slots_AutoFixApplying(object sender, AutoFixApplyingEventArgs e) { if (e.Target is CabinDeck target) { - target.FixSlotCount(); + AutoFixResult result = target.FixSlotCount(); + + result.SendNotification(string.Format("{0} missing slots have been added to your layout", result.SuccessCount)); } } @@ -133,6 +141,12 @@ private void DuplicateDoors_AutoFixApplying(object sender, AutoFixApplyingEventA { AutoFixResult result = target.FixDuplicateDoors(); + string message = result.FailCount > 0 ? + string.Format("{0}/{1} door numbers have been\nadjusted successfully.\n{2} doors could not be adjusted.", result.SuccessCount, result.TotalCount, result.FailCount) : + string.Format("{0} door numbers have been adjusted.", result.SuccessCount); + + result.SendNotification(message); + if (App.GuidedTour.IsAwaitingAutoFix) { App.GuidedTour.ForceCompleteEntry(0, result.AllSucceeded); diff --git a/SLC_LayoutEditor/Controls/KeybindInfo.xaml b/SLC_LayoutEditor/Controls/KeybindInfo.xaml index 0df3e9d..a78d733 100644 --- a/SLC_LayoutEditor/Controls/KeybindInfo.xaml +++ b/SLC_LayoutEditor/Controls/KeybindInfo.xaml @@ -3,14 +3,75 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:dvm="clr-namespace:SLC_LayoutEditor.ViewModel.DesignTime" xmlns:local="clr-namespace:SLC_LayoutEditor.Controls" mc:Ignorable="d" d:DesignWidth="150" Margin="8"> - + + + + + + + + + + + + + + - + + + + + + + diff --git a/SLC_LayoutEditor/Controls/KeybindInfo.xaml.cs b/SLC_LayoutEditor/Controls/KeybindInfo.xaml.cs index ceca651..b87bdbe 100644 --- a/SLC_LayoutEditor/Controls/KeybindInfo.xaml.cs +++ b/SLC_LayoutEditor/Controls/KeybindInfo.xaml.cs @@ -30,6 +30,26 @@ public string Keybind public static readonly DependencyProperty KeybindProperty = DependencyProperty.Register("Keybind", typeof(string), typeof(KeybindInfo), new PropertyMetadata(null)); + public string ActionIcon + { + get { return (string)GetValue(ActionIconProperty); } + set { SetValue(ActionIconProperty, value); } + } + + // Using a DependencyProperty as the backing store for ActionIcon. This enables animation, styling, binding, etc... + public static readonly DependencyProperty ActionIconProperty = + DependencyProperty.Register("ActionIcon", typeof(string), typeof(KeybindInfo), new PropertyMetadata(null)); + + public string SecondActionIcon + { + get { return (string)GetValue(SecondActionIconProperty); } + set { SetValue(SecondActionIconProperty, value); } + } + + // Using a DependencyProperty as the backing store for SecondActionIcon. This enables animation, styling, binding, etc... + public static readonly DependencyProperty SecondActionIconProperty = + DependencyProperty.Register("SecondActionIcon", typeof(string), typeof(KeybindInfo), new PropertyMetadata(null)); + public string Title { get { return (string)GetValue(TitleProperty); } @@ -50,6 +70,16 @@ public string Notes public static readonly DependencyProperty NotesProperty = DependencyProperty.Register("Notes", typeof(string), typeof(KeybindInfo), new PropertyMetadata(null)); + public bool IsKeybindEnabled + { + get { return (bool)GetValue(IsKeybindEnabledProperty); } + set { SetValue(IsKeybindEnabledProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsKeybindEnabled. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsKeybindEnabledProperty = + DependencyProperty.Register("IsKeybindEnabled", typeof(bool), typeof(KeybindInfo), new PropertyMetadata(true)); + public KeybindInfo() { InitializeComponent(); diff --git a/SLC_LayoutEditor/Core/AutoFix/AutoFixResult.cs b/SLC_LayoutEditor/Core/AutoFix/AutoFixResult.cs index ddc093b..447f177 100644 --- a/SLC_LayoutEditor/Core/AutoFix/AutoFixResult.cs +++ b/SLC_LayoutEditor/Core/AutoFix/AutoFixResult.cs @@ -1,4 +1,5 @@ -using System; +using SLC_LayoutEditor.Controls.Notifications; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -15,8 +16,16 @@ public class AutoFixResult private string failText; private int failCount; + private string notificationTitle; + public bool AllSucceeded => failCount == 0; + public int SuccessCount => successCount; + + public int FailCount => failCount; + + public int TotalCount => successCount + failCount; + public void CountSuccess() { successCount++; @@ -37,12 +46,19 @@ public void CountFails(int amount) failCount += amount; } - public AutoFixResult(string resultText, string successText, string failText) + public AutoFixResult(string resultText, string successText, string failText, + string notificationTitle) { //this.floor = floor; this.resultText = resultText; this.successText = successText; this.failText = failText; + this.notificationTitle = notificationTitle; + } + + public void SendNotification(string message) + { + Notification.MakeTimedNotification(notificationTitle, message, 15000, FixedValues.ICON_AUTO_FIX); } public override string ToString() diff --git a/SLC_LayoutEditor/Core/Cabin/CabinDeck.cs b/SLC_LayoutEditor/Core/Cabin/CabinDeck.cs index 06e1703..fa6914e 100644 --- a/SLC_LayoutEditor/Core/Cabin/CabinDeck.cs +++ b/SLC_LayoutEditor/Core/Cabin/CabinDeck.cs @@ -315,7 +315,7 @@ public int CountRowsWithSeats() return CabinSlots.Where(x => x.IsSeat).GroupBy(x => x.Column).Count(); } - public bool ContainsCabinSlots(IEnumerable targets) + public bool ContainsAnyCabinSlots(IEnumerable targets) { if (targets == null) { @@ -324,13 +324,13 @@ public bool ContainsCabinSlots(IEnumerable targets) foreach (CabinSlot target in targets) { - if (!ContainsCabinSlot(target)) + if (ContainsCabinSlot(target)) { - return false; + return true; } } - return true; + return false; } public bool ContainsCabinSlot(CabinSlot target) @@ -382,8 +382,8 @@ public int GetDeckRows() public AutoFixResult FixSlotCount() { - AutoFixResult autoFixResult = new AutoFixResult("Slot fix applied.", "Amount of added slots", - "Failed changes"); + AutoFixResult autoFixResult = new AutoFixResult("Slot fix applied", "Amount of added slots", + "Failed changes", "Slots filled in"); int expectedRowsCount = CabinSlots.Max(x => x.Row); var ordered = CabinSlots.GroupBy(x => x.Column).OrderBy(x => x.Key); diff --git a/SLC_LayoutEditor/Core/Cabin/CabinLayout.cs b/SLC_LayoutEditor/Core/Cabin/CabinLayout.cs index a5be945..ab77e76 100644 --- a/SLC_LayoutEditor/Core/Cabin/CabinLayout.cs +++ b/SLC_LayoutEditor/Core/Cabin/CabinLayout.cs @@ -110,6 +110,14 @@ public IEnumerable InvalidSlots public IEnumerable DuplicateDoors => InvalidSlots?.Where(duplicateDoorssCondition); public bool HasNoDuplicateDoors => !DuplicateDoors?.Any() ?? true; + + public int CateringDoorSurplus => Math.Max(0, mCabinDecks.Sum(x => x.DoorSlots.Count(y => y.Type == CabinSlotType.CateringDoor)) - 9); + + public bool HasNoCateringDoorSurplus => CateringDoorSurplus <= 0; + + public int DoorSurplus => Math.Max(0, mCabinDecks.Sum(x => x.DoorSlots.Count(y => y.IsDoor)) - 99); + + public bool HasNoDoorSurplus => DoorSurplus <= 0; #endregion public IEnumerable InvalidStairways => InvalidSlots?.Where(invalidStairwaysCondition); @@ -177,6 +185,8 @@ public string IssuesCountText public bool IsTemplate => isTemplate; + public bool IsEmpty => mCabinDecks.Count == 0; + public string ThumbnailDirectory => !IsTemplate ? Path.Combine(App.ThumbnailsPath, layoutFile.Directory.Name, mLayoutName) : Path.Combine(App.ThumbnailsPath, layoutFile.Directory.Parent.Name, "templates", mLayoutName); @@ -186,11 +196,11 @@ public string IssuesCountText //private string SnapshotFilePath => Path.Combine(SnapshotSubDirectory, layoutFile.Name); private bool HasSnapshots => Directory.Exists(SnapshotSubDirectory) && - Directory.EnumerateFiles(SnapshotSubDirectory, string.Format("{0}.*.txt", LayoutName)).Count() > 0; + Directory.EnumerateFiles(SnapshotSubDirectory, string.Format("{0}.*.txt", mLayoutName)).Count() > 0; public IEnumerable GetSnapshots() { - return Directory.EnumerateFiles(SnapshotSubDirectory, string.Format("{0}.*.txt", LayoutName)).Reverse(); + return Directory.EnumerateFiles(SnapshotSubDirectory, string.Format("{0}.*.txt", mLayoutName)).Reverse(); } public CabinLayout(string layoutName, string aircraftName, bool isTemplate) : @@ -199,8 +209,8 @@ public CabinLayout(string layoutName, string aircraftName, bool isTemplate) : layoutName + ".txt"))) { mLayoutName = layoutName; - #region Generate default layout + #region Generate default layout CabinDeck deck = new CabinDeck(0, 14, 6); deck.CabinSlotsChanged += Deck_CabinSlotsChanged; mCabinDecks.Add(deck); @@ -262,7 +272,7 @@ public void CreateSnapshot() if (Util.HasLayoutChanged(this)) { Directory.CreateDirectory(SnapshotSubDirectory); - string filePath = Path.Combine(SnapshotSubDirectory, string.Format("{0}.{1}.txt", LayoutName, + string filePath = Path.Combine(SnapshotSubDirectory, string.Format("{0}.{1}.txt", mLayoutName, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"))); File.WriteAllText(filePath, ToLayoutFile()); } @@ -297,8 +307,8 @@ public void RefreshData() public AutoFixResult FixDuplicateDoors() { - AutoFixResult autoFixResult = new AutoFixResult("Duplicate doors fix applied.", "Door numbers adjusted", - "Failed to adjust door numbers"); + AutoFixResult autoFixResult = new AutoFixResult("Duplicate doors fix applied", "Door numbers adjusted", + "Failed to adjust door numbers", "Fixed duplicate doors"); int doorsCount = mCabinDecks.Select(x => x.CabinSlots.Where(y => y.IsDoor).Count()).Sum(); ToggleIssueChecking(false); @@ -309,6 +319,13 @@ public AutoFixResult FixDuplicateDoors() bool handleCateringDoorsSeparately = doorsCount > 9; Dictionary> changesPerFloor = new Dictionary>(); + if (CateringDoorSurplus > 0) + { + Notification.MakeNotification("Too many catering doors", + string.Format("A layout can only have a total of 9\ncatering doors (CAT) across all decks.\nYour layout has {0} too many.", + CateringDoorSurplus), + FixedValues.ICON_AUTO_FIX_ALERT); + } if (handleCateringDoorsSeparately) // Prioritize numbering catering doors over other doors { @@ -326,7 +343,16 @@ public AutoFixResult FixDuplicateDoors() { slotNumber = cabinDeck.FixDuplicateDoors(slotNumber, isZeroDoorSet, handleCateringDoorsSeparately, out int successes, out int fails, out isZeroDoorSet, out List changes); - changesPerFloor.Add(cabinDeck.Floor, changes); + + if (!changesPerFloor.ContainsKey(cabinDeck.Floor)) + { + changesPerFloor.Add(cabinDeck.Floor, changes); + } + else + { + var targetKeyValuePair = changesPerFloor[cabinDeck.Floor]; + targetKeyValuePair = targetKeyValuePair.Merge(changes); + } autoFixResult.CountSuccesses(successes); autoFixResult.CountFails(fails); } @@ -641,12 +667,12 @@ public string ToLayoutFile() layoutRaw += cabinDeck.ToFileString() + "@"; } - return layoutRaw; + return layoutRaw != "" ? layoutRaw : "@"; } public void SaveLayout() { - Logger.Default.WriteLog("Saving {0} \"{1}\"...", IsTemplate ? "template" : "layout", LayoutName); + Logger.Default.WriteLog("Saving {0} \"{1}\"...", IsTemplate ? "template" : "layout", mLayoutName); File.WriteAllText(FilePath, ToLayoutFile()); Logger.Default.WriteLog("{0} saved successfully!", IsTemplate ? "template" : "layout"); OnCabinSlotsChanged(EventArgs.Empty); @@ -656,12 +682,11 @@ public AutoFixResult FixStairwayPositions() { CabinDeck firstDeckWithStairs = CabinDecks.FirstOrDefault(x => x.CabinSlots.Any(y => y.Type == CabinSlotType.Stairway)); - AutoFixResult autoFixResult = new AutoFixResult("Stairway fix applied.", "Amount of changed slots", - "Failed changes"); + AutoFixResult autoFixResult = new AutoFixResult("Stairway fix applied", "Stairways fixed", + "Non-aisle slots overwritten", "Fixed stairways"); if (HasMultipleDecks) { - // TODO: Rework stairway fix ToggleIssueChecking(false); Dictionary> changesPerFloor = new Dictionary>(); @@ -678,14 +703,15 @@ public AutoFixResult FixStairwayPositions() if (slotBelow?.Type != CabinSlotType.Stairway) { - if (hasPreviousDeckStairways) + if (cabinSlot.Type != CabinSlotType.Aisle) { - cabinSlot.Type = CabinSlotType.Aisle; - } - else - { - slotBelow.Type = CabinSlotType.Stairway; + autoFixResult.CountFail(); } + + cabinSlot.Type = hasPreviousDeckStairways ? + CabinSlotType.Aisle : CabinSlotType.Stairway; + + autoFixResult.CountSuccess(); } } if (nextDeck != null) @@ -694,7 +720,12 @@ public AutoFixResult FixStairwayPositions() if (slotAbove?.Type != CabinSlotType.Stairway) { + if (slotAbove.Type != CabinSlotType.Aisle) + { + autoFixResult.CountFail(); + } slotAbove.Type = CabinSlotType.Stairway; + autoFixResult.CountSuccess(); } } } @@ -711,44 +742,6 @@ public AutoFixResult FixStairwayPositions() CabinHistory.Instance.RecordChanges(changesPerFloor, AutomationMode.AutoFix_Stairways); ToggleIssueChecking(true); - - #region Old - /*Dictionary stairwayMapping = firstDeckWithStairs.GetStairways(); - - foreach (CabinDeck cabinDeck in CabinDecks) - { - if (cabinDeck.Equals(firstDeckWithStairs)) - { - continue; - } - - if (cabinDeck.Rows >= stairwayMapping.Max(x => x.Key.Row) && - cabinDeck.Columns >= stairwayMapping.Max(x => x.Key.Column)) - { - foreach (CabinSlot slot in cabinDeck.CabinSlots.Where(x => x.Type == CabinSlotType.Stairway)) - { - slot.Type = CabinSlotType.Aisle; - } - - foreach (var stairMap in stairwayMapping) - { - CabinSlot targetSlot = cabinDeck.CabinSlots - .FirstOrDefault(x => x.Row == stairMap.Key.Row && x.Column == stairMap.Key.Column); - - if (targetSlot != null) - { - targetSlot.Type = CabinSlotType.Stairway; - targetSlot.SlotIssues.ToggleIssue(CabinSlotIssueType.STAIRWAY, false); - autoFixResult.CountSuccess(); - } - else - { - autoFixResult.CountFail(); - } - } - } - }*/ - #endregion } else { @@ -927,6 +920,10 @@ public void RefreshProblemChecks() InvokePropertyChanged(nameof(StairwaysValid)); InvokePropertyChanged(nameof(DuplicateDoors)); InvokePropertyChanged(nameof(HasNoDuplicateDoors)); + InvokePropertyChanged(nameof(CateringDoorSurplus)); + InvokePropertyChanged(nameof(HasNoCateringDoorSurplus)); + InvokePropertyChanged(nameof(DoorSurplus)); + InvokePropertyChanged(nameof(HasNoDoorSurplus)); InvokePropertyChanged(nameof(MinorIssuesCountSum)); InvokePropertyChanged(nameof(HasMinorIssues)); @@ -942,6 +939,32 @@ public void RefreshProblemChecks() } } + public int GetFloorForCabinSlots(IEnumerable cabinSlots) + { + if (cabinSlots?.Count() == 0) + { + return 0; + } + + int targetFloor = 0; + foreach (CabinDeck cabinDeck in mCabinDecks) + { + if (cabinDeck.ContainsAnyCabinSlots(cabinSlots)) + { + if (targetFloor == 0) + { + targetFloor = cabinDeck.Floor; + } + else + { + return -1; + } + } + } + + return targetFloor; + } + public override string ToString() { return mLayoutName; @@ -951,6 +974,7 @@ protected virtual void OnCabinDeckCountChanged(CabinDeckChangedEventArgs e) { CabinDeckCountChanged?.Invoke(this, e); InvokePropertyChanged(nameof(HasMultipleDecks)); + InvokePropertyChanged(nameof(IsEmpty)); RefreshCapacities(); } diff --git a/SLC_LayoutEditor/Core/Cabin/Renderer/CabinDeckRenderer.cs b/SLC_LayoutEditor/Core/Cabin/Renderer/CabinDeckRenderer.cs index a144171..4a38981 100644 --- a/SLC_LayoutEditor/Core/Cabin/Renderer/CabinDeckRenderer.cs +++ b/SLC_LayoutEditor/Core/Cabin/Renderer/CabinDeckRenderer.cs @@ -466,7 +466,8 @@ public void CheckMouseClick(UIElement relativeControl, bool isMouseDown) slotHitResult.CabinSlot.IsSelected = !Util.IsControlDown(); slotHitResult.CabinSlot.IsDirty = true; RedrawCabinSlot(slotHitResult.CabinSlot, true); - OnSelectedSlotsChanged(new SelectedSlotsChangedEventArgs(slotHitResults.Select(x => x.CabinSlot).Where(x => x.IsSelected))); + OnSelectedSlotsChanged(new SelectedSlotsChangedEventArgs(!Util.IsControlDown() ? slotHitResult.CabinSlot : null, Util.IsControlDown() ? slotHitResult.CabinSlot : null)); + //OnSelectedSlotsChanged(new SelectedSlotsChangedEventArgs(slotHitResults.Select(x => x.CabinSlot).Where(x => x.IsSelected))); } } // The element is a button @@ -754,7 +755,7 @@ private Size UpdateBitmapSize(bool excludeBaseMargin = false, bool? refreshWidth return new Size(width, height); } - public void SelectSlots(IEnumerable targetSlots) + public void SelectSlots(IEnumerable targetSlots, bool fireEvent = true) { bool isSelected = !Util.IsControlDown(); @@ -765,12 +766,15 @@ public void SelectSlots(IEnumerable targetSlots) RedrawCabinSlot(targetSlot, false); } - OnSelectedSlotsChanged(new SelectedSlotsChangedEventArgs(slotHitResults.Select(x => x.CabinSlot).Where(x => x.IsSelected))); + if (fireEvent) + { + OnSelectedSlotsChanged(new SelectedSlotsChangedEventArgs(!Util.IsControlDown() ? targetSlots : null, Util.IsControlDown() ? targetSlots : null)); + } } - public void SelectAllSlots() + public void SelectAllSlots(bool fireEvent = true) { - SelectSlots(slotHitResults.Select(x => x.CabinSlot)); + SelectSlots(slotHitResults.Select(x => x.CabinSlot), fireEvent); } public void SelectSlotsInArea(Rect selectionRect) @@ -781,12 +785,12 @@ public void SelectSlotsInArea(Rect selectionRect) SelectSlots(targetSlots); } - public void DeselectAllSlots() + public void DeselectAllSlots(bool notify = true) { - DeselectSlots(slotHitResults.Where(x => x.CabinSlot.IsSelected).Select(x => x.CabinSlot), true); + DeselectSlots(slotHitResults.Where(x => x.CabinSlot.IsSelected).Select(x => x.CabinSlot), true, notify); } - private void DeselectSlots(IEnumerable selectedSlots, bool forceDeselect = false) + private void DeselectSlots(IEnumerable selectedSlots, bool forceDeselect = false, bool notify = true) { if (!Util.IsShiftDown() && !Util.IsControlDown()) // If no modifier keys are pressed, remove selection from all other selected slots { @@ -799,6 +803,11 @@ private void DeselectSlots(IEnumerable selectedSlots, bool forceDesel selectedSlot.IsSelected = false; RedrawCabinSlot(selectedSlot, false); } + + if (notify) + { + Mediator.Instance.NotifyColleagues(ViewModelMessage.DeselectOther_Deck, cabinDeck); + } } } diff --git a/SLC_LayoutEditor/Core/Events/SelectedSlotsChangedEventArgs.cs b/SLC_LayoutEditor/Core/Events/SelectedSlotsChangedEventArgs.cs index f1115d8..9cae3fe 100644 --- a/SLC_LayoutEditor/Core/Events/SelectedSlotsChangedEventArgs.cs +++ b/SLC_LayoutEditor/Core/Events/SelectedSlotsChangedEventArgs.cs @@ -8,23 +8,39 @@ namespace SLC_LayoutEditor.Core.Events { public class SelectedSlotsChangedEventArgs : EventArgs { - private readonly IEnumerable newSelection; + private readonly IEnumerable added; + private readonly IEnumerable removed; private readonly CabinDeckControl deckControl; private readonly int floor; + private readonly bool isNewSelection; - public IEnumerable NewSelection => newSelection; + public IEnumerable Added => added; + + public IEnumerable Removed => removed; public CabinDeckControl DeckControl => deckControl; public int Floor => floor; - public SelectedSlotsChangedEventArgs(IEnumerable newSelection) + public bool IsNewSelection => isNewSelection; + + public SelectedSlotsChangedEventArgs(IEnumerable added, IEnumerable removed) { - this.newSelection = newSelection; + this.added = added; + this.removed = removed; + + isNewSelection = !Util.IsControlDown() && !Util.IsShiftDown(); + } + + public SelectedSlotsChangedEventArgs(CabinSlot added, CabinSlot removed) : this( + added != null ? new List() { added } : null, + removed != null ? new List() { removed } : null) + { + } public SelectedSlotsChangedEventArgs(SelectedSlotsChangedEventArgs e, CabinDeckControl deckControl, - int floor) : this(e.NewSelection) + int floor) : this(e.Added, e.Removed) { this.deckControl = deckControl; this.floor = floor; diff --git a/SLC_LayoutEditor/Core/ExtensionMethods.cs b/SLC_LayoutEditor/Core/ExtensionMethods.cs index 56b0000..59e8904 100644 --- a/SLC_LayoutEditor/Core/ExtensionMethods.cs +++ b/SLC_LayoutEditor/Core/ExtensionMethods.cs @@ -138,6 +138,14 @@ public static Dictionary GetDiff(this IEnumerable ne return diff; } + public static IEnumerable Merge(this IEnumerable left, IEnumerable right) + { + List merged = new List(left); + merged.AddRange(right); + + return merged; + } + public static Size Modify(this Size size, double width, double height) { return new Size(size.Width + width, size.Height + height); diff --git a/SLC_LayoutEditor/Core/Memento/History.cs b/SLC_LayoutEditor/Core/Memento/History.cs index b62e7bb..9a5cfd3 100644 --- a/SLC_LayoutEditor/Core/Memento/History.cs +++ b/SLC_LayoutEditor/Core/Memento/History.cs @@ -1,10 +1,12 @@ -using System; +using SLC_LayoutEditor.ViewModel.Communication; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tasty.Logging; using Tasty.ViewModel; +using Tasty.ViewModel.Communication; namespace SLC_LayoutEditor.Core.Memento { @@ -252,6 +254,7 @@ protected virtual void OnHistoryChanged(HistoryChangedEventArgs e) return; } HistoryChanged?.Invoke(this, e); + Mediator.Instance.NotifyColleagues(ViewModelMessage.HistoryStepApplied); } protected virtual void OnHistoryChanging(EventArgs e) diff --git a/SLC_LayoutEditor/FixedValues.cs b/SLC_LayoutEditor/FixedValues.cs index e95d798..8cdbbef 100644 --- a/SLC_LayoutEditor/FixedValues.cs +++ b/SLC_LayoutEditor/FixedValues.cs @@ -54,6 +54,8 @@ class FixedValues internal static readonly string ICON_CHECK_CIRCLE = (string)App.Current.FindResource("CheckCircle"); internal static readonly string ICON_BACKUP_RESTORE = (string)App.Current.FindResource("BackupRestore"); internal static readonly string ICON_SAVE = (string)App.Current.FindResource("SaveConfirm"); + internal static readonly string ICON_AUTO_FIX = (string)App.Current.FindResource("AutoFix"); + internal static readonly string ICON_AUTO_FIX_ALERT = (string)App.Current.FindResource("AutoFixAlert"); internal static readonly string MAXIMIZE_ICON = (string)App.Current.FindResource("WindowMaximize"); internal static readonly string RESTORE_ICON = (string)App.Current.FindResource("WindowRestore"); diff --git a/SLC_LayoutEditor/Icons.xaml b/SLC_LayoutEditor/Icons.xaml index 2657653..0d96942 100644 --- a/SLC_LayoutEditor/Icons.xaml +++ b/SLC_LayoutEditor/Icons.xaml @@ -8,7 +8,9 @@ M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z M22.61,19L13.53,9.91C14.46,7.57 14,4.81 12.09,2.91C9.79,0.61 6.21,0.4 3.66,2.26L7.5,6.11L6.08,7.5L2.25,3.69C0.39,6.23 0.6,9.82 2.9,12.11C4.76,13.97 7.47,14.46 9.79,13.59L18.9,22.7C19.29,23.09 19.92,23.09 20.31,22.7L22.61,20.4C23,20 23,19.39 22.61,19M19.61,20.59L10.15,11.13C9.54,11.58 8.86,11.85 8.15,11.95C6.79,12.15 5.36,11.74 4.32,10.7C3.37,9.76 2.93,8.5 3,7.26L6.09,10.35L10.33,6.11L7.24,3C8.5,2.95 9.73,3.39 10.68,4.33C11.76,5.41 12.17,6.9 11.92,8.29C11.8,9 11.5,9.66 11.04,10.25L20.5,19.7L19.61,20.59Z - + M7.5,5.6L5,7L6.4,4.5L5,2L7.5,3.4L10,2L8.6,4.5L10,7L7.5,5.6M19.5,15.4L22,14L20.6,16.5L22,19L19.5,17.6L17,19L18.4,16.5L17,14L19.5,15.4M22,2L20.6,4.5L22,7L19.5,5.6L17,7L18.4,4.5L17,2L19.5,3.4L22,2M13.34,12.78L15.78,10.34L13.66,8.22L11.22,10.66L13.34,12.78M14.37,7.29L16.71,9.63C17.1,10 17.1,10.65 16.71,11.04L5.04,22.71C4.65,23.1 4,23.1 3.63,22.71L1.29,20.37C0.9,20 0.9,19.35 1.29,18.96L12.96,7.29C13.35,6.9 14,6.9 14.37,7.29Z + M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z + M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z M12.5,8C9.85,8 7.45,9 5.6,10.6L2,7V16H11L7.38,12.38C8.77,11.22 10.54,10.5 12.5,10.5C16.04,10.5 19.05,12.81 20.1,16L22.47,15.22C21.08,11.03 17.15,8 12.5,8Z @@ -67,4 +69,7 @@ M20,9V15H12V19.84L4.16,12L12,4.16V9H20Z M12 2C6.5 2 2 6.5 2 12S6.5 22 12 22 22 17.5 22 12 17.5 2 12 2M12 20C7.59 20 4 16.41 4 12S7.59 4 12 4 20 7.59 20 12 16.41 20 12 20M16.59 7.58L10 14.17L7.41 11.59L6 13L10 17L18 9L16.59 7.58Z + + M13,6V11H18V7.75L22.25,12L18,16.25V13H13V18H16.25L12,22.25L7.75,18H11V13H6V16.25L1.75,12L6,7.75V11H11V6H7.75L12,1.75L16.25,6H13Z + M13 9V1.07C13.7 1.16 14.37 1.33 15 1.59C17.33 2.53 19.11 4.53 19.75 7C19.91 7.64 20 8.31 20 9H13M17.66 7C17.18 5.65 16.23 4.5 15 3.81V7H17.66M6 15V13H18V15C18 16.59 17.37 18.12 16.24 19.24C15.12 20.37 13.59 21 12 21C10.41 21 8.88 20.37 7.76 19.24C6.63 18.12 6 16.59 6 15M4 15C4 17.12 4.84 19.16 6.34 20.66C7.84 22.16 9.88 23 12 23C14.12 23 16.16 22.16 17.66 20.66C19.16 19.16 20 17.12 20 15V11H4V15M11 9V1.07C7.06 1.56 4 4.92 4 9H11Z \ No newline at end of file diff --git a/SLC_LayoutEditor/KeybindsCheatSheet.xaml b/SLC_LayoutEditor/KeybindsCheatSheet.xaml index 3eb884e..2965069 100644 --- a/SLC_LayoutEditor/KeybindsCheatSheet.xaml +++ b/SLC_LayoutEditor/KeybindsCheatSheet.xaml @@ -6,7 +6,7 @@ xmlns:local="clr-namespace:SLC_LayoutEditor" xmlns:controls="clr-namespace:SLC_LayoutEditor.Controls" mc:Ignorable="d" WindowStyle="SingleBorderWindow" - Title="Keybinds cheat sheet" Width="640" Height="710" + Title="Keybinds cheat sheet" Width="650" Height="544" TextElement.Foreground="{DynamicResource ForegroundColorBrush}" Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource BackgroundLightBrush}" @@ -37,48 +37,114 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + diff --git a/SLC_LayoutEditor/MainWindow.xaml b/SLC_LayoutEditor/MainWindow.xaml index 12e46de..432b864 100644 --- a/SLC_LayoutEditor/MainWindow.xaml +++ b/SLC_LayoutEditor/MainWindow.xaml @@ -254,11 +254,11 @@ - - + diff --git a/SLC_LayoutEditor/Properties/AssemblyInfo.cs b/SLC_LayoutEditor/Properties/AssemblyInfo.cs index d988b8a..f58f605 100644 --- a/SLC_LayoutEditor/Properties/AssemblyInfo.cs +++ b/SLC_LayoutEditor/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.6.6.2")] -[assembly: AssemblyFileVersion("1.6.6.2")] +[assembly: AssemblyVersion("1.6.7.0")] +[assembly: AssemblyFileVersion("1.6.7.0")] diff --git a/SLC_LayoutEditor/Resources/patchnotes.txt b/SLC_LayoutEditor/Resources/patchnotes.txt index a2d002a..5e8edcc 100644 --- a/SLC_LayoutEditor/Resources/patchnotes.txt +++ b/SLC_LayoutEditor/Resources/patchnotes.txt @@ -1,4 +1,12 @@ -17.03.2024 -Changed: There is now a separate notification after a successful save +30.04.2024 m +Added: Actions like removing slots from your selection are now also explained in the keybind cheatsheet window +Added: Applying an autofix now also shows a notification containing information about the applied fix +Added: Implemented two new tracked issues: "Catering door count" and "Door count" +Added: There is now a separate notification after a successful save +Updated: You can now select and configure slots across multiple decks! +Updated: The keybind cheatsheet window has been cleaned up Updated: Replaced the "Save as" icon with a more fitting variant -Fixed: Fixed a bug where the state of the layout/template mode toggle would affect if your current layout or template is copied to the clipboard \ No newline at end of file +Fixed: The editor would crash when applying the door autofix, while having more than 9 doors present across your layout +Fixed: Fixed a bug, where the state of the layout/template mode toggle would affect your current layout or template being copied to the clipboard +Fixed: Using undo/redo didn't trigger the check for unsaved changes +Disabled: Temporarily disabled the keybind to select all slots on the current deck \ No newline at end of file diff --git a/SLC_LayoutEditor/SLC_LayoutEditor.csproj b/SLC_LayoutEditor/SLC_LayoutEditor.csproj index 8f3296a..20cded0 100644 --- a/SLC_LayoutEditor/SLC_LayoutEditor.csproj +++ b/SLC_LayoutEditor/SLC_LayoutEditor.csproj @@ -329,6 +329,7 @@ + @@ -502,6 +503,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/SLC_LayoutEditor/Themes/Style.xaml b/SLC_LayoutEditor/Themes/Style.xaml index 72d1607..2b7921f 100644 --- a/SLC_LayoutEditor/Themes/Style.xaml +++ b/SLC_LayoutEditor/Themes/Style.xaml @@ -11,6 +11,7 @@ + diff --git a/SLC_LayoutEditor/Themes/Styles/TabStyle.xaml b/SLC_LayoutEditor/Themes/Styles/TabStyle.xaml new file mode 100644 index 0000000..be8dcd0 --- /dev/null +++ b/SLC_LayoutEditor/Themes/Styles/TabStyle.xaml @@ -0,0 +1,153 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/SLC_LayoutEditor/UI/LayoutEditor.xaml b/SLC_LayoutEditor/UI/LayoutEditor.xaml index 0ecd95d..e14b0a6 100644 --- a/SLC_LayoutEditor/UI/LayoutEditor.xaml +++ b/SLC_LayoutEditor/UI/LayoutEditor.xaml @@ -155,7 +155,6 @@ TemplatingModeToggled="Layout_TemplatingModeToggled" TemplateCreated="Layout_TemplateCreated" LayoutReloaded="Layout_LayoutReloaded" - SelectedDeckChanged="Layout_SelectedDeckChanged" CabinDeckChanged="control_layout_CabinDeckChanged" GuideMenu="{StaticResource GuideMenu}" controls:GuideAssist.Title="{StaticResource GuideEditorAreaTitle}" diff --git a/SLC_LayoutEditor/UI/LayoutEditor.xaml.cs b/SLC_LayoutEditor/UI/LayoutEditor.xaml.cs index 645b4bb..537b230 100644 --- a/SLC_LayoutEditor/UI/LayoutEditor.xaml.cs +++ b/SLC_LayoutEditor/UI/LayoutEditor.xaml.cs @@ -41,7 +41,6 @@ public partial class LayoutEditor : Grid public event EventHandler CabinLayoutSelected; public event EventHandler Changed; public event EventHandler TourRunningStateChanged; - public event EventHandler SelectedDeckChanged; private readonly LayoutEditorViewModel vm; private Adorner sidebarToggleAdorner; @@ -85,7 +84,7 @@ public LayoutEditor() }, ViewModelMessage.Keybind_SaveLayout); } - public void DeselectSlots() + public void DeselectAllSlots() { control_layout.DeselectSlots(); } @@ -385,7 +384,7 @@ private void MultiSelect_SlotTypeSelectionChanged(object sender, SelectionChange if (!vm.IgnoreMultiSlotTypeChange && sender is ComboBox comboBox && comboBox.SelectedItem is CabinSlotType slotType) { vm.ActiveLayout.ToggleIssueChecking(false); - foreach (CabinSlot cabinSlot in control_layout.SelectedCabinSlots) + foreach (CabinSlot cabinSlot in vm.SelectedCabinSlots) { cabinSlot.Type = slotType; } @@ -466,8 +465,6 @@ private void Automate_Click(object sender, RoutedEventArgs e) } break; case AutomationMode.WallGenerator: // Wall generator - vm.SelectedCabinSlotFloor = vm.AutomationSelectedDeck.Floor; - IEnumerable wallSlots = vm.AutomationSelectedDeck.CabinSlots .Where(x => (x.Row == 0 || x.Column == 0 || x.Row == vm.AutomationSelectedDeck.Rows || x.Column == vm.AutomationSelectedDeck.Columns) && !x.IsDoor && x.Type != CabinSlotType.Wall && x.Type != CabinSlotType.Cockpit); @@ -933,27 +930,16 @@ private void Automation_SelectionChanged(object sender, SelectionChangedEventArg } } - private void Layout_SelectedDeckChanged(object sender, SelectedDeckChangedEventArgs e) - { - OnSelectedDeckChanged(e); - } - protected virtual void OnTourRunningStateChanged(EventArgs e) { TourRunningStateChanged?.Invoke(this, e); } - protected virtual void OnSelectedDeckChanged(SelectedDeckChangedEventArgs e) - { - SelectedDeckChanged?.Invoke(this, e); - } - private void CabinLayout_SelectedSlotsChanged(object sender, SelectedSlotsChangedEventArgs e) { - vm.SelectedCabinSlots = e.NewSelection.ToList(); - vm.SelectedCabinSlotFloor = e.Floor; + vm.ModifyCabinSlotSelection(e); - if (App.GuidedTour.IsAwaitingBorderSlotSelection && e.NewSelection.All(x => e.DeckControl.CabinDeck.IsSlotValidDoorPosition(x))) + if (App.GuidedTour.IsAwaitingBorderSlotSelection && vm.SelectedCabinSlots.All(x => e.DeckControl.CabinDeck.IsSlotValidDoorPosition(x))) { todoList.ForceCompleteEntry(0, true); App.GuidedTour.ContinueTour(true); diff --git a/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsCommand.cs b/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsCommand.cs index ce1efbd..edc8b33 100644 --- a/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsCommand.cs +++ b/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsCommand.cs @@ -1,13 +1,22 @@ -using System; +using SLC_LayoutEditor.ViewModel.Communication; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tasty.ViewModel.Commands; +using Tasty.ViewModel.Communication; namespace SLC_LayoutEditor.ViewModel.Commands { - internal class SelectAllSlotsCommand : CommandBase + internal class SelectAllSlotsCommand : LayoutBaseCommand { + public override void Execute(object parameter) + { + if (parameter is LayoutEditorViewModel vm) + { + Mediator.Instance.NotifyColleagues(ViewModelMessage.SelectAll_Layout); + } + } } } diff --git a/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsOnDeckCommand.cs b/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsOnDeckCommand.cs index 6f61b0b..cf2de4b 100644 --- a/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsOnDeckCommand.cs +++ b/SLC_LayoutEditor/ViewModel/Commands/SelectAllSlotsOnDeckCommand.cs @@ -11,13 +11,8 @@ namespace SLC_LayoutEditor.ViewModel.Commands { - internal class SelectAllSlotsOnDeckCommand : CommandBase + internal class SelectAllSlotsOnDeckCommand : LayoutBaseCommand { - public override bool CanExecute(object parameter) - { - return parameter is CabinDeckControl; - } - public override void Execute(object parameter) { if (parameter is CabinDeckControl targetControl) diff --git a/SLC_LayoutEditor/ViewModel/Communication/ViewModelMessage.cs b/SLC_LayoutEditor/ViewModel/Communication/ViewModelMessage.cs index 95a996b..cad93c1 100644 --- a/SLC_LayoutEditor/ViewModel/Communication/ViewModelMessage.cs +++ b/SLC_LayoutEditor/ViewModel/Communication/ViewModelMessage.cs @@ -28,6 +28,10 @@ public enum ViewModelMessage FinishLayoutChange, Layout_ToggleIssueChecking, BakedTemplate_Add, - BakedTemplate_Delete + BakedTemplate_Delete, + HistoryStepApplied, + SelectAll_Layout, + SelectAll_Deck, + DeselectOther_Deck } } diff --git a/SLC_LayoutEditor/ViewModel/DesignTime/KeybindInfoDesignControl.cs b/SLC_LayoutEditor/ViewModel/DesignTime/KeybindInfoDesignControl.cs new file mode 100644 index 0000000..bfc4d2f --- /dev/null +++ b/SLC_LayoutEditor/ViewModel/DesignTime/KeybindInfoDesignControl.cs @@ -0,0 +1,16 @@ +using SLC_LayoutEditor.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SLC_LayoutEditor.ViewModel.DesignTime +{ + internal class KeybindInfoDesignControl : KeybindInfo + { + public new string Keybind => "Shift"; + public new string Title => "Test title"; + public new string Notes => "This is a test note, do be afraid"; + } +} diff --git a/SLC_LayoutEditor/ViewModel/LayoutEditorViewModel.cs b/SLC_LayoutEditor/ViewModel/LayoutEditorViewModel.cs index ef93dda..49b5ef8 100644 --- a/SLC_LayoutEditor/ViewModel/LayoutEditorViewModel.cs +++ b/SLC_LayoutEditor/ViewModel/LayoutEditorViewModel.cs @@ -58,7 +58,6 @@ class LayoutEditorViewModel : ViewModelBase private bool mHasSeatNumberInputError; private List mSelectedCabinSlots = new List(); - private int mSelectedCabinSlotFloor; private int mSelectedMultiSlotTypeIndex = -1; private int mSelectedAutomationIndex = -1; @@ -250,27 +249,7 @@ public List SelectedCabinSlots { mSelectedCabinSlots = value; InvokePropertyChanged(); - InvokePropertyChanged(nameof(IsSingleCabinSlotSelected)); - InvokePropertyChanged(nameof(SelectedCabinSlot)); - - if (value.Count <= 1) - { - InvokePropertyChanged(nameof(SelectedCabinSlotTypeId)); - } - - IgnoreMultiSlotTypeChange = true; - if (value?.Count > 0) { - int checkType = value.First().TypeId; - SelectedMultiSlotTypeIndex = value.All(x => x.TypeId == checkType) ? checkType : -1; - } - else - { - SelectedMultiSlotTypeIndex = -1; - } - IgnoreMultiSlotTypeChange = false; - InvokePropertyChanged(nameof(ShowSelectedCabinSlotDetails)); - InvokePropertyChanged(nameof(RequiredLettersForAutomation)); - InvokePropertyChanged(nameof(SeatLettersError)); + UpdateSelectedCabinSlots(); } } @@ -301,30 +280,25 @@ public int SelectedCabinSlotTypeId public bool ShowSelectedCabinSlotDetails => SelectedCabinSlot != null && IsSingleCabinSlotSelected && !IsAutomationChecked; - public int SelectedCabinSlotFloor - { - get => mSelectedCabinSlotFloor; - set - { - mSelectedCabinSlotFloor = value; - InvokePropertyChanged(); - InvokePropertyChanged(nameof(SelectedFloorText)); - } - } + public int SelectedCabinSlotFloor => ActiveLayout?.GetFloorForCabinSlots(mSelectedCabinSlots) ?? -1; public string SelectedFloorText { get { - switch (mSelectedCabinSlotFloor) + int targetFloor = SelectedCabinSlotFloor; + + switch (targetFloor) { + case -1: + return "multiple decks"; case 1: return "Lower deck"; case 2: return "Upper deck"; default: string suffix; - switch (int.Parse(mSelectedCabinSlotFloor.ToString().LastOrDefault().ToString())) + switch (int.Parse(targetFloor.ToString().LastOrDefault().ToString())) { case 1: suffix = "st"; @@ -340,7 +314,7 @@ public string SelectedFloorText break; } - return string.Format("{0}{1} deck", mSelectedCabinSlotFloor, suffix); + return string.Format("{0}{1} deck", targetFloor, suffix); } } } @@ -665,6 +639,11 @@ public LayoutEditorViewModel() } } }, ViewModelMessage.BakedTemplate_Delete); + + Mediator.Instance.Register(o => + { + RefreshUnsavedChanges(); + }, ViewModelMessage.HistoryStepApplied); } private void EditLayoutName_DialogClosing(object sender, DialogClosingEventArgs e) @@ -677,6 +656,30 @@ private void EditLayoutName_DialogClosing(object sender, DialogClosingEventArgs } } + public void ModifyCabinSlotSelection(SelectedSlotsChangedEventArgs e) + { + if (e.IsNewSelection) + { + SelectedCabinSlots = e.Added.ToList(); + } + else if (e.Added != null) + { + SelectedCabinSlots.AddRangeDistinct(e.Added); + InvokePropertyChanged(nameof(SelectedCabinSlots)); + UpdateSelectedCabinSlots(); + } + else if (e.Removed != null) + { + foreach (CabinSlot removed in e.Removed) + { + SelectedCabinSlots.Remove(removed); + } + + InvokePropertyChanged(nameof(SelectedCabinSlots)); + UpdateSelectedCabinSlots(); + } + } + public void RefreshUnsavedChanges() { OnChanged(new ChangedEventArgs( @@ -712,6 +715,34 @@ public void ClearSelection() InvokePropertyChanged(nameof(ShowSelectedCabinSlotDetails)); } + private void UpdateSelectedCabinSlots() + { + InvokePropertyChanged(nameof(IsSingleCabinSlotSelected)); + InvokePropertyChanged(nameof(SelectedCabinSlot)); + + if (mSelectedCabinSlots.Count <= 1) + { + InvokePropertyChanged(nameof(SelectedCabinSlotTypeId)); + } + + IgnoreMultiSlotTypeChange = true; + if (mSelectedCabinSlots?.Count > 0) + { + int checkType = mSelectedCabinSlots.First().TypeId; + SelectedMultiSlotTypeIndex = mSelectedCabinSlots.All(x => x.TypeId == checkType) ? checkType : -1; + } + else + { + SelectedMultiSlotTypeIndex = -1; + } + IgnoreMultiSlotTypeChange = false; + InvokePropertyChanged(nameof(ShowSelectedCabinSlotDetails)); + InvokePropertyChanged(nameof(RequiredLettersForAutomation)); + InvokePropertyChanged(nameof(SeatLettersError)); + InvokePropertyChanged(nameof(SelectedCabinSlotFloor)); + InvokePropertyChanged(nameof(SelectedFloorText)); + } + private void LayoutSets_CollectionUpdated(object sender, Tasty.ViewModel.Core.Events.CollectionUpdatedEventArgs e) { InvokePropertyChanged(nameof(LayoutSets)); diff --git a/SLC_LayoutEditor/ViewModel/MainViewModel.cs b/SLC_LayoutEditor/ViewModel/MainViewModel.cs index de44574..b18ff72 100644 --- a/SLC_LayoutEditor/ViewModel/MainViewModel.cs +++ b/SLC_LayoutEditor/ViewModel/MainViewModel.cs @@ -40,8 +40,6 @@ class MainViewModel : MementoViewModel private bool mIsMaximized; private bool mIsGuideOpen; - private CabinDeckControl mSelectedDeck; - private bool mIsSearching; #region Commands @@ -223,14 +221,13 @@ public FrameworkElement Content { if (newValue == null) { - this.editor.DeselectSlots(); + this.editor.DeselectAllSlots(); } this.editor = oldEditor; oldEditor.CabinLayoutSelected -= Editor_CabinLayoutSelected; oldEditor.Changed -= Editor_LayoutChanged; oldEditor.TourRunningStateChanged -= Editor_TourRunningStateChanged; - oldEditor.SelectedDeckChanged -= Editor_SelectedDeckChanged; } mContent = value; @@ -240,7 +237,6 @@ public FrameworkElement Content newValue.CabinLayoutSelected += Editor_CabinLayoutSelected; newValue.Changed += Editor_LayoutChanged; newValue.TourRunningStateChanged += Editor_TourRunningStateChanged; - newValue.SelectedDeckChanged += Editor_SelectedDeckChanged; } InvokePropertyChanged(); @@ -252,16 +248,6 @@ public FrameworkElement Content public bool IsLayoutOpened => EditorViewModel?.ActiveLayout != null; - public CabinDeckControl SelectedDeck - { - get => mSelectedDeck; - set - { - mSelectedDeck = value; - InvokePropertyChanged(); - } - } - public bool AllowHistoryCommands => !IsViewNotEditor && !IsDialogOpen && !mIsGuideOpen; public bool IsViewNotEditor => !(mContent is LayoutEditor) && App.Settings.WelcomeScreenShown; @@ -372,7 +358,7 @@ public void ShowChangelog() public void ShowChangelogIfUpdated() { - if (App.Settings.LastVersionChangelogShown < App.Patcher.VersionData.VersionNumber && + if (App.Settings.LastVersionChangelogShown != App.Patcher.VersionData.VersionNumber && App.Settings.ShowChangesAfterUpdate) { ShowChangelog(); @@ -432,17 +418,11 @@ private LayoutEditor GetEditor() editor.CabinLayoutSelected += Editor_CabinLayoutSelected; editor.Changed += Editor_LayoutChanged; editor.TourRunningStateChanged += Editor_TourRunningStateChanged; - editor.SelectedDeckChanged += Editor_SelectedDeckChanged; InvokePropertyChanged(nameof(EditorViewModel)); return editor; } - private void Editor_SelectedDeckChanged(object sender, SelectedDeckChangedEventArgs e) - { - SelectedDeck = e.NewValue; - } - private void Welcome_WelcomeConfirmed(object sender, EventArgs e) { if (mContent is WelcomeScreen welcome)