/// <summary>
        /// Sets the initial state of the application
        /// </summary>
        public void InitAppState(
            List <ComboDataItem> themes,
            List <ComboDataItem> fontSizes,
            List <ComboDataItem> demos,
            List <ComboDataItem> scenarios,
            List <ComboDataItem> sourceFiles)
        {
            if (State != null)
            {
                return;
            }
            var oldState = State;
            var newState = new BlazorBoardState
            {
                Themes = themes ?? throw new ArgumentNullException(nameof(themes)),
                               SelectedThemeId = (themes?.Count ?? -1) > 0 ? themes[0].Id : null,
                               FontSizes       = fontSizes ?? throw new ArgumentNullException(nameof(fontSizes)),
                                                       SelectedFontSizeId = (fontSizes?.Count ?? -1) > 0 ? fontSizes[0].Id : null,
                                                       Demos = demos ?? throw new ArgumentNullException(nameof(demos)),
                                                                     SelectedDemoId = (demos?.Count ?? -1) > 0 ? demos[0].Id : null,
                                                                     Scenarios      = scenarios ?? throw new ArgumentNullException(nameof(scenarios)),
                                                                                            SelectedScenarioId = (scenarios?.Count ?? -1) > 0 ? scenarios[0].Id : null,
                                                                                            SourceFiles        = sourceFiles ?? throw new ArgumentNullException(nameof(sourceFiles)),
                                                                                                                       SelectedSourceFileName = (sourceFiles?.Count ?? -1) > 0 ? sourceFiles[0].Id : null,
            };

            State = newState;
            AppStateChanged?.Invoke(this, new StateChangedEventArgs(oldState, State));
        }
        /// <summary>
        /// Selects a new application theme
        /// </summary>
        /// <param name="themeId">ID of the new theme</param>
        public void SelectTheme(string themeId)
        {
            if (State.SelectedThemeId == themeId)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s => s.SelectedThemeId = themeId);
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            SelectedThemeChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Selects a scenario in the scenario list
        /// </summary>
        /// <param name="scenarioId">ID of the selected scenario</param>
        public void SelectScenario(string scenarioId)
        {
            if (State.SelectedScenarioId == scenarioId)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s => s.SelectedScenarioId = scenarioId);
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            SelectedScenarioChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Selects a source file in the source file list
        /// </summary>
        /// <param name="sourceFile">Selected source file</param>
        public void SelectSourceFile(string sourceFile)
        {
            if (State.SelectedSourceFileName == sourceFile)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s => s.SelectedSourceFileName = sourceFile);
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            SelectedSourceFileChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Selects a demo in the demo list
        /// </summary>
        /// <param name="demoId">ID of the selected demo</param>
        public void SelectDemo(string demoId)
        {
            if (State.SelectedDemoId == demoId)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s => s.SelectedDemoId = demoId);
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            SelectedDemoChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Selects a new font size
        /// </summary>
        /// <param name="fontSizeId">ID of the new font size</param>
        public void SelectFontSize(string fontSizeId)
        {
            if (State.SelectedFontSizeId == fontSizeId)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s => s.SelectedFontSizeId = fontSizeId);
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            SelectedFontSizeChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Sets the list of themes
        /// </summary>
        /// <param name="themes">List of themes</param>
        public void SetThemeList(List <ComboDataItem> themes)
        {
            if (State.Themes == themes)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s =>
            {
                s.Themes          = themes;
                s.SelectedThemeId = themes.Count > 0 ? themes[0].Id : null;
            });
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            ThemeListChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Sets the list of demos
        /// </summary>
        /// <param name="demos">List of demos</param>
        public void SetDemoList(List <ComboDataItem> demos)
        {
            if (State.Demos == demos)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s => {
                s.Demos          = demos;
                s.SelectedDemoId = demos.Count > 0 ? demos[0].Id : null;
            });
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            DemoListChanged?.Invoke(this, args);
            SelectedDemoChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Sets the list of source files
        /// </summary>
        /// <param name="sourceFiles">List of source files</param>
        public void SetSourceFileList(List <ComboDataItem> sourceFiles)
        {
            if (State.SourceFiles == sourceFiles)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s =>
            {
                s.SourceFiles            = sourceFiles;
                s.SelectedSourceFileName = sourceFiles.Count > 0 ? sourceFiles[0].Id : null;
            });
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            SourceFileListChanged?.Invoke(this, args);
            SelectedSourceFileChanged?.Invoke(this, args);
        }
        /// <summary>
        /// Sets the list of scenarios
        /// </summary>
        /// <param name="scenarios">List of scenarios</param>
        public void SetScenarioList(List <ComboDataItem> scenarios)
        {
            if (State.Scenarios == scenarios)
            {
                return;
            }
            var oldState = State;

            State = State.Clone(s =>
            {
                s.Scenarios          = scenarios;
                s.SelectedScenarioId = scenarios.Count > 0 ? scenarios[0].Id : null;
            });
            var args = new StateChangedEventArgs(oldState, State);

            AppStateChanged?.Invoke(this, args);
            ScenarioListChanged?.Invoke(this, args);
            SelectedScenarioChanged?.Invoke(this, args);
        }