diff --git a/src/LiveSplit.Subsplits/UI/ColumnType.cs b/src/LiveSplit.Subsplits/UI/ColumnType.cs index 07def45..9ea1e6b 100644 --- a/src/LiveSplit.Subsplits/UI/ColumnType.cs +++ b/src/LiveSplit.Subsplits/UI/ColumnType.cs @@ -2,5 +2,5 @@ public enum ColumnType { - Delta, SplitTime, DeltaorSplitTime, SegmentDelta, SegmentTime, SegmentDeltaorSegmentTime + Delta, SplitTime, DeltaorSplitTime, SegmentDelta, SegmentTime, SegmentDeltaorSegmentTime, CustomVariable } diff --git a/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.Designer.cs b/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.Designer.cs index 5c3a4d7..36aab24 100644 --- a/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.Designer.cs +++ b/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.Designer.cs @@ -137,7 +137,8 @@ private void InitializeComponent() "Delta or Split Time", "Segment Delta", "Segment Time", - "Segment Delta or Segment Time"}); + "Segment Delta or Segment Time", + "Custom Variable"}); this.cmbColumnType.Location = new System.Drawing.Point(93, 33); this.cmbColumnType.Name = "cmbColumnType"; this.cmbColumnType.Size = new System.Drawing.Size(325, 21); @@ -247,4 +248,4 @@ private void InitializeComponent() private System.Windows.Forms.Button btnMoveDown; private System.Windows.Forms.Button btnMoveUp; } -} \ No newline at end of file +} diff --git a/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.cs b/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.cs index deda8ef..a33cb0b 100644 --- a/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.cs +++ b/src/LiveSplit.Subsplits/UI/Components/ColumnSettings.cs @@ -131,10 +131,18 @@ private static string GetColumnType(ColumnType type) { return "Segment Delta"; } - else + else if (type == ColumnType.SegmentDeltaorSegmentTime) { return "Segment Delta or Segment Time"; } + else if (type == ColumnType.CustomVariable) + { + return "Custom Variable"; + } + else + { + return "Unknown"; + } } private static ColumnType ParseColumnType(string columnType) diff --git a/src/LiveSplit.Subsplits/UI/Components/LabelsComponent.cs b/src/LiveSplit.Subsplits/UI/Components/LabelsComponent.cs index 0c2bf04..8e85b2a 100644 --- a/src/LiveSplit.Subsplits/UI/Components/LabelsComponent.cs +++ b/src/LiveSplit.Subsplits/UI/Components/LabelsComponent.cs @@ -5,7 +5,6 @@ using System.Windows.Forms; using LiveSplit.Model; -using LiveSplit.TimeFormatters; namespace LiveSplit.UI.Components; @@ -13,22 +12,13 @@ public class LabelsComponent : IComponent { public SplitsSettings Settings { get; set; } - protected SimpleLabel MeasureTimeLabel { get; set; } - protected SimpleLabel MeasureDeltaLabel { get; set; } - - protected ITimeFormatter TimeFormatter { get; set; } - protected ITimeFormatter DeltaTimeFormatter { get; set; } - - protected TimeAccuracy CurrentAccuracy { get; set; } - protected TimeAccuracy CurrentDeltaAccuracy { get; set; } - protected bool CurrentDropDecimals { get; set; } - protected int FrameCount { get; set; } public GraphicsCache Cache { get; set; } public IEnumerable ColumnsList { get; set; } public IList LabelsList { get; set; } + protected List<(int exLength, float exWidth, float width)> ColumnWidths { get; } public float PaddingTop => 0f; public float PaddingLeft => 0f; @@ -44,19 +34,15 @@ public class LabelsComponent : IComponent public float MinimumHeight { get; set; } public IDictionary ContextMenuControls => null; - public LabelsComponent(SplitsSettings settings, IEnumerable columns) + public LabelsComponent(SplitsSettings settings, IEnumerable columns, List<(int exLength, float exWidth, float width)> columnWidths) { Settings = settings; MinimumHeight = 31; - MeasureTimeLabel = new SimpleLabel(); - MeasureDeltaLabel = new SimpleLabel(); - TimeFormatter = new SplitTimeFormatter(Settings.SplitTimesAccuracy); - DeltaTimeFormatter = new DeltaSplitTimeFormatter(Settings.DeltasAccuracy, Settings.DropDecimals); - Cache = new GraphicsCache(); LabelsList = []; ColumnsList = columns; + ColumnWidths = columnWidths; } private void DrawGeneral(Graphics g, LiveSplitState state, float width, float height, LayoutMode mode) @@ -68,30 +54,6 @@ private void DrawGeneral(Graphics g, LiveSplitState state, float width, float he ), 0, 0, width, height); } - MeasureTimeLabel.Text = TimeFormatter.Format(new TimeSpan(24, 0, 0)); - MeasureDeltaLabel.Text = DeltaTimeFormatter.Format(new TimeSpan(0, 9, 0, 0)); - - MeasureTimeLabel.Font = state.LayoutSettings.TimesFont; - MeasureTimeLabel.IsMonospaced = true; - MeasureDeltaLabel.Font = state.LayoutSettings.TimesFont; - MeasureDeltaLabel.IsMonospaced = true; - - MeasureTimeLabel.SetActualWidth(g); - MeasureDeltaLabel.SetActualWidth(g); - - if (Settings.SplitTimesAccuracy != CurrentAccuracy) - { - TimeFormatter = new SplitTimeFormatter(Settings.SplitTimesAccuracy); - CurrentAccuracy = Settings.SplitTimesAccuracy; - } - - if (Settings.DeltasAccuracy != CurrentDeltaAccuracy || Settings.DropDecimals != CurrentDropDecimals) - { - DeltaTimeFormatter = new DeltaSplitTimeFormatter(Settings.DeltasAccuracy, Settings.DropDecimals); - CurrentDeltaAccuracy = Settings.DeltasAccuracy; - CurrentDropDecimals = Settings.DropDecimals; - } - foreach (SimpleLabel label in LabelsList) { label.ShadowColor = state.LayoutSettings.ShadowsColor; @@ -104,24 +66,15 @@ private void DrawGeneral(Graphics g, LiveSplitState state, float width, float he if (ColumnsList.Count() == LabelsList.Count) { + while (ColumnWidths.Count < LabelsList.Count) + { + ColumnWidths.Add((0, 0f, 0f)); + } + float curX = width - 7; foreach (SimpleLabel label in LabelsList.Reverse()) { - ColumnData column = ColumnsList.ElementAt(LabelsList.IndexOf(label)); - - float labelWidth = 0f; - if (column.Type is ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime) - { - labelWidth = Math.Max(MeasureDeltaLabel.ActualWidth, MeasureTimeLabel.ActualWidth); - } - else if (column.Type is ColumnType.Delta or ColumnType.SegmentDelta) - { - labelWidth = MeasureDeltaLabel.ActualWidth; - } - else - { - labelWidth = MeasureTimeLabel.ActualWidth; - } + float labelWidth = ColumnWidths[LabelsList.IndexOf(label)].width; curX -= labelWidth + 5; label.Width = labelWidth; @@ -203,9 +156,14 @@ public void Update(IInvalidator invalidator, LiveSplitState state, float width, Cache.Restart(); Cache["ColumnsCount"] = ColumnsList.Count(); - foreach (SimpleLabel label in LabelsList) + for (int index = 0; index < LabelsList.Count; index++) { - Cache["Columns" + LabelsList.IndexOf(label) + "Text"] = label.Text; + SimpleLabel label = LabelsList[index]; + Cache["Columns" + index + "Text"] = label.Text; + if (index < ColumnWidths.Count) + { + Cache["Columns" + index + "Width"] = ColumnWidths[index].width; + } } if (invalidator != null && (Cache.HasChanged || FrameCount > 1)) diff --git a/src/LiveSplit.Subsplits/UI/Components/SplitComponent.cs b/src/LiveSplit.Subsplits/UI/Components/SplitComponent.cs index ac5b369..259e712 100644 --- a/src/LiveSplit.Subsplits/UI/Components/SplitComponent.cs +++ b/src/LiveSplit.Subsplits/UI/Components/SplitComponent.cs @@ -27,8 +27,6 @@ public class SplitComponent : IComponent protected SimpleLabel NameLabel { get; set; } protected SimpleLabel TimeLabel { get; set; } - protected SimpleLabel MeasureTimeLabel { get; set; } - protected SimpleLabel MeasureDeltaLabel { get; set; } protected SimpleLabel HeaderMeasureTimeLabel { get; set; } protected SimpleLabel HeaderMeasureDeltaLabel { get; set; } protected SimpleLabel DeltaLabel { get; set; } @@ -67,6 +65,7 @@ public class SplitComponent : IComponent public IEnumerable ColumnsList { get; set; } public IList LabelsList { get; set; } + protected List<(int exLength, float exWidth, float width)> ColumnWidths { get; } private readonly Regex SubsplitRegex = new(@"^{(.+)}\s*(.+)$", RegexOptions.Compiled); @@ -81,7 +80,7 @@ public float HorizontalWidth public IDictionary ContextMenuControls => null; - public SplitComponent(SplitsSettings settings, IEnumerable columnsList) + public SplitComponent(SplitsSettings settings, IEnumerable columnsList, List<(int exLength, float exWidth, float width)> columnWidths) { NameLabel = new SimpleLabel() { @@ -96,7 +95,6 @@ public SplitComponent(SplitsSettings settings, IEnumerable columnsLi Y = 3, Text = "" }; - MeasureTimeLabel = new SimpleLabel(); HeaderMeasureTimeLabel = new SimpleLabel(); DeltaLabel = new SimpleLabel() { @@ -104,10 +102,10 @@ public SplitComponent(SplitsSettings settings, IEnumerable columnsLi Y = 3, Text = "" }; - MeasureDeltaLabel = new SimpleLabel(); HeaderMeasureDeltaLabel = new SimpleLabel(); Settings = settings; ColumnsList = columnsList; + ColumnWidths = columnWidths; TimeFormatter = new SplitTimeFormatter(Settings.SplitTimesAccuracy); DeltaTimeFormatter = new DeltaSplitTimeFormatter(Settings.DeltasAccuracy, Settings.DropDecimals); HeaderTimesFormatter = new SplitTimeFormatter(Settings.HeaderAccuracy); @@ -124,22 +122,14 @@ public SplitComponent(SplitsSettings settings, IEnumerable columnsLi private void SetMeasureLabels(Graphics g, LiveSplitState state) { - MeasureTimeLabel.Text = TimeFormatter.Format(new TimeSpan(24, 0, 0)); - MeasureDeltaLabel.Text = DeltaTimeFormatter.Format(new TimeSpan(0, 9, 0, 0)); HeaderMeasureTimeLabel.Text = HeaderTimesFormatter.Format(new TimeSpan(24, 0, 0)); HeaderMeasureDeltaLabel.Text = SectionTimerFormatter.Format(new TimeSpan(0, 9, 0, 0)); - MeasureTimeLabel.Font = state.LayoutSettings.TimesFont; - MeasureTimeLabel.IsMonospaced = true; - MeasureDeltaLabel.Font = state.LayoutSettings.TimesFont; - MeasureDeltaLabel.IsMonospaced = true; HeaderMeasureTimeLabel.Font = state.LayoutSettings.TimesFont; HeaderMeasureTimeLabel.IsMonospaced = true; HeaderMeasureDeltaLabel.Font = state.LayoutSettings.TimesFont; HeaderMeasureDeltaLabel.IsMonospaced = true; - MeasureTimeLabel.SetActualWidth(g); - MeasureDeltaLabel.SetActualWidth(g); HeaderMeasureTimeLabel.SetActualWidth(g); HeaderMeasureDeltaLabel.SetActualWidth(g); } @@ -314,25 +304,17 @@ private void DrawGeneral(Graphics g, LiveSplitState state, float width, float he if (ColumnsList.Count() == LabelsList.Count) { + while (ColumnWidths.Count < LabelsList.Count) + { + ColumnWidths.Add((0, 0f, 0f)); + } + float curX = width - 7; float nameX = width - 7; foreach (SimpleLabel label in LabelsList.Reverse()) { - ColumnData column = ColumnsList.ElementAt(LabelsList.IndexOf(label)); - - float labelWidth = 0f; - if (column.Type is ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime) - { - labelWidth = Math.Max(MeasureDeltaLabel.ActualWidth, MeasureTimeLabel.ActualWidth); - } - else if (column.Type is ColumnType.Delta or ColumnType.SegmentDelta) - { - labelWidth = MeasureDeltaLabel.ActualWidth; - } - else - { - labelWidth = MeasureTimeLabel.ActualWidth; - } + int i = LabelsList.IndexOf(label); + float labelWidth = ColumnWidths[i].width; label.Width = labelWidth + 20; curX -= labelWidth + 5; @@ -346,6 +328,10 @@ private void DrawGeneral(Graphics g, LiveSplitState state, float width, float he if (!string.IsNullOrEmpty(label.Text)) { nameX = curX + labelWidth + 5 - label.ActualWidth; + if (ColumnWidths[i].exWidth < label.ActualWidth) + { + ColumnWidths[i] = (label.Text.Length, label.ActualWidth, labelWidth); + } } } @@ -864,7 +850,7 @@ protected void UpdateColumn(LiveSplitState state, SimpleLabel label, ColumnData int splitIndex = state.Run.IndexOf(Split); if (splitIndex < state.CurrentSplitIndex) { - if (type is ColumnType.SplitTime or ColumnType.SegmentTime) + if (type is ColumnType.SplitTime or ColumnType.SegmentTime or ColumnType.CustomVariable) { label.ForeColor = Settings.OverrideTimesColor ? Settings.BeforeTimesColor : state.LayoutSettings.TextColor; @@ -872,11 +858,16 @@ protected void UpdateColumn(LiveSplitState state, SimpleLabel label, ColumnData { label.Text = TimeFormatter.Format(Split.SplitTime[timingMethod]); } - else //SegmentTime + else if (type == ColumnType.SegmentTime) { TimeSpan? segmentTime = LiveSplitStateHelper.GetPreviousSegmentTime(state, splitIndex, timingMethod); label.Text = TimeFormatter.Format(segmentTime); } + else if (type == ColumnType.CustomVariable) + { + Split.CustomVariableValues.TryGetValue(data.Name, out string text); + label.Text = text ?? ""; + } } if (type is ColumnType.DeltaorSplitTime or ColumnType.Delta) @@ -938,7 +929,7 @@ protected void UpdateColumn(LiveSplitState state, SimpleLabel label, ColumnData } else { - if (type is ColumnType.SplitTime or ColumnType.SegmentTime or ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime) + if (type is ColumnType.SplitTime or ColumnType.SegmentTime or ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime or ColumnType.CustomVariable) { if (IsActive) { @@ -953,7 +944,7 @@ protected void UpdateColumn(LiveSplitState state, SimpleLabel label, ColumnData { label.Text = TimeFormatter.Format(Split.Comparisons[comparison][timingMethod]); } - else //SegmentTime or SegmentTimeorSegmentDeltaTime + else if (type is ColumnType.SegmentTime or ColumnType.SegmentDeltaorSegmentTime) { TimeSpan previousTime = TimeSpan.Zero; for (int index = splitIndex - 1; index >= 0; index--) @@ -968,6 +959,17 @@ protected void UpdateColumn(LiveSplitState state, SimpleLabel label, ColumnData label.Text = TimeFormatter.Format(Split.Comparisons[comparison][timingMethod] - previousTime); } + else if (type is ColumnType.CustomVariable) + { + if (splitIndex == state.CurrentSplitIndex) + { + label.Text = state.Run.Metadata.CustomVariableValue(data.Name) ?? ""; + } + else if (splitIndex > state.CurrentSplitIndex) + { + label.Text = ""; + } + } } //Live Delta @@ -1031,7 +1033,7 @@ protected void UpdateCollapsedColumn(LiveSplitState state, SimpleLabel label, Co int splitIndex = state.Run.IndexOf(Split); if (splitIndex < state.CurrentSplitIndex) { - if (type is ColumnType.SplitTime or ColumnType.SegmentTime) + if (type is ColumnType.SplitTime or ColumnType.SegmentTime or ColumnType.CustomVariable) { label.ForeColor = Settings.OverrideTimesColor ? Settings.BeforeTimesColor : state.LayoutSettings.TextColor; @@ -1039,11 +1041,16 @@ protected void UpdateCollapsedColumn(LiveSplitState state, SimpleLabel label, Co { label.Text = TimeFormatter.Format(Split.SplitTime[timingMethod]); } - else //SegmentTime + else if (type == ColumnType.SegmentTime) { TimeSpan? segmentTime = getSectionTime(state, splitIndex, TopSplit, comparison, timingMethod); label.Text = TimeFormatter.Format(segmentTime); } + else if (type == ColumnType.CustomVariable) + { + Split.CustomVariableValues.TryGetValue(data.Name, out string text); + label.Text = text ?? ""; + } } if (type is ColumnType.DeltaorSplitTime or ColumnType.Delta) @@ -1107,7 +1114,7 @@ protected void UpdateCollapsedColumn(LiveSplitState state, SimpleLabel label, Co } else { - if (type is ColumnType.SplitTime or ColumnType.SegmentTime or ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime) + if (type is ColumnType.SplitTime or ColumnType.SegmentTime or ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime or ColumnType.CustomVariable) { if (IsActive) { @@ -1122,11 +1129,22 @@ protected void UpdateCollapsedColumn(LiveSplitState state, SimpleLabel label, Co { label.Text = TimeFormatter.Format(Split.Comparisons[comparison][timingMethod]); } - else //SegmentTime or SegmentTimeorSegmentDeltaTime + else if (type is ColumnType.SegmentTime or ColumnType.SegmentDeltaorSegmentTime) { TimeSpan? previousTime = TopSplit > 0 ? state.Run[TopSplit - 1].Comparisons[comparison][timingMethod] : TimeSpan.Zero; label.Text = TimeFormatter.Format(Split.Comparisons[comparison][timingMethod] - previousTime); } + else if (type is ColumnType.CustomVariable) + { + if (splitIndex == state.CurrentSplitIndex) + { + label.Text = state.Run.Metadata.CustomVariableValue(data.Name) ?? ""; + } + else if (splitIndex > state.CurrentSplitIndex) + { + label.Text = ""; + } + } } //Live Delta @@ -1164,14 +1182,9 @@ protected float CalculateHeaderWidth() protected float CalculateLabelsWidth() { - if (ColumnsList != null) + if (ColumnWidths != null) { - int mixedCount = ColumnsList.Count(x => x.Type is ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime); - int deltaCount = ColumnsList.Count(x => x.Type is ColumnType.Delta or ColumnType.SegmentDelta); - int timeCount = ColumnsList.Count(x => x.Type is ColumnType.SplitTime or ColumnType.SegmentTime); - return (mixedCount * (Math.Max(MeasureDeltaLabel.ActualWidth, MeasureTimeLabel.ActualWidth) + 5)) - + (deltaCount * (MeasureDeltaLabel.ActualWidth + 5)) - + (timeCount * (MeasureTimeLabel.ActualWidth + 5)); + return ColumnWidths.Sum(e => e.width) + (5 * ColumnWidths.Count()); } return 0f; @@ -1229,10 +1242,12 @@ public void Update(IInvalidator invalidator, LiveSplitState state, float width, SimpleLabel label = LabelsList[index]; Cache["Columns" + index + "Text"] = label.Text; Cache["Columns" + index + "Color"] = label.ForeColor.ToArgb(); + if (index < ColumnWidths.Count) + { + Cache["Columns" + index + "Width"] = ColumnWidths[index].width; + } } - Cache["MeasureTimeActualWidth"] = MeasureTimeLabel.ActualWidth; - Cache["MeasureDeltaActualWidth"] = MeasureDeltaLabel.ActualWidth; Cache["HeaderMeasureTimeActualWidth"] = HeaderMeasureTimeLabel.ActualWidth; Cache["HeaderMeasureDeltaActualWidth"] = HeaderMeasureDeltaLabel.ActualWidth; Cache["Header"] = Header; diff --git a/src/LiveSplit.Subsplits/UI/Components/SplitsComponent.cs b/src/LiveSplit.Subsplits/UI/Components/SplitsComponent.cs index 9e30f06..e622b6e 100644 --- a/src/LiveSplit.Subsplits/UI/Components/SplitsComponent.cs +++ b/src/LiveSplit.Subsplits/UI/Components/SplitsComponent.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using LiveSplit.Model; +using LiveSplit.TimeFormatters; namespace LiveSplit.UI.Components; @@ -23,6 +24,17 @@ public class SplitsComponent : IComponent protected SplitsSettings Settings { get; set; } + protected SimpleLabel MeasureTimeLabel { get; set; } + protected SimpleLabel MeasureDeltaLabel { get; set; } + protected SimpleLabel MeasureCharLabel { get; set; } + + protected TimeAccuracy CurrentAccuracy { get; set; } + protected TimeAccuracy CurrentDeltaAccuracy { get; set; } + protected bool CurrentDropDecimals { get; set; } + + protected ITimeFormatter TimeFormatter { get; set; } + protected ITimeFormatter DeltaTimeFormatter { get; set; } + private Dictionary ShadowImages { get; set; } private int visualSplitCount; @@ -42,6 +54,7 @@ public class SplitsComponent : IComponent protected Color OldShadowsColor { get; set; } protected IEnumerable ColumnsList => Settings.ColumnsList.Select(x => x.Data); + protected List<(int exLength, float exWidth, float width)> ColumnWidths { get; set; } public string ComponentName => "Subsplits"; @@ -61,9 +74,20 @@ public SplitsComponent(LiveSplitState state) CurrentState = state; Settings = new SplitsSettings(state); InternalComponent = new ComponentRendererComponent(); + + MeasureTimeLabel = new SimpleLabel(); + MeasureDeltaLabel = new SimpleLabel(); + MeasureCharLabel = new SimpleLabel(); + CurrentAccuracy = Settings.SplitTimesAccuracy; + CurrentDeltaAccuracy = Settings.DeltasAccuracy; + CurrentDropDecimals = Settings.DropDecimals; + TimeFormatter = new SplitTimeFormatter(CurrentAccuracy); + DeltaTimeFormatter = new DeltaSplitTimeFormatter(CurrentDeltaAccuracy, CurrentDropDecimals); + ShadowImages = []; visualSplitCount = Settings.VisualSplitCount; Settings.SplitLayoutChanged += Settings_SplitLayoutChanged; + ColumnWidths = Settings.ColumnsList.Select(_ => (0, 0f, 0f)).ToList(); ScrollOffset = 0; RebuildVisualSplits(); sectionList = new SectionList(); @@ -102,7 +126,7 @@ private void RebuildVisualSplits() if (Settings.ShowColumnLabels && CurrentState.Layout?.Mode == LayoutMode.Vertical) { - Components.Add(new LabelsComponent(Settings, ColumnsList)); + Components.Add(new LabelsComponent(Settings, ColumnsList, ColumnWidths)); Components.Add(new SeparatorComponent()); } @@ -121,7 +145,7 @@ private void RebuildVisualSplits() } } - var splitComponent = new SplitComponent(Settings, ColumnsList); + var splitComponent = new SplitComponent(Settings, ColumnsList, ColumnWidths); Components.Add(splitComponent); SplitComponents.Add(splitComponent); @@ -148,6 +172,19 @@ private void Prepare(LiveSplitState state) OldState = state; } + if (Settings.SplitTimesAccuracy != CurrentAccuracy) + { + TimeFormatter = new SplitTimeFormatter(Settings.SplitTimesAccuracy); + CurrentAccuracy = Settings.SplitTimesAccuracy; + } + + if (Settings.DeltasAccuracy != CurrentDeltaAccuracy || Settings.DropDecimals != CurrentDropDecimals) + { + DeltaTimeFormatter = new DeltaSplitTimeFormatter(Settings.DeltasAccuracy, Settings.DropDecimals); + CurrentDeltaAccuracy = Settings.DeltasAccuracy; + CurrentDropDecimals = Settings.DropDecimals; + } + if (Settings.VisualSplitCount != visualSplitCount || Settings.ShowColumnLabels != PreviousShowLabels || (Settings.ShowColumnLabels && state.Layout.Mode != OldLayoutMode)) @@ -368,10 +405,29 @@ private void DrawBackground(Graphics g, float width, float height) } } + private void SetMeasureLabels(Graphics g, LiveSplitState state) + { + MeasureTimeLabel.Text = TimeFormatter.Format(new TimeSpan(24, 0, 0)); + MeasureDeltaLabel.Text = DeltaTimeFormatter.Format(new TimeSpan(0, 9, 0, 0)); + MeasureCharLabel.Text = "W"; + + MeasureTimeLabel.Font = state.LayoutSettings.TimesFont; + MeasureTimeLabel.IsMonospaced = true; + MeasureDeltaLabel.Font = state.LayoutSettings.TimesFont; + MeasureDeltaLabel.IsMonospaced = true; + MeasureCharLabel.Font = state.LayoutSettings.TimesFont; + MeasureCharLabel.IsMonospaced = true; + + MeasureTimeLabel.SetActualWidth(g); + MeasureDeltaLabel.SetActualWidth(g); + MeasureCharLabel.SetActualWidth(g); + } + public void DrawVertical(Graphics g, LiveSplitState state, float width, Region clipRegion) { Prepare(state); DrawBackground(g, width, VerticalHeight); + SetMeasureLabels(g, state); InternalComponent.DrawVertical(g, state, width, clipRegion); } @@ -379,6 +435,7 @@ public void DrawHorizontal(Graphics g, LiveSplitState state, float height, Regio { Prepare(state); DrawBackground(g, HorizontalWidth, height); + SetMeasureLabels(g, state); InternalComponent.DrawHorizontal(g, state, height, clipRegion); } @@ -647,12 +704,96 @@ public void Update(IInvalidator invalidator, LiveSplitState state, float width, i++; } + CalculateColumnWidths(state.Run); + if (invalidator != null) { InternalComponent.Update(invalidator, state, width, height, mode); } } + private void CalculateColumnWidths(IRun run) + { + if (ColumnsList != null) + { + while (ColumnWidths.Count < ColumnsList.Count()) + { + ColumnWidths.Add((0, 0f, 0f)); + } + + TimeSpan longestTime = new TimeSpan(9, 0, 0); + TimeSpan longestDelta = new TimeSpan(0, 0, 59, 0); + foreach (ISegment split in run.Reverse()) + { + if (split.SplitTime.RealTime is TimeSpan splitRealTime && longestTime < splitRealTime) + { + longestTime = splitRealTime; + } + + foreach (KeyValuePair kv in split.Comparisons) + { + if (kv.Value.RealTime is TimeSpan cmpRealTime && longestTime < cmpRealTime) + { + longestTime = cmpRealTime; + } + + if (split.SplitTime.RealTime - kv.Value.RealTime is TimeSpan deltaRealTime) + { + if (longestDelta < deltaRealTime) + { + longestDelta = deltaRealTime; + } + else if (longestDelta < (-deltaRealTime)) + { + longestDelta = -deltaRealTime; + } + } + } + } + + int timeLength = TimeFormatter.Format(longestTime).Length; + int deltaLength = DeltaTimeFormatter.Format(longestDelta).Length; + float timeCharWidth = MeasureTimeLabel.Text.Length > 0 ? MeasureTimeLabel.ActualWidth / MeasureTimeLabel.Text.Length : MeasureCharLabel.ActualWidth; + float timeWidth = Math.Max(MeasureTimeLabel.ActualWidth, timeCharWidth * (timeLength + 1)); + float deltaWidth = Math.Max(MeasureDeltaLabel.ActualWidth, timeCharWidth * (deltaLength + 1)); + + for (int i = 0; i < ColumnsList.Count(); i++) + { + ColumnData column = ColumnsList.ElementAt(i); + + float labelWidth = 0f; + if (column.Type is ColumnType.DeltaorSplitTime or ColumnType.SegmentDeltaorSegmentTime) + { + labelWidth = Math.Max(deltaWidth, timeWidth); + } + else if (column.Type is ColumnType.Delta or ColumnType.SegmentDelta) + { + labelWidth = deltaWidth; + } + else if (column.Type is ColumnType.SplitTime or ColumnType.SegmentTime) + { + labelWidth = timeWidth; + } + else if (column.Type is ColumnType.CustomVariable) + { + int longestLength = run.Metadata.CustomVariableValue(column.Name).Length; + foreach (ISegment split in run) + { + if (split.CustomVariableValues.TryGetValue(column.Name, out string value) && !string.IsNullOrEmpty(value)) + { + longestLength = Math.Max(longestLength, value.Length); + } + } + + float exCharWidth = ColumnWidths[i].exLength > 0 ? ColumnWidths[i].exWidth / ColumnWidths[i].exLength : MeasureCharLabel.ActualWidth; + labelWidth = exCharWidth * (longestLength + 1); + } + + ColumnWidths[i] = (ColumnWidths[i].exLength, ColumnWidths[i].exWidth, labelWidth); + } + } + } + private bool ShouldIncludeSplit(int currentSection, int split) { return (sectionList.isMajorSplit(split)