diff --git a/EstusShots.Gtk/MainWindow.cs b/EstusShots.Gtk/MainWindow.cs index 43e0fc6..a8e364a 100644 --- a/EstusShots.Gtk/MainWindow.cs +++ b/EstusShots.Gtk/MainWindow.cs @@ -1,37 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using EstusShots.Client; using EstusShots.Gtk.Controls; using EstusShots.Shared.Dto; -using EstusShots.Shared.Models.Parameters; using Gtk; using UI = Gtk.Builder.ObjectAttribute; namespace EstusShots.Gtk { - internal class MainWindow : Window + internal partial class MainWindow : Window { private const string ApiUrl = "http://localhost:5000/api/"; private const string ApplicationName = "Estus Shots"; private const string Version = "0.1"; private const int EpisodesPageNumber = 1; - - [UI] private readonly Label _infoLabel = null; - [UI] public readonly Button LoadButton = null; + + [UI] public readonly Label InfoLabel = null; [UI] public readonly Box LoadingSpinner = null; - [UI] public readonly Button NewSeasonButton = null; - [UI] public readonly Button AddEpisodeButton = null; - [UI] public readonly Overlay SeasonsOverlay = null; - [UI] public readonly Overlay EpisodesOverlay = null; - [UI] public readonly TreeView SeasonsView = null; - [UI] public readonly TreeView EpisodesTreeView = null; [UI] public readonly Notebook Navigation = null; - [UI] public readonly Box EpisodesPage = null; private EstusShotsClient Client { get; } - private BindableListControl SeasonsControl { get; set; } private BindableListControl EpisodesControl { get; set; } public MainWindow() : this(new Builder("MainWindow.glade")) @@ -44,189 +30,19 @@ namespace EstusShots.Gtk Client = new EstusShotsClient(ApiUrl); DeleteEvent += Window_DeleteEvent; - LoadButton.Clicked += LoadButtonClicked; - NewSeasonButton.Clicked += NewSeasonButtonOnClicked; - AddEpisodeButton.Clicked += AddEpisodeButtonOnClicked; - InitSeasonsControl(); - InitEpisodesControl(); - + // Call initialization code of each page + InitSeasonsPage(); + InitEpisodesPage(); + InitPlayersPage(); + + CreateEpisodesControl(); + // The episodes page is not shown, as long as no season is selected EpisodesPage.Hide(); - + Info("Application Started"); UpdateTitle(); - - // No need to wait for the loading to finnish - var _ = ReloadSeasons(); - } - - private void InitSeasonsControl() - { - var columns = new List - { - new DataColumn(nameof(Season.DisplayName)) {Title = "Name"}, - new DataColumn(nameof(Season.Description)) {Title = "Description"}, - new DataColumn(nameof(Season.Start)) - { - Title = "Start", - Format = date => (date as DateTime?)?.ToString("dd.MM.yyyy") - }, - new DataColumn(nameof(Season.End)) - { - Title = "End", - Format = date => (date as DateTime?)?.ToString("dd.MM.yyyy") ?? "Ongoing" - } - }; - SeasonsControl = new BindableListControl(columns, nameof(Season.SeasonId), SeasonsView); - SeasonsControl.OnSelectionChanged += SeasonsViewOnOnSelectionChanged; - SeasonsControl.TreeView.RowActivated += SeasonsViewOnRowActivated; - } - - private void SeasonsViewOnRowActivated(object o, RowActivatedArgs args) - { - UpdateTitle(); - Navigation.Page = EpisodesPageNumber; - } - - private void InitEpisodesControl() - { - var columns = new List - { - new DataColumn(nameof(Episode.DisplayName)) {Title = "Name"}, - new DataColumn(nameof(Episode.Title)) {Title = "Title"}, - new DataColumn(nameof(Episode.Date)) - { - Title = "Date", - Format = d => (d as DateTime?)?.ToString("dd.MM.yyyy") - }, - new DataColumn(nameof(Episode.Start)) - { - Title = "Start", - Format = d => (d as DateTime?)?.ToString("HH:mm") - - }, - new DataColumn(nameof(Episode.End)) - { - Title = "End", - Format = d => (d as DateTime?)?.ToString("HH:mm") ?? "Ongoing" - } - }; - EpisodesControl = new BindableListControl(columns, nameof(Episode.EpisodeId), EpisodesTreeView); - } - - private async void SeasonsViewOnOnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - if (!(e.Selection is Season season)) return; - using var _ = new LoadingMode(this); - - EpisodesPage.Show(); - var parameter = new GetEpisodesParameter(season.SeasonId); - var res = await Client.Episodes.GetEpisodes(parameter); - EpisodesControl.Items = res.Data.Episodes; - EpisodesControl.DataBind(); - Info($"{season.DisplayName}: {res.Data.Episodes.Count} episodes"); - } - - private async void NewSeasonButtonOnClicked(object sender, EventArgs e) - { - using var _ = new LoadingMode(this); - // TODO real season edit control - var season = new Season - { - Game = "Test Game", - Number = SeasonsControl.Items.Any() ? SeasonsControl.Items.Max(x => x.Number) + 1 : 1, - Start = DateTime.Now, - Description = "This is a demo description!" - }; - var parameter = new SaveSeasonParameter(season); - var res = await Client.Seasons.SaveSeason(parameter); - if (!res.OperationResult.Success) - { - _infoLabel.Text = $"Error while creating Season: {res.OperationResult.ShortMessage}"; - return; - } - await ReloadSeasons(); - Info("Created new Season"); - } - - private async void AddEpisodeButtonOnClicked(object sender, EventArgs e) - { - if (SeasonsControl.SelectedItem == null) return; - using var _ = new LoadingMode(this); - - var season = SeasonsControl.SelectedItem; - - // Some random test data - var rand = new Random(); - var start = new DateTime( - DateTime.Today.Year, - DateTime.Today.Month, - DateTime.Today.Day, - DateTime.Today.Hour + rand.Next(0, 12), - DateTime.Today.Minute + rand.Next(0, 59), - DateTime.Today.Second - ); - var end = start.AddHours(rand.Next(2, 4)); - - var ep = new Episode - { - SeasonId = season.SeasonId, - Number = EpisodesControl.Items.Any() ? EpisodesControl.Items.Max(x => x.Number) + 1 : 1, - Title = $"An Episode in season '{season.Game}'", - Date = DateTime.Today, - Start = start, - End = end - }; - - var parameter = new SaveEpisodeParameter(ep); - var res = await Client.Episodes.SaveEpisode(parameter); - - if (!res.OperationResult.Success) - { - Info($"Cannot add episode: {res.OperationResult.ShortMessage}"); - return; - } - - await ReloadEpisodes(); - } - - private async void LoadButtonClicked(object sender, EventArgs a) - { - using var _ = new LoadingMode(this); - Info("Loading Seasons..."); - await ReloadSeasons(); - } - - private async Task ReloadSeasons() - { - var res = await Task.Factory.StartNew( - () => Client.Seasons.GetSeasons(new GetSeasonsParameter()).Result); - if (!res.OperationResult.Success) - { - _infoLabel.Text = $"Refresh Failed: {res.OperationResult.ShortMessage}"; - return; - } - - SeasonsControl.Items = res.Data.Seasons; - SeasonsControl.DataBind(); - Info("Seasons Refreshed"); - } - - private async Task ReloadEpisodes() - { - var seasonId = SeasonsControl.SelectedItem.SeasonId; - var res = await Task.Factory.StartNew( - () => Client.Episodes.GetEpisodes(new GetEpisodesParameter(seasonId)).Result); - if (!res.OperationResult.Success) - { - _infoLabel.Text = $"Refresh Failed: {res.OperationResult.ShortMessage}"; - return; - } - - EpisodesControl.Items = res.Data.Episodes; - EpisodesControl.DataBind(); - Info("Episodes Refreshed"); } private void Window_DeleteEvent(object sender, DeleteEventArgs a) @@ -236,13 +52,13 @@ namespace EstusShots.Gtk private void Info(string message) { - _infoLabel.Text = message; + InfoLabel.Text = message; } private void UpdateTitle() { - Title = SeasonsControl.SelectedItem == null - ? $"{ApplicationName} v{Version}" + Title = SeasonsControl.SelectedItem == null + ? $"{ApplicationName} v{Version}" : $"{SeasonsControl.SelectedItem.DisplayName} - {ApplicationName} v{Version}"; } } diff --git a/EstusShots.Gtk/MainWindow.glade b/EstusShots.Gtk/MainWindow.glade index bb5ebee..85c7b00 100644 --- a/EstusShots.Gtk/MainWindow.glade +++ b/EstusShots.Gtk/MainWindow.glade @@ -270,18 +270,117 @@ - + True False - vertical - - - - + True False - Players go here + + + True + True + in + + + True + True + + + + + + + + -1 + + + + + True + True + 0 + + + + + True + False + vertical + + + True + False + 5 + 5 + Edit Player + + + False + True + 0 + + + + + True + False + vertical + + + + + + True + True + 1 + + + + + True + False + 5 + start + + + gtk-save + True + True + True + True + + + True + True + 0 + + + + + gtk-delete + True + True + True + True + + + True + True + 1 + + + + + + + + False + True + 2 + + False @@ -289,9 +388,6 @@ 1 - - - 3 @@ -335,7 +431,7 @@ - + True False diff --git a/EstusShots.Gtk/Pages/EpisodesPage.cs b/EstusShots.Gtk/Pages/EpisodesPage.cs new file mode 100644 index 0000000..8d60f5b --- /dev/null +++ b/EstusShots.Gtk/Pages/EpisodesPage.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using EstusShots.Gtk.Controls; +using EstusShots.Shared.Dto; +using EstusShots.Shared.Models.Parameters; +using Gtk; +using UI = Gtk.Builder.ObjectAttribute; + +namespace EstusShots.Gtk +{ + internal partial class MainWindow + { + [UI] public readonly Box EpisodesPage = null; + [UI] public readonly Button AddEpisodeButton = null; + [UI] public readonly Overlay EpisodesOverlay = null; + [UI] public readonly TreeView EpisodesTreeView = null; + + private void InitEpisodesPage() + { + AddEpisodeButton.Clicked += AddEpisodeButtonOnClicked; + } + + // Eevents + + private async void AddEpisodeButtonOnClicked(object sender, EventArgs e) + { + if (SeasonsControl.SelectedItem == null) return; + using var _ = new LoadingMode(this); + + var season = SeasonsControl.SelectedItem; + + // Some random test data + var rand = new Random(); + var start = new DateTime( + DateTime.Today.Year, + DateTime.Today.Month, + DateTime.Today.Day, + DateTime.Today.Hour + rand.Next(0, 12), + DateTime.Today.Minute + rand.Next(0, 59), + DateTime.Today.Second + ); + var end = start.AddHours(rand.Next(2, 4)); + + var ep = new Episode + { + SeasonId = season.SeasonId, + Number = EpisodesControl.Items.Any() ? EpisodesControl.Items.Max(x => x.Number) + 1 : 1, + Title = $"An Episode in season '{season.Game}'", + Date = DateTime.Today, + Start = start, + End = end + }; + + var parameter = new SaveEpisodeParameter(ep); + var res = await Client.Episodes.SaveEpisode(parameter); + + if (!res.OperationResult.Success) + { + Info($"Cannot add episode: {res.OperationResult.ShortMessage}"); + return; + } + + await ReloadEpisodes(); + } + + // Private Methods + + private async Task ReloadEpisodes() + { + var seasonId = SeasonsControl.SelectedItem.SeasonId; + var res = await Task.Factory.StartNew( + () => Client.Episodes.GetEpisodes(new GetEpisodesParameter(seasonId)).Result); + if (!res.OperationResult.Success) + { + InfoLabel.Text = $"Refresh Failed: {res.OperationResult.ShortMessage}"; + return; + } + + EpisodesControl.Items = res.Data.Episodes; + EpisodesControl.DataBind(); + Info("Episodes Refreshed"); + } + + private void CreateEpisodesControl() + { + var columns = new List + { + new DataColumn(nameof(Episode.DisplayName)) {Title = "Name"}, + new DataColumn(nameof(Episode.Title)) {Title = "Title"}, + new DataColumn(nameof(Episode.Date)) + { + Title = "Date", + Format = d => (d as DateTime?)?.ToString("dd.MM.yyyy") + }, + new DataColumn(nameof(Episode.Start)) + { + Title = "Start", + Format = d => (d as DateTime?)?.ToString("HH:mm") + }, + new DataColumn(nameof(Episode.End)) + { + Title = "End", + Format = d => (d as DateTime?)?.ToString("HH:mm") ?? "Ongoing" + } + }; + EpisodesControl = new BindableListControl(columns, nameof(Episode.EpisodeId), EpisodesTreeView); + } + } +} \ No newline at end of file diff --git a/EstusShots.Gtk/Pages/PlayersPage.cs b/EstusShots.Gtk/Pages/PlayersPage.cs new file mode 100644 index 0000000..19da251 --- /dev/null +++ b/EstusShots.Gtk/Pages/PlayersPage.cs @@ -0,0 +1,21 @@ +using Gtk; +using UI = Gtk.Builder.ObjectAttribute; + +namespace EstusShots.Gtk +{ + internal partial class MainWindow + { + [UI] public readonly Box PlayersPage = null; + [UI] public readonly Overlay PlayersOverlay = null; + [UI] public readonly TreeView PlayersTreeView = null; + [UI] public readonly Button SavePlayerButton = null; + [UI] public readonly Button DeletePlayerButton = null; + [UI] public readonly Box PlayerEditorContainer = null; + + + private void InitPlayersPage() + { + + } + } +} \ No newline at end of file diff --git a/EstusShots.Gtk/Pages/SeasonsPage.cs b/EstusShots.Gtk/Pages/SeasonsPage.cs new file mode 100644 index 0000000..9549381 --- /dev/null +++ b/EstusShots.Gtk/Pages/SeasonsPage.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using EstusShots.Gtk.Controls; +using EstusShots.Shared.Dto; +using EstusShots.Shared.Models.Parameters; +using Gtk; +using UI = Gtk.Builder.ObjectAttribute; + +namespace EstusShots.Gtk +{ + internal partial class MainWindow + { + [UI] public readonly Button LoadButton = null; + [UI] public readonly Button NewSeasonButton = null; + [UI] public readonly TreeView SeasonsView = null; + [UI] public readonly Overlay SeasonsOverlay = null; + + private BindableListControl SeasonsControl { get; set; } + + private void InitSeasonsPage() + { + CreateSeasonsControl(); + + LoadButton.Clicked += LoadButtonClicked; + NewSeasonButton.Clicked += NewSeasonButtonOnClicked; + + // No need to wait for the loading to finnish + var _ = ReloadSeasons(); + } + + // Events + + private async void LoadButtonClicked(object sender, EventArgs a) + { + using var _ = new LoadingMode(this); + Info("Loading Seasons..."); + await ReloadSeasons(); + } + + private async void NewSeasonButtonOnClicked(object sender, EventArgs e) + { + using var _ = new LoadingMode(this); + // TODO real season edit control + var season = new Season + { + Game = "Test Game", + Number = SeasonsControl.Items.Any() ? SeasonsControl.Items.Max(x => x.Number) + 1 : 1, + Start = DateTime.Now, + Description = "This is a demo description!" + }; + var parameter = new SaveSeasonParameter(season); + var res = await Client.Seasons.SaveSeason(parameter); + if (!res.OperationResult.Success) + { + InfoLabel.Text = $"Error while creating Season: {res.OperationResult.ShortMessage}"; + return; + } + + await ReloadSeasons(); + Info("Created new Season"); + } + + private async void SeasonsControlOnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (!(e.Selection is Season season)) return; + using var _ = new LoadingMode(this); + + EpisodesPage.Show(); + var parameter = new GetEpisodesParameter(season.SeasonId); + var res = await Client.Episodes.GetEpisodes(parameter); + EpisodesControl.Items = res.Data.Episodes; + EpisodesControl.DataBind(); + + UpdateTitle(); + Navigation.Page = EpisodesPageNumber; + + Info($"{season.DisplayName}: {res.Data.Episodes.Count} episodes"); + } + + // Private Methods + + private async Task ReloadSeasons() + { + var res = await Task.Factory.StartNew( + () => Client.Seasons.GetSeasons(new GetSeasonsParameter()).Result); + if (!res.OperationResult.Success) + { + InfoLabel.Text = $"Refresh Failed: {res.OperationResult.ShortMessage}"; + return; + } + + SeasonsControl.Items = res.Data.Seasons; + SeasonsControl.DataBind(); + Info("Seasons Refreshed"); + } + + private void CreateSeasonsControl() + { + var columns = new List + { + new DataColumn(nameof(Season.DisplayName)) {Title = "Name"}, + new DataColumn(nameof(Season.Description)) {Title = "Description"}, + new DataColumn(nameof(Season.Start)) + { + Title = "Start", + Format = date => (date as DateTime?)?.ToString("dd.MM.yyyy") + }, + new DataColumn(nameof(Season.End)) + { + Title = "End", + Format = date => (date as DateTime?)?.ToString("dd.MM.yyyy") ?? "Ongoing" + } + }; + SeasonsControl = new BindableListControl(columns, nameof(Season.SeasonId), SeasonsView); + SeasonsControl.OnSelectionChanged += SeasonsControlOnSelectionChanged; + } + + } +} \ No newline at end of file