Skip to content

Commit 5b3611c

Browse files
committed
Add CSV export and improve UI
1 parent 63e476c commit 5b3611c

File tree

11 files changed

+279
-60
lines changed

11 files changed

+279
-60
lines changed

Ray2StringEd/App.xaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<converters:NotNullConverter x:Key="NotNullConverter" />
1111

1212
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
13-
<Setter Property="Padding" Value="5 2" />
13+
<Setter Property="Padding" Value="6 2" />
1414
</Style>
1515

1616
<Style TargetType="MenuItem" x:Key="MenuBarItem">
@@ -20,6 +20,15 @@
2020
<Style TargetType="ListViewItem">
2121
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
2222
</Style>
23+
24+
<Style TargetType="GroupBox">
25+
<Setter Property="Padding" Value="2 5" />
26+
</Style>
27+
28+
<Style x:Key="SideButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
29+
<Setter Property="Width" Value="80"/>
30+
<Setter Property="Margin" Value="2 0 2 4" />
31+
</Style>
2332

2433
</Application.Resources>
2534
</Application>

Ray2StringEd/Csvutils.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Windows;
7+
using CsvHelper;
8+
9+
namespace Ray2StringEd
10+
{
11+
public static class CsvUtils
12+
{
13+
public static void ImportCsv(IEnumerable<FixString> strings, string path)
14+
{
15+
Dictionary<long, FixString> dStrings = strings.ToDictionary(s => s.Offset);
16+
int errorCounter = 0;
17+
int importedCounter = 0;
18+
19+
using (StreamReader reader = new StreamReader(path))
20+
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
21+
{
22+
csv.Configuration.RegisterClassMap<FixStringMap>();
23+
csv.Read();
24+
csv.ReadHeader();
25+
while (csv.Read())
26+
{
27+
FixString imported = csv.GetRecord<FixString>();
28+
29+
try
30+
{
31+
if (!dStrings.TryGetValue(imported.Offset, out FixString current))
32+
throw new Exception("Offset not found.");
33+
34+
if (imported.DwordLength != current.DwordLength)
35+
throw new Exception(
36+
$"DWORD length does not match.\nExpected {current.DwordLength}, got {imported.DwordLength}.");
37+
38+
if (imported.Text.Length > current.MaxTextLength)
39+
throw new Exception(
40+
$"String is too long.\nExpected max {current.MaxTextLength} chars, got {imported.Text.Length} chars.");
41+
42+
current.Text = imported.Text;
43+
importedCounter++;
44+
}
45+
catch (Exception e)
46+
{
47+
errorCounter++;
48+
49+
string error = $"Offset 0x{imported.Offset:X}:\n" +
50+
e.Message +
51+
"\nOK - skip current string and continue importing" +
52+
"\nCancel - Stop importing";
53+
54+
MessageBoxResult result = MessageBox.Show(error, "CSV Import Error",
55+
MessageBoxButton.OKCancel, MessageBoxImage.Error, MessageBoxResult.Cancel);
56+
57+
if (result == MessageBoxResult.Cancel) break;
58+
}
59+
}
60+
}
61+
62+
string message = $"Imported {importedCounter} strings.\n" +
63+
$"Errors: {errorCounter}\n" +
64+
$"Total strings in CSV file: {importedCounter + errorCounter}\n" +
65+
$"Total strings in Fix: {dStrings.Count}";
66+
MessageBox.Show(message, "CSV Import", MessageBoxButton.OK, MessageBoxImage.Asterisk);
67+
}
68+
69+
public static void ExportCsv(IEnumerable<FixString> strings, string path)
70+
{
71+
using (StreamWriter writer = new StreamWriter(path, false))
72+
using (CsvWriter csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
73+
{
74+
csv.Configuration.RegisterClassMap<FixStringMap>();
75+
csv.WriteRecords(strings);
76+
}
77+
}
78+
}
79+
}

Ray2StringEd/FixString.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
{
33
public class FixString
44
{
5+
internal FixString() { }
6+
57
public FixString(string text, int dwordLength, long offset)
68
{
79
Text = text;
@@ -10,9 +12,9 @@ public FixString(string text, int dwordLength, long offset)
1012
}
1113

1214
public string Text { get; set; }
13-
public int DwordLength { get; }
14-
public long Offset { get; }
15-
15+
public int DwordLength { get; set; }
16+
public long Offset { get; set; }
17+
1618
public int ByteLength => DwordLength * 4;
1719
public int MaxTextLength => ByteLength - 5;
1820
}

Ray2StringEd/FixStringMap.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using CsvHelper.Configuration;
2+
3+
namespace Ray2StringEd
4+
{
5+
public class FixStringMap : ClassMap<FixString>
6+
{
7+
public FixStringMap()
8+
{
9+
Map(x => x.Offset).Name("Offset");
10+
Map(x => x.DwordLength).Name("Length");
11+
Map(x => x.MaxTextLength).Name("MaxTextLength");
12+
Map(x => x.Text).Name("Text");
13+
}
14+
}
15+
}

Ray2StringEd/MainViewModel.cs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,14 @@ public MainViewModel()
1515
ChooseFileCommand = new RelayCommand(ChooseFile);
1616
ReadFixCommand = new RelayCommand(ReadFix);
1717
WriteFixCommand = new RelayCommand(WriteFix);
18+
ImportCsvCommand = new RelayCommand(ImportCsv);
19+
ExportCsvCommand = new RelayCommand(ExportCsv);
20+
CopyOffsetCommand = new RelayCommand(CopyOffset);
21+
CopyTextCommand = new RelayCommand(CopyText);
1822
}
1923

24+
private long _previousOffset;
25+
2026
private FixManager Manager { get; set; }
2127

2228
public ObservableCollection<FixString> FixStrings { get; set; }
@@ -26,10 +32,14 @@ public MainViewModel()
2632
public ICommand ChooseFileCommand { get; }
2733
public ICommand ReadFixCommand { get; }
2834
public ICommand WriteFixCommand { get; }
35+
public ICommand ImportCsvCommand { get; }
36+
public ICommand ExportCsvCommand { get; }
37+
public ICommand CopyOffsetCommand { get; }
38+
public ICommand CopyTextCommand { get; }
2939

3040
private void ChooseFile()
3141
{
32-
OpenFileDialog dialog = new OpenFileDialog();
42+
OpenFileDialog dialog = new OpenFileDialog { FileName = "Fix.sna", Filter = "SNA File (*.sna)|*.sna|All Files (*.*)|*.*" };
3343
dialog.ShowDialog();
3444

3545
if (!string.IsNullOrWhiteSpace(dialog.FileName))
@@ -46,17 +56,51 @@ private void ReadFix()
4656

4757
private void WriteFix()
4858
{
49-
if (!File.Exists(FixPath)) return;
59+
if (Manager == null || !File.Exists(FixPath)) return;
5060

5161
Manager.BackupFix();
5262
Manager.WriteFix(FixStrings);
5363

5464
MessageBox.Show($"Written {FixStrings.Count} strings to {FixPath}.");
5565
}
5666

67+
private void ImportCsv()
68+
{
69+
if (FixStrings == null) return;
70+
71+
OpenFileDialog dialog = new OpenFileDialog { Filter = "Comma-separated values (*.csv)|*.csv" };
72+
dialog.ShowDialog();
73+
74+
if (!string.IsNullOrWhiteSpace(dialog.FileName))
75+
CsvUtils.ImportCsv(FixStrings, dialog.FileName);
76+
}
77+
78+
private void ExportCsv()
79+
{
80+
if (FixStrings == null) return;
81+
82+
SaveFileDialog dialog = new SaveFileDialog { Filter = "Comma-separated values (*.csv)|*.csv" };
83+
dialog.ShowDialog();
84+
85+
if (string.IsNullOrWhiteSpace(dialog.FileName)) return;
86+
87+
CsvUtils.ExportCsv(FixStrings, dialog.FileName);
88+
MessageBox.Show($"Strings successfully exported to {dialog.FileName}");
89+
}
90+
91+
public void CopyOffset()
92+
{
93+
Clipboard.SetText(SelectedItem?.Offset.ToString("X") ?? string.Empty);
94+
}
95+
96+
public void CopyText()
97+
{
98+
Clipboard.SetText(SelectedItem?.Text ?? string.Empty);
99+
}
100+
57101
public void GoToOffset()
58102
{
59-
OffsetEntryWindow dialog = new OffsetEntryWindow
103+
OffsetEntryWindow dialog = new OffsetEntryWindow(_previousOffset)
60104
{
61105
Owner = Application.Current.MainWindow,
62106
WindowStartupLocation = WindowStartupLocation.CenterOwner
@@ -66,7 +110,11 @@ public void GoToOffset()
66110
if (!dialog.Result) return;
67111

68112
FixString foundOffset = FixStrings.FirstOrDefault(x => x.Offset == dialog.Offset);
69-
if (foundOffset != null) SelectedItem = foundOffset;
113+
if (foundOffset != null)
114+
{
115+
SelectedItem = foundOffset;
116+
_previousOffset = foundOffset.Offset;
117+
}
70118
}
71119
}
72120
}

0 commit comments

Comments
 (0)