Skip to content

Commit d5c4a7d

Browse files
authored
Convert log form to Blazor (#345)
1 parent 8544bca commit d5c4a7d

10 files changed

+459
-170
lines changed

Diff for: FrEee.UI.Blazor/Views/HistoryLog.razor

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@using FrEee.Extensions
2+
@inherits ViewBase<HistoryLogViewModel>
3+
<table>
4+
@foreach (var turn in VM.Messages.GroupBy(q => q.TurnNumber).OrderByDescending(q => q.Key))
5+
{
6+
<tr>
7+
<td colspan="3">
8+
@turn.Key.ToStardate()
9+
</td>
10+
</tr>
11+
@foreach (var message in turn)
12+
{
13+
<tr>
14+
<td style="width: 32px; height: 32px;">
15+
<ImageDisplay VM="VM.CreateImageDisplayViewModel(message.Picture)"/>
16+
</td>
17+
<td>
18+
@message.Text
19+
</td>
20+
<td>
21+
@if (VM.CanNavigate(message))
22+
{
23+
<button onclick="@(() => VM.Navigate(message))" style="width: 100px; height: 50%">Go</button>
24+
}
25+
</td>
26+
</tr>
27+
}
28+
}
29+
</table>

Diff for: FrEee.UI.Blazor/Views/HistoryLogViewModel.cs

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.Drawing;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using FrEee.Modding.Templates;
9+
using FrEee.Objects.Civilization.Diplomacy.Messages;
10+
using FrEee.Objects.GameState;
11+
using FrEee.Objects.LogMessages;
12+
using FrEee.Objects.Space;
13+
using FrEee.Objects.Technology;
14+
using FrEee.Processes.Combat;
15+
using FrEee.Vehicles.Types;
16+
using FrEee.Vehicles;
17+
using FrEee.Extensions;
18+
19+
namespace FrEee.UI.Blazor.Views;
20+
21+
public class HistoryLogViewModel
22+
: ViewModelBase
23+
{
24+
public IEnumerable<LogMessage> Messages { get; set; } = [];
25+
26+
public ImageDisplayViewModel CreateImageDisplayViewModel(Image image)
27+
{
28+
return new ImageDisplayViewModel
29+
{
30+
Image = image
31+
};
32+
}
33+
34+
public void Navigate(LogMessage message)
35+
{
36+
if (message is IPictorialLogMessage<IPictorial> pm)
37+
{
38+
var context = pm.Context;
39+
if (context is ISpaceObject sobj)
40+
{
41+
// go to space object
42+
OnSpaceObjectSelected(this, sobj);
43+
}
44+
else if (context is IUnit unit)
45+
{
46+
// go to whatever contains the unit
47+
var container = unit.FindContainer();
48+
if (container != null)
49+
{
50+
if (container is Sector)
51+
{
52+
OnSpaceObjectSelected(this, (ISpaceObject)unit);
53+
}
54+
else
55+
{
56+
OnSpaceObjectSelected(this, (ISpaceObject)container);
57+
}
58+
}
59+
}
60+
else if (context is Facility facility)
61+
{
62+
// go to the planet
63+
var container = facility.Container;
64+
OnSpaceObjectSelected(this, container);
65+
}
66+
else if (context is Technology tech)
67+
{
68+
// go to research screen
69+
OnTechnologySelected(this, tech);
70+
}
71+
else if (context is IHull hull)
72+
{
73+
// go to design screen and create a new design using this hull
74+
OnHullSelected(this, hull);
75+
}
76+
else if (context is ComponentTemplate || context is Mount)
77+
{
78+
// go to design screen
79+
OnHullSelected(this, null);
80+
}
81+
else if (context is IBattle battle)
82+
{
83+
// show battle results
84+
OnBattleSelected(this, battle);
85+
}
86+
else if (context is IMessage msg)
87+
{
88+
// show diplomacy screen
89+
OnMessageSelected(this, msg);
90+
}
91+
else if (context is StarSystem sys)
92+
{
93+
// navigate game form to that system
94+
OnStarSystemSelected(this, sys);
95+
}
96+
97+
// TODO - more types of goto-messages
98+
}
99+
}
100+
101+
public bool CanNavigate(LogMessage message)
102+
{
103+
if (message is PictorialLogMessage<IPictorial> pm)
104+
{
105+
return pm.Context is ISpaceObject
106+
|| pm.Context is IUnit
107+
|| pm.Context is Facility
108+
|| pm.Context is Technology
109+
|| pm.Context is IHull
110+
|| pm.Context is ComponentTemplate
111+
|| pm.Context is Mount
112+
|| pm.Context is IBattle
113+
|| pm.Context is IMessage
114+
|| pm.Context is StarSystem;
115+
}
116+
return false;
117+
}
118+
119+
public event EventHandler<ISpaceObject> OnSpaceObjectSelected = (sender, e) => { };
120+
121+
public event EventHandler<Technology> OnTechnologySelected = (sender, e) => { };
122+
123+
public event EventHandler<IHull?> OnHullSelected = (sender, e) => { };
124+
125+
public event EventHandler<IBattle> OnBattleSelected = (sender, e) => { };
126+
127+
public event EventHandler<IMessage> OnMessageSelected = (sender, e) => { };
128+
129+
public event EventHandler<StarSystem> OnStarSystemSelected = (sender, e) => { };
130+
}

Diff for: FrEee.UI.Blazor/Views/ViewModelBase.cs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace FrEee.UI.Blazor.Views;
9+
public class ViewModelBase
10+
: INotifyPropertyChanged
11+
{
12+
public event PropertyChangedEventHandler? PropertyChanged;
13+
}

Diff for: FrEee.UI.WinForms/Forms/BlazorForm.cs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Drawing;
4+
using System.Windows.Forms;
5+
using FrEee.UI.WinForms.Forms;
6+
using FrEee.UI.WinForms.Utility.Extensions;
7+
using Microsoft.AspNetCore.Components;
8+
using Microsoft.AspNetCore.Components.WebView.WindowsForms;
9+
10+
namespace FrEee.UI.WinForms.Controls
11+
{
12+
public partial class BlazorForm
13+
: GameForm
14+
{
15+
public BlazorForm()
16+
{
17+
// set up control
18+
SuspendLayout();
19+
BackColor = Color.Black;
20+
ForeColor = Color.White;
21+
Margin = new(0);
22+
Name = "BlazorForm";
23+
24+
// set up Blazor
25+
try
26+
{
27+
var parameters = new Dictionary<string, object?> { ["VM"] = VM };
28+
var blazorView = new BlazorWebView
29+
{
30+
HostPage = "index.html",
31+
Padding = new(0),
32+
Margin = new(0),
33+
Dock = DockStyle.Fill,
34+
Location = new(0, 0),
35+
Name = "blazorView",
36+
StartPath = "/",
37+
TabIndex = 0,
38+
Text = "blazorWebView1",
39+
AutoScroll = false
40+
};
41+
blazorView.InitializeServices(); // the code in this method can't go here directly because it crashes th eWinForms designer
42+
blazorView.RootComponents.Add(new RootComponent("#app", BlazorComponentType, parameters));
43+
Controls.Add(blazorView);
44+
}
45+
catch
46+
{
47+
// Blazor could not be loaded, display a dummy label
48+
VM = new();
49+
Controls.Add(new Label { Text = "Blazor " + BlazorComponentType.Name, Dock = DockStyle.Fill });
50+
}
51+
52+
ResumeLayout(false);
53+
}
54+
55+
/// <summary>
56+
/// The type of Blazor component to display. Should be overridden.
57+
/// </summary>
58+
protected virtual Type BlazorComponentType { get; } = typeof(ComponentBase);
59+
60+
/// <summary>
61+
/// The view model for this Blazor control. Should be overridden.
62+
/// </summary>
63+
protected virtual object VM { get; } = new();
64+
65+
private void InitializeComponent()
66+
{
67+
68+
}
69+
}
70+
}

Diff for: FrEee.UI.WinForms/Forms/BlazorForm.resx

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<root>
3+
<!--
4+
Microsoft ResX Schema
5+
6+
Version 2.0
7+
8+
The primary goals of this format is to allow a simple XML format
9+
that is mostly human readable. The generation and parsing of the
10+
various data types are done through the TypeConverter classes
11+
associated with the data types.
12+
13+
Example:
14+
15+
... ado.net/XML headers & schema ...
16+
<resheader name="resmimetype">text/microsoft-resx</resheader>
17+
<resheader name="version">2.0</resheader>
18+
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19+
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20+
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21+
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22+
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23+
<value>[base64 mime encoded serialized .NET Framework object]</value>
24+
</data>
25+
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26+
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27+
<comment>This is a comment</comment>
28+
</data>
29+
30+
There are any number of "resheader" rows that contain simple
31+
name/value pairs.
32+
33+
Each data row contains a name, and value. The row also contains a
34+
type or mimetype. Type corresponds to a .NET class that support
35+
text/value conversion through the TypeConverter architecture.
36+
Classes that don't support this are serialized and stored with the
37+
mimetype set.
38+
39+
The mimetype is used for serialized objects, and tells the
40+
ResXResourceReader how to depersist the object. This is currently not
41+
extensible. For a given mimetype the value must be set accordingly:
42+
43+
Note - application/x-microsoft.net.object.binary.base64 is the format
44+
that the ResXResourceWriter will generate, however the reader can
45+
read any of the formats listed below.
46+
47+
mimetype: application/x-microsoft.net.object.binary.base64
48+
value : The object must be serialized with
49+
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
50+
: and then encoded with base64 encoding.
51+
52+
mimetype: application/x-microsoft.net.object.soap.base64
53+
value : The object must be serialized with
54+
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55+
: and then encoded with base64 encoding.
56+
57+
mimetype: application/x-microsoft.net.object.bytearray.base64
58+
value : The object must be serialized into a byte array
59+
: using a System.ComponentModel.TypeConverter
60+
: and then encoded with base64 encoding.
61+
-->
62+
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63+
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
64+
<xsd:element name="root" msdata:IsDataSet="true">
65+
<xsd:complexType>
66+
<xsd:choice maxOccurs="unbounded">
67+
<xsd:element name="metadata">
68+
<xsd:complexType>
69+
<xsd:sequence>
70+
<xsd:element name="value" type="xsd:string" minOccurs="0" />
71+
</xsd:sequence>
72+
<xsd:attribute name="name" use="required" type="xsd:string" />
73+
<xsd:attribute name="type" type="xsd:string" />
74+
<xsd:attribute name="mimetype" type="xsd:string" />
75+
<xsd:attribute ref="xml:space" />
76+
</xsd:complexType>
77+
</xsd:element>
78+
<xsd:element name="assembly">
79+
<xsd:complexType>
80+
<xsd:attribute name="alias" type="xsd:string" />
81+
<xsd:attribute name="name" type="xsd:string" />
82+
</xsd:complexType>
83+
</xsd:element>
84+
<xsd:element name="data">
85+
<xsd:complexType>
86+
<xsd:sequence>
87+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
88+
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
89+
</xsd:sequence>
90+
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
91+
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
92+
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
93+
<xsd:attribute ref="xml:space" />
94+
</xsd:complexType>
95+
</xsd:element>
96+
<xsd:element name="resheader">
97+
<xsd:complexType>
98+
<xsd:sequence>
99+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
100+
</xsd:sequence>
101+
<xsd:attribute name="name" type="xsd:string" use="required" />
102+
</xsd:complexType>
103+
</xsd:element>
104+
</xsd:choice>
105+
</xsd:complexType>
106+
</xsd:element>
107+
</xsd:schema>
108+
<resheader name="resmimetype">
109+
<value>text/microsoft-resx</value>
110+
</resheader>
111+
<resheader name="version">
112+
<value>2.0</value>
113+
</resheader>
114+
<resheader name="reader">
115+
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116+
</resheader>
117+
<resheader name="writer">
118+
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119+
</resheader>
120+
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
121+
<value>False</value>
122+
</metadata>
123+
</root>

0 commit comments

Comments
 (0)