public AdvancedOptions()
        {
            InitializeComponent();

            if (DesignMode)
            {
                return;
            }

            if (ZAMsettings.LoggerFactory == null)
            {
                return;
            }

            Logger = ZAMsettings.LoggerFactory.CreateLogger <AdvancedOptions>();

            this.BackColor = Color.AliceBlue;
            this.ForeColor = Color.AliceBlue;

            MSoffice2010ColorManager colorTable = ZAMappearance.ApplyColorTable(this);

            // SfForm is not firing the property changed events so doing it manually here.
            this.AdvancedOptions_BackColorChanged(this, null);
            this.AdvancedOptions_ForeColorChanged(this, null);

            this.Icon = Properties.Resources.ZAMicon;

            UserControlBase.SetListViewHeaderColor(ref this.lvTrace, SystemColors.Control, SystemColors.ControlText);
        }
        public ConfigurationOptions(Point ZAMWindowPos)
        {
            InitializeComponent();

            if (DesignMode)
            {
                return;
            }

            if (ZAMsettings.LoggerFactory == null)
            {
                return;
            }

            Logger = ZAMsettings.LoggerFactory.CreateLogger <ConfigurationOptions>();

            SystemControl.ZAMWindowPos = ZAMWindowPos;

            MSoffice2010ColorManager colorTable = ZAMappearance.ApplyColorTable(this);

            this.Icon = Properties.Resources.ZAMicon;

            //ZAMappearance.ApplyColorScheme(this);

            tabOptions.TabPanelBackColor  = colorTable.ActiveFormBorderColor;
            tabOptions.ActiveTabColor     = colorTable.ActiveFormBorderColor;
            tabOptions.ActiveTabForeColor = colorTable.FormTextColor;

            tabOptions.InactiveTabColor     = colorTable.InactiveFormBorderColor;;
            tabOptions.InActiveTabForeColor = colorTable.FormTextColor;

            // the user controls will receive notifications that their parent's (the tabpages) colors have changed
            this.tpSystem.BackColor       = Color.AliceBlue;
            this.tpSystem.ForeColor       = Color.AliceBlue;
            this.tpLaps.BackColor         = Color.AliceBlue;
            this.tpLaps.ForeColor         = Color.AliceBlue;
            this.tpSplits.BackColor       = Color.AliceBlue;
            this.tpSplits.ForeColor       = Color.AliceBlue;
            this.tpUserProfiles.BackColor = Color.AliceBlue;
            this.tpUserProfiles.ForeColor = Color.AliceBlue;
            this.tpGeneral.BackColor      = Color.AliceBlue;
            this.tpGeneral.ForeColor      = Color.AliceBlue;

            this.tpSystem.BackColor = colorTable.FormBackground;
            this.tpSystem.ForeColor = colorTable.FormTextColor;

            this.tpLaps.BackColor = colorTable.FormBackground;
            this.tpLaps.ForeColor = colorTable.FormTextColor;

            this.tpSplits.BackColor = colorTable.FormBackground;
            this.tpSplits.ForeColor = colorTable.FormTextColor;

            this.tpUserProfiles.BackColor = colorTable.FormBackground;
            this.tpUserProfiles.ForeColor = colorTable.FormTextColor;

            this.tpGeneral.BackColor = colorTable.FormBackground;
            this.tpGeneral.ForeColor = colorTable.FormTextColor;
        }
        private void AdjustFont()
        {
            if (this.InitializingControls)
            {
                return;
            }

            if (this.cbFonts.SelectedItem == null)
            {
                return;
            }

            if (this.cbTheme.SelectedItem == null)
            {
                return;
            }

            FontStyle style = 0;

            style |= cbBold.Checked ? FontStyle.Bold : 0;
            style |= cbItalic.Checked ? FontStyle.Italic : 0;

            Font font = new Font(this.cbFonts.SelectedItem.ToString(), (float)this.nudFontSize.Value, style);

            lblSample.Font = font;


            var selection = (KeyValuePair <ThemeType, string>)cbTheme.SelectedItem;

            MSoffice2010ColorManager colorTable;

            if (selection.Key != ThemeType.Custom)
            {
                MSoffice2010Theme theme = ZAMsettings.Settings.Appearance.GetMSoffice2010Theme(selection.Key, out Color? managedColor);

                if (theme == MSoffice2010Theme.Managed)
                {
                    // store managed colors in the static object
                    MSoffice2010ColorManager.ApplyManagedColors(managedColor.Value);
                    colorTable = MSoffice2010ColorManager.GetColorTable(MSoffice2010Theme.Managed);
                }
                else
                {
                    colorTable = MSoffice2010ColorManager.GetColorTable(theme);
                }
            }
            else
            {
                // store managed colors in the static object
                MSoffice2010ColorManager.ApplyManagedColors(btnColor.SelectedColor);
                colorTable = MSoffice2010ColorManager.GetColorTable(MSoffice2010Theme.Managed);
            }

            this.panel1.BackColor = colorTable.FormBackground;
            this.panel1.ForeColor = colorTable.FormTextColor;
        }
        private void AdvancedOptions_BackColorChanged(object sender, EventArgs e)
        {
            this.btnClose.BackColor = this.BackColor;
            this.btnStart.BackColor = this.BackColor;
            this.btnStop.BackColor  = this.BackColor;

            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            this.gbZwiftPacketMonitor.BorderColor = colorTable.ActiveFormBorderColor;
        }
Example #5
0
        protected override void Parent_BackColorChanged(object sender, EventArgs e)
        {
            base.Parent_BackColorChanged(sender, e);

            this.tbDescUsers.BackColor = this.BackColor;

            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            this.gbUserProfiles.BorderColor = colorTable.ActiveFormBorderColor;
        }
Example #6
0
        public void CreateDocumentText()
        {
            /*
             #000001 BackColor
             #000002 ActiveFormBorderColor
             #000003 ForeColor
             #000004 ActiveTitleGradientEnd
             */
            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            string styleSheet = Properties.Resources.StyleSheet;

            styleSheet = styleSheet.Replace("000001", $"{colorTable.FormBackground.R:X2}{ colorTable.FormBackground.G:X2}{ colorTable.FormBackground.B:X2}");
            styleSheet = styleSheet.Replace("000002", $"{colorTable.ActiveFormBorderColor.R:X2}{ colorTable.ActiveFormBorderColor.G:X2}{ colorTable.ActiveFormBorderColor.B:X2}");
            styleSheet = styleSheet.Replace("000003", $"{colorTable.FormTextColor.R:X2}{ colorTable.FormTextColor.G:X2}{ colorTable.FormTextColor.B:X2}");
            styleSheet = styleSheet.Replace("000004", $"{colorTable.ActiveTitleGradientEnd.R:X2}{ colorTable.ActiveTitleGradientEnd.G:X2}{ colorTable.ActiveTitleGradientEnd.B:X2}");

            string splitStatus = Properties.Resources.SplitStatusFreeform;
            string delta       = "";

            if (this.mSplitEventArgs.DeltaTime.HasValue)
            {
                TimeSpan std     = (TimeSpan)this.mSplitEventArgs.DeltaTime;
                bool     negated = false;

                if (std.TotalSeconds < 0)
                {
                    std     = std.Negate();
                    negated = true;
                }

                delta = $"{(negated ? "-" : "+")}{(std.Minutes > 0 ? std.ToString("m'@QT's'\"'").Replace("@QT", "\'") : std.ToString("s'\"'"))}";

                splitStatus = splitStatus.Replace("DeltaColorCode", this.mSplitEventArgs.AheadOfGoalTime.Value ? "00C000" : "C00000");
            }
            else
            {
                splitStatus = splitStatus.Replace("DeltaColorCode", "00C000");
                //splitStatus = splitStatus.Replace("DeltaColorCode", $"{colorTable.FormBackground.R:X2}{ colorTable.FormBackground.G:X2}{ colorTable.FormBackground.B:X2}");
                delta = "No Goal";
            }

            splitStatus = splitStatus.Replace("DeltaTime", delta);
            splitStatus = splitStatus.Replace("SplitNumber", this.mSplitEventArgs.SplitNumber.ToString());
            splitStatus = splitStatus.Replace("SplitSpeedKph", this.mSplitEventArgs.SplitSpeedKph.ToString("0.0"));
            splitStatus = splitStatus.Replace("SplitSpeedMph", this.mSplitEventArgs.SplitSpeedMph.ToString("0.0"));
            splitStatus = splitStatus.Replace("SplitTime", this.mSplitEventArgs.SplitTime.ToString("hh\\:mm\\:ss"));
            splitStatus = splitStatus.Replace("TotalKmTravelled", this.mSplitEventArgs.TotalKmTravelled.ToString("0.0"));
            splitStatus = splitStatus.Replace("TotalMiTravelled", this.mSplitEventArgs.TotalMiTravelled.ToString("0.0"));
            splitStatus = splitStatus.Replace("TotalTime", this.mSplitEventArgs.TotalTime.ToString("hh\\:mm\\:ss"));

            Logger.LogDebug($"{this.GetType()}::CreateDocumentText - \n{splitStatus}");
            this.DocumentText = styleSheet + splitStatus;
        }
Example #7
0
        protected override void Parent_BackColorChanged(object sender, EventArgs e)
        {
            base.Parent_BackColorChanged(sender, e);

            this.tbDescSystem.BackColor = this.BackColor;

            this.dgvSplits.RowBackColor    = this.BackColor;
            this.dgvSplits.BackgroundColor = this.BackColor;
            this.dgvSplits.RowHeadersDefaultCellStyle.BackColor = this.BackColor;

            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            this.gbSplitGoals.BorderColor = colorTable.ActiveFormBorderColor;
            this.gbSplits.BorderColor     = colorTable.ActiveFormBorderColor;
        }
        /// <summary>
        /// This needs to be called on the UI thread
        /// </summary>
        /// <param name="form"></param>
        public virtual void InitializeStatus(Form form)
        {
            Debug.Assert(!this.mIsStatusInitialized, $"InitializeStatus already called.");
            Debug.Assert(ZAMsettings.Settings.StatusViewerDurationSecs.HasValue, $"StatusViewerDurationSecs is null.");

            this.mParentForm = form;
            this.mParentForm.Controls.Add(this);

            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            this.tlPanel.BackColor = colorTable.FormBackground;
            this.pStatus.BackColor = colorTable.FormBackground;
            this.pStatus.ForeColor = colorTable.FormTextColor;

            this.mStatusViewerDuration = ZAMsettings.Settings.StatusViewerDurationSecs.Value;
            this.btnAutoDismiss.Text   = this.mDismissBtnBaseText;
            this.mIsStatusInitialized  = true;
        }
Example #9
0
        protected override void Parent_ForeColorChanged(object sender, EventArgs e)
        {
            base.Parent_ForeColorChanged(sender, e);

            this.tbDescSystem.ForeColor = this.ForeColor;

            this.dgvSplits.RowForeColor    = this.ForeColor;
            this.dgvSplits.ForeColor       = this.ForeColor;
            this.dgvSplits.HeaderForeColor = this.ForeColor;

            this.gbSplitGoals.ForeColor = this.ForeColor;
            this.gbSplits.ForeColor     = this.ForeColor;

            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            //Office2010Colors t = Office2010Colors.GetColorTable(Office2010Colors.DefaultTheme);
            dgvSplits.HeaderGradientBeginColor = colorTable.ActiveTitleGradientBegin;
            dgvSplits.HeaderGradientEndColor   = colorTable.ActiveTitleGradientEnd;
        }
        public void CreateDocumentText()
        {
            /*
             #000001 BackColor
             #000002 ActiveFormBorderColor
             #000003 ForeColor
             #000004 ActiveTitleGradientEnd
             */
            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            string styleSheet = Properties.Resources.StyleSheet;

            styleSheet = styleSheet.Replace("000001", $"{colorTable.FormBackground.R:X2}{ colorTable.FormBackground.G:X2}{ colorTable.FormBackground.B:X2}");
            styleSheet = styleSheet.Replace("000002", $"{colorTable.ActiveFormBorderColor.R:X2}{ colorTable.ActiveFormBorderColor.G:X2}{ colorTable.ActiveFormBorderColor.B:X2}");
            styleSheet = styleSheet.Replace("000003", $"{colorTable.FormTextColor.R:X2}{ colorTable.FormTextColor.G:X2}{ colorTable.FormTextColor.B:X2}");
            styleSheet = styleSheet.Replace("000004", $"{colorTable.ActiveTitleGradientEnd.R:X2}{ colorTable.ActiveTitleGradientEnd.G:X2}{ colorTable.ActiveTitleGradientEnd.B:X2}");

            string lapStatus = Properties.Resources.LapStatusFreeform;


            lapStatus = lapStatus.Replace("LapAPwattsPerKg", this.mLapEventArgs.LapAPwattsPerKg.HasValue ? this.mLapEventArgs.LapAPwattsPerKg.Value.ToString("0.00") + "w/kg" : "");
            lapStatus = lapStatus.Replace("LapAPwatts", this.mLapEventArgs.LapAPwatts.ToString());
            lapStatus = lapStatus.Replace("LapDistanceKm", this.mLapEventArgs.LapDistanceKm.ToString("0.0"));
            lapStatus = lapStatus.Replace("LapDistanceMi", this.mLapEventArgs.LapDistanceMi.ToString("0.0"));
            lapStatus = lapStatus.Replace("LapNumber", this.mLapEventArgs.LapNumber.ToString());
            lapStatus = lapStatus.Replace("LapSpeedKph", this.mLapEventArgs.LapSpeedKph.ToString("0.0"));
            lapStatus = lapStatus.Replace("LapSpeedMph", this.mLapEventArgs.LapSpeedMph.ToString("0.0"));
            lapStatus = lapStatus.Replace("LapTime", this.mLapEventArgs.LapTime.ToString("hh\\:mm\\:ss"));
            lapStatus = lapStatus.Replace("TotalTime", this.mLapEventArgs.TotalTime.ToString("hh\\:mm\\:ss"));

            lapStatus = lapStatus.Replace("LapPower", $"{this.mLapEventArgs.LapAPwatts + " w"}{(this.mLapEventArgs.LapAPwattsPerKg.HasValue ? " (" + this.mLapEventArgs.LapAPwattsPerKg.Value.ToString("0.00") + " w/kg)" : "")}");
            lapStatus = lapStatus.Replace("LapDistance", $"{this.mLapEventArgs.LapDistanceKm.ToString("0.0") + " km"}{" (" + this.mLapEventArgs.LapDistanceMi.ToString("0.0") + " mi)"}");
            lapStatus = lapStatus.Replace("LapSpeed", $"{this.mLapEventArgs.LapSpeedKph.ToString("0.0") + " km/h"}{" (" + this.mLapEventArgs.LapSpeedMph.ToString("0.0") + " mi/h)"}");

            Logger.LogDebug($"{this.GetType()}::CreateDocumentText - \n{lapStatus}");
            this.DocumentText = styleSheet + lapStatus;
        }
Example #11
0
        public RideRecap(RideRecapMetrics rideRecapMetrics)
        {
            mRideRecapMetrics = rideRecapMetrics;

            InitializeComponent();

            if (DesignMode)
            {
                return;
            }

            if (ZAMsettings.LoggerFactory == null)
            {
                return;
            }

            Logger = ZAMsettings.LoggerFactory.CreateLogger <RideRecap>();

            this.toolStrip.Renderer = new ToolStripProfessionalRendererEx();

            MSoffice2010ColorManager colorTable = ZAMappearance.ApplyColorTable(this);

            this.Icon = Properties.Resources.ZAMicon;
        }
Example #12
0
        private void RideRecap_Load(object sender, EventArgs e)
        {
            /*
             #000001 BackColor
             #000002 ActiveFormBorderColor
             #000003 ForeColor
             #000004 ActiveTitleGradientEnd
             */
            MSoffice2010ColorManager colorTable = ZAMappearance.GetColorTable();

            this.pControls.BackColor = colorTable.FormBackground;
            this.pControls.ForeColor = colorTable.FormTextColor;
            this.toolStrip.BackColor = colorTable.FormBackground;

            string styleSheet = Properties.Resources.StyleSheet;

            styleSheet = styleSheet.Replace("000001", $"{colorTable.FormBackground.R:X2}{ colorTable.FormBackground.G:X2}{ colorTable.FormBackground.B:X2}");
            styleSheet = styleSheet.Replace("000002", $"{colorTable.ActiveFormBorderColor.R:X2}{ colorTable.ActiveFormBorderColor.G:X2}{ colorTable.ActiveFormBorderColor.B:X2}");
            styleSheet = styleSheet.Replace("000003", $"{colorTable.FormTextColor.R:X2}{ colorTable.FormTextColor.G:X2}{ colorTable.FormTextColor.B:X2}");
            styleSheet = styleSheet.Replace("000004", $"{colorTable.ActiveTitleGradientEnd.R:X2}{ colorTable.ActiveTitleGradientEnd.G:X2}{ colorTable.ActiveTitleGradientEnd.B:X2}");

            mRideRecapHtml = Properties.Resources.RideRecap;

            StringBuilder xAxis = new StringBuilder("");
            StringBuilder yAxis = new StringBuilder("");

            if (this.mRideRecapMetrics.Power.Length > 0)
            {
                foreach (var power in this.mRideRecapMetrics.Power)
                {
                    xAxis.Append($"'{DurationEnum.Instance.GetText(power.DurationType)}',");
                    yAxis.Append($"{power.APwattsMax},");
                }
            }
            else
            {
                // no power values, build an empty chart
                foreach (var item in DurationEnum.Instance.GetValues())
                {
                    xAxis.Append($"'{item}',");
                }
            }

            string chartDef = "{type:'line',data:{labels:[xAxisValues],datasets:[{fill:true,lineTension:0,backgroundColor:'#000004',borderColor:'#000002',data:[yAxisValues],}]},options:{legend:{display:false},title:{display:true,text:'Peak Power',fontSize:20,fontFamily:'Segoe UI, sans-serif',fontColor:'#000003',},scales:{yAxes:[{ticks:{fontFamily:'Segoe UI, sans-serif',fontColor: '#000003'},scaleLabel:{display:true,labelString:'Watts',fontSize:16,fontFamily:'Segoe UI, sans-serif',fontColor:'#000003',},gridLines:{display:false,}}],xAxes:[{ticks:{fontFamily:'Segoe UI, sans-serif',fontColor: '#000003'},scaleLabel:{display:false,labelString:'Time',fontSize:16,fontFamily:'Segoe UI, sans-serif',fontColor:'#000003',},gridLines:{display:false,}}],}}}";

            chartDef = chartDef.Replace("xAxisValues", xAxis.ToString());
            chartDef = chartDef.Replace("yAxisValues", yAxis.ToString());

            // Define and encode the chart URL
            string urlStr = WebUtility.UrlEncode(chartDef);

            Debug.WriteLine(urlStr);

            mRideRecapHtml = mRideRecapHtml.Replace("EncodedChartUrl", urlStr);


            mRideRecapHtml = mRideRecapHtml.Replace("000001", $"{colorTable.FormBackground.R:X2}{ colorTable.FormBackground.G:X2}{ colorTable.FormBackground.B:X2}");
            mRideRecapHtml = mRideRecapHtml.Replace("000002", $"{colorTable.ActiveFormBorderColor.R:X2}{ colorTable.ActiveFormBorderColor.G:X2}{ colorTable.ActiveFormBorderColor.B:X2}");
            mRideRecapHtml = mRideRecapHtml.Replace("000003", $"{colorTable.FormTextColor.R:X2}{ colorTable.FormTextColor.G:X2}{ colorTable.FormTextColor.B:X2}");
            mRideRecapHtml = mRideRecapHtml.Replace("000004", $"{colorTable.ActiveTitleGradientEnd.R:X2}{ colorTable.ActiveTitleGradientEnd.G:X2}{ colorTable.ActiveTitleGradientEnd.B:X2}");

            //public TimeSpan Duration { get; set; }
            //public double DistanceKm { get; set; }
            //public double DistanceMi { get; set; }
            //public double AverageKph { get; set; }
            //public double AverageMph { get; set; }
            //public int APwatts { get; set; }
            //public double? APwattsPerKg { get; set; }
            //public int NPwatts { get; set; }
            //public double? NPwattsPerKg { get; set; }
            //public double? IntensityFactor { get; set; } // null if FTP not set
            //public int? TrainingStressScore { get; set; } // null if FTP not set

            mRideRecapHtml = mRideRecapHtml.Replace("Duration", $"{this.mRideRecapMetrics.Duration.ToString("hh\\:mm\\:ss")}");
            mRideRecapHtml = mRideRecapHtml.Replace("DistanceKm", $"{this.mRideRecapMetrics.DistanceKm:0.0}");
            mRideRecapHtml = mRideRecapHtml.Replace("DistanceMi", $"{this.mRideRecapMetrics.DistanceMi:0.0}");
            mRideRecapHtml = mRideRecapHtml.Replace("AverageKph", $"{this.mRideRecapMetrics.AverageKph:0.0}");
            mRideRecapHtml = mRideRecapHtml.Replace("AverageMph", $"{this.mRideRecapMetrics.AverageMph:0.0}");
            mRideRecapHtml = mRideRecapHtml.Replace("APwattsPerKg", $"{(this.mRideRecapMetrics.APwattsPerKg.HasValue ? this.mRideRecapMetrics.APwattsPerKg.Value.ToString("0.00") + " w/kg" : "")}");
            mRideRecapHtml = mRideRecapHtml.Replace("APwatts", $"{this.mRideRecapMetrics.APwatts}");
            mRideRecapHtml = mRideRecapHtml.Replace("NPwattsPerKg", $"{(this.mRideRecapMetrics.NPwattsPerKg.HasValue ? this.mRideRecapMetrics.NPwattsPerKg.Value.ToString("0.00") + " w/kg" : "")}");
            mRideRecapHtml = mRideRecapHtml.Replace("NPwatts", $"{this.mRideRecapMetrics.NPwatts}");
            mRideRecapHtml = mRideRecapHtml.Replace("IntensityFactor", $"{(this.mRideRecapMetrics.IntensityFactor.HasValue ? this.mRideRecapMetrics.IntensityFactor.Value.ToString(".00") : "")}");
            mRideRecapHtml = mRideRecapHtml.Replace("TrainingStressScore", $"{(this.mRideRecapMetrics.TrainingStressScore.HasValue ? this.mRideRecapMetrics.TrainingStressScore.Value : "")}");
            mRideRecapHtml = mRideRecapHtml.Replace("WorkKiloJoules", $"{this.mRideRecapMetrics.KiloJoules}");

            StringBuilder powerStr = new StringBuilder("");

            foreach (var power in this.mRideRecapMetrics.Power)
            {
                powerStr.AppendLine("<tr>");
                powerStr.AppendLine($"<td>{DurationEnum.Instance.GetText(power.DurationType)}</td>");
                powerStr.AppendLine($"<td>{power.APwattsMax}</td>");
                powerStr.AppendLine($"<td>{(power.APwattsKgMax.HasValue ? power.APwattsKgMax.Value.ToString("0.00") : "")}</td>");
                powerStr.AppendLine("</tr>");
            }

            mRideRecapHtml = mRideRecapHtml.Replace("RideRecapPower", powerStr.ToString());


            /*
             * <tr>
             *  <td>1</td>
             *  <td>1:45:43</td>
             *  <td>34.5 km/h (25.3 mi/h)</td>
             *  <td>21.0 km (18.3 mi)</td>
             *  <td>245 (3.2 w/kg)</td>
             *  <td>05:45:43</td>
             * </tr>
             */

            StringBuilder lapStr = new StringBuilder("");

            foreach (var lap in this.mRideRecapMetrics.Laps)
            {
                lapStr.AppendLine("<tr>");
                lapStr.AppendLine($"<td>{lap.LapNumber}</td>");
                lapStr.AppendLine($"<td>{lap.LapTime.ToString("hh\\:mm\\:ss")}</td>");
                lapStr.AppendLine($"<td>{lap.LapSpeedKph:0.0} km/h ({lap.LapSpeedMph:0.0} mi/h)</td>");
                lapStr.AppendLine($"<td>{lap.LapDistanceKm:0.0} km ({lap.LapDistanceMi:0.0} mi)</td>");
                lapStr.AppendLine($"<td>{lap.LapAPwatts} w{(lap.LapAPwattsPerKg.HasValue ? " (" + lap.LapAPwattsPerKg.Value.ToString("0.00") + " w/kg)" : "")}</td>");
                lapStr.AppendLine($"<td>{lap.TotalTime.ToString("hh\\:mm\\:ss")}</td>");
                lapStr.AppendLine("</tr>");
            }

            mRideRecapHtml = mRideRecapHtml.Replace("RideRecapLaps", lapStr.ToString());

            /*
             * <tr>
             *  <td>1</td>
             *  <td>1:45:43</td>
             *  <td>34.5 km/h (25.3 mi/h)</td>
             *  <td>21.0 km (18.3 mi)</td>
             *  <td>05:45:43</td>
             *  <td>-01:43</td>
             * </tr>
             */

            StringBuilder splitStr = new StringBuilder("");

            foreach (var split in this.mRideRecapMetrics.Splits)
            {
                string delta;
                //string deltaColorCode;
                if (split.DeltaTime.HasValue)
                {
                    TimeSpan std     = (TimeSpan)split.DeltaTime;
                    bool     negated = false;

                    if (std.TotalSeconds < 0)
                    {
                        std     = std.Negate();
                        negated = true;
                    }

                    delta = $"{(negated ? "-" : "+")}{(std.Minutes > 0 ? std.ToString("m'@QT's'\"'").Replace("@QT", "\'") : std.ToString("s'\"'"))}";
                    //deltaColorCode = negated ? "00C000" : "C00000";
                }
                else
                {
                    delta = "No Goal";
                }

                splitStr.AppendLine("<tr>");
                splitStr.AppendLine($"<td>{split.SplitNumber}</td>");
                splitStr.AppendLine($"<td>{split.SplitTime.ToString("hh\\:mm\\:ss")}</td>");
                splitStr.AppendLine($"<td>{split.SplitSpeedKph:0.0} km/h ({split.SplitSpeedMph:0.0} mi/h)</td>");
                splitStr.AppendLine($"<td>{split.SplitDistanceKm:0.0} km ({split.SplitDistanceMi:0.0} mi)</td>");
                splitStr.AppendLine($"<td>{split.TotalTime.ToString("hh\\:mm\\:ss")}</td>");
                splitStr.AppendLine($"<td>{delta}</td>");
                splitStr.AppendLine("</tr>");
            }

            mRideRecapHtml = mRideRecapHtml.Replace("RideRecapSplits", splitStr.ToString());

            Logger.LogDebug($"{this.GetType()}::RideRecap_Load - \n{mRideRecapHtml}");

            this.webBrowser.BrowserControl.DocumentText = styleSheet + mRideRecapHtml;

            tsbEmail.ToolTipText = this.CurrentUserProfile.EmailAddress.Length > 0 ? "MailTo:" + this.CurrentUserProfile.EmailAddress : "Please set email address in your user profile to use this feature.";
        }