Creating and updating seasons with an editor.
This commit is contained in:
81
EstusShots.Gtk/Dialogs/DialogBase.cs
Normal file
81
EstusShots.Gtk/Dialogs/DialogBase.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using EstusShots.Shared.Models;
|
||||
using Gtk;
|
||||
using UI = Gtk.Builder.ObjectAttribute;
|
||||
|
||||
namespace EstusShots.Gtk.Dialogs
|
||||
{
|
||||
public class DialogClosedEventArgs<T> : EventArgs where T: class, new()
|
||||
{
|
||||
public bool Ok { get; }
|
||||
public T Model { get; }
|
||||
|
||||
public DialogClosedEventArgs(bool ok, T model)
|
||||
{
|
||||
Ok = ok;
|
||||
Model = model;
|
||||
}
|
||||
}
|
||||
public delegate void DialogClosedEventHandler<T>(object o, DialogClosedEventArgs<T> args) where T: class, new();
|
||||
|
||||
// TODO remove non-generic version
|
||||
public class DialogClosedEventArgs : EventArgs
|
||||
{
|
||||
public bool Ok { get; }
|
||||
public object Model { get; }
|
||||
|
||||
public DialogClosedEventArgs(bool ok, object model)
|
||||
{
|
||||
Ok = ok;
|
||||
Model = model;
|
||||
}
|
||||
}
|
||||
public delegate void DialogClosedEventHandler(object o, DialogClosedEventArgs args);
|
||||
|
||||
public abstract class DialogBase<T> where T: class, new()
|
||||
{
|
||||
protected T EditObject { get; set; }
|
||||
|
||||
[UI] private readonly Dialog _editorDialog = null;
|
||||
[UI] private readonly Button _saveButton = null;
|
||||
[UI] private readonly Button _cancelButton = null;
|
||||
|
||||
public event DialogClosedEventHandler<T> OnDialogClosed;
|
||||
|
||||
protected DialogBase(Window parent, Builder builder)
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
|
||||
_saveButton.Clicked += OnSaveButtonClicked;
|
||||
_cancelButton.Clicked += (sender, args) =>
|
||||
{
|
||||
OnDialogClosed?.Invoke(this, new DialogClosedEventArgs<T>(false, new T()));
|
||||
_editorDialog.Dispose();
|
||||
};
|
||||
_editorDialog.TransientFor = parent;
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
LoadFromModel();
|
||||
_editorDialog.Show();
|
||||
}
|
||||
|
||||
private void OnSaveButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadToModel();
|
||||
OnDialogClosed?.Invoke(this, new DialogClosedEventArgs<T>(true, EditObject));
|
||||
_editorDialog.Dispose();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ErrorDialog.Show(new OperationResult(exception));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void LoadToModel();
|
||||
protected abstract void LoadFromModel();
|
||||
}
|
||||
}
|
||||
210
EstusShots.Gtk/Dialogs/Glade/SeasonEditor.glade
Normal file
210
EstusShots.Gtk/Dialogs/Glade/SeasonEditor.glade
Normal file
@@ -0,0 +1,210 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkDialog" id="_editorDialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Season</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="default_width">400</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="gravity">center</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="_saveButton">
|
||||
<property name="label">gtk-save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<accelerator key="Return" signal="clicked"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="_cancelButton">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="row_spacing">5</property>
|
||||
<property name="column_spacing">7</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Number</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Game</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="_gameEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Start</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">End</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Description</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<property name="min_content_height">150</property>
|
||||
<property name="propagate_natural_width">True</property>
|
||||
<property name="propagate_natural_height">True</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="_descriptionTextView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="hscroll_policy">natural</property>
|
||||
<property name="vscroll_policy">natural</property>
|
||||
<property name="wrap_mode">word</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="_startEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="_endEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="secondary_icon_stock">gtk-clear</property>
|
||||
<property name="placeholder_text" translatable="yes">Ongoing</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="_numberEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="input_purpose">digits</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -5,19 +5,6 @@ using UI = Gtk.Builder.ObjectAttribute;
|
||||
|
||||
namespace EstusShots.Gtk.Dialogs
|
||||
{
|
||||
public class DialogClosedEventArgs : EventArgs
|
||||
{
|
||||
public bool Ok { get; }
|
||||
public object Model { get; }
|
||||
|
||||
public DialogClosedEventArgs(bool ok, object model)
|
||||
{
|
||||
Ok = ok;
|
||||
Model = model;
|
||||
}
|
||||
}
|
||||
public delegate void DialogClosedEventHandler(object o, DialogClosedEventArgs args);
|
||||
|
||||
public class PlayerEditor
|
||||
{
|
||||
private readonly Player _player;
|
||||
|
||||
57
EstusShots.Gtk/Dialogs/SeasonEditor.cs
Normal file
57
EstusShots.Gtk/Dialogs/SeasonEditor.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using EstusShots.Shared.Dto;
|
||||
using EstusShots.Shared.Extensions;
|
||||
using Gtk;
|
||||
using UI = Gtk.Builder.ObjectAttribute;
|
||||
|
||||
namespace EstusShots.Gtk.Dialogs
|
||||
{
|
||||
public class SeasonEditor : DialogBase<Season>
|
||||
{
|
||||
[UI] private readonly Entry _numberEntry = null;
|
||||
[UI] private readonly Entry _gameEntry = null;
|
||||
[UI] private readonly Entry _startEntry = null;
|
||||
[UI] private readonly Entry _endEntry = null;
|
||||
[UI] private readonly TextView _descriptionTextView = null;
|
||||
|
||||
public SeasonEditor(Window parent, Season season) : base(parent, new Builder("SeasonEditor.glade"))
|
||||
{
|
||||
EditObject = season;
|
||||
_startEntry.FocusOutEvent += (o, args) =>
|
||||
{
|
||||
if (!(o is Entry entry)) return;
|
||||
entry.Text = entry.Text.DateMask();
|
||||
};
|
||||
_endEntry.FocusOutEvent += (o, args) =>
|
||||
{
|
||||
if (!(o is Entry entry)) return;
|
||||
if (entry.Text.IsNullOrWhiteSpace()) return;
|
||||
entry.Text = entry.Text.DateMask();
|
||||
};
|
||||
_endEntry.IconPress += (o, args) =>
|
||||
{
|
||||
if (!(o is Entry entry)) return;
|
||||
entry.Text = "";
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadFromModel()
|
||||
{
|
||||
if (EditObject.SeasonId.IsEmpty()) return;
|
||||
_numberEntry.Text = EditObject.Number.ToString();
|
||||
_gameEntry.Text = EditObject.Game;
|
||||
_startEntry.Text = EditObject.Start.ToString("yyyy-MM-dd");
|
||||
_endEntry.Text = EditObject.End?.ToString("yyyy-MM-dd") ?? "";
|
||||
_descriptionTextView.Buffer = new TextBuffer(new TextTagTable()) {Text = EditObject.Description};
|
||||
}
|
||||
|
||||
protected override void LoadToModel()
|
||||
{
|
||||
EditObject.Number = _numberEntry.Text.ToInt32OrDefault();
|
||||
EditObject.Game = _gameEntry.Text;
|
||||
EditObject.Start = _startEntry.Text.ToDateTime();
|
||||
EditObject.End = _endEntry.Text.IsNullOrWhiteSpace() ? null :_endEntry.Text.ToNullableDateTime();
|
||||
EditObject.Description = _descriptionTextView.Buffer.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user