126 lines
4.7 KiB
C#
126 lines
4.7 KiB
C#
using System;
|
||
using System.IO;
|
||
using System.Text.Json;
|
||
|
||
namespace BoxPacker3D
|
||
{
|
||
/// <summary>
|
||
/// Strongly-typed representation of appsettings.json.
|
||
/// Loaded once at startup via <see cref="Load"/>; falls back to sensible defaults
|
||
/// if the file is missing or malformed.
|
||
/// </summary>
|
||
public class AppSettings
|
||
{
|
||
public DatabaseSettings Database { get; set; } = new();
|
||
public DefaultBoxSettings DefaultBox { get; set; } = new();
|
||
public MaxBoxSettings MaxBox { get; set; } = new();
|
||
public PaddingSettings Padding { get; set; } = new();
|
||
public ViewSettings View { get; set; } = new();
|
||
public UISettings UI { get; set; } = new();
|
||
|
||
public class DatabaseSettings
|
||
{
|
||
public string FilePath { get; set; } = "items.db";
|
||
}
|
||
public class DefaultBoxSettings
|
||
{
|
||
public double Width { get; set; } = 600;
|
||
public double Height { get; set; } = 400;
|
||
public double Depth { get; set; } = 500;
|
||
public double WallThickness { get; set; } = 20;
|
||
}
|
||
public class MaxBoxSettings
|
||
{
|
||
public double Width { get; set; } = 1200;
|
||
public double Height { get; set; } = 800;
|
||
public double Depth { get; set; } = 1000;
|
||
}
|
||
public class PaddingSettings
|
||
{
|
||
public double WallPadding { get; set; } = 10;
|
||
public double ItemPadding { get; set; } = 3;
|
||
}
|
||
public class ViewSettings
|
||
{
|
||
public int InitialRotationX { get; set; } = 30;
|
||
public int InitialRotationY { get; set; } = 30;
|
||
public int InitialZoomPercent { get; set; } = 100;
|
||
}
|
||
public class UISettings
|
||
{
|
||
public int WindowWidth { get; set; } = 1340;
|
||
public int WindowHeight { get; set; } = 840;
|
||
public int LeftPanelWidth { get; set; } = 500;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Loads appsettings.json from the application directory.
|
||
/// If the file is missing or invalid, returns defaults and writes a warning to stderr.
|
||
/// </summary>
|
||
public static AppSettings Load()
|
||
{
|
||
string path = Path.Combine(AppContext.BaseDirectory, "appsettings.json");
|
||
if (!File.Exists(path))
|
||
{
|
||
Console.Error.WriteLine($"[AppSettings] {path} not found – using defaults.");
|
||
return new AppSettings();
|
||
}
|
||
try
|
||
{
|
||
var json = File.ReadAllText(path);
|
||
var opts = new JsonSerializerOptions
|
||
{
|
||
PropertyNameCaseInsensitive = true,
|
||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||
AllowTrailingCommas = true
|
||
};
|
||
return JsonSerializer.Deserialize<AppSettings>(json, opts) ?? new AppSettings();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.Error.WriteLine($"[AppSettings] Failed to parse: {ex.Message} – using defaults.");
|
||
return new AppSettings();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resolves the writable database path.
|
||
///
|
||
/// Priority:
|
||
/// 1. If FilePath is absolute → use it as-is (developer override).
|
||
/// 2. Otherwise → store in %AppData%\BoxPacker3D\<filename> so the
|
||
/// file is always user-writable, even when the app is installed in
|
||
/// Program Files (which is read-only for normal users).
|
||
///
|
||
/// On first run the seed database is copied from the application directory
|
||
/// to AppData so the user starts with the pre-built item catalogue.
|
||
/// </summary>
|
||
public string ResolvedDatabasePath
|
||
{
|
||
get
|
||
{
|
||
if (Path.IsPathRooted(Database.FilePath))
|
||
return Database.FilePath;
|
||
|
||
// User-writable location: %AppData%\BoxPacker3D\items.db
|
||
string appDataDir = Path.Combine(
|
||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||
"BoxPacker3D");
|
||
Directory.CreateDirectory(appDataDir);
|
||
|
||
string userDbPath = Path.Combine(appDataDir, Path.GetFileName(Database.FilePath));
|
||
|
||
// Copy seed database on first run (do not overwrite user's existing data)
|
||
if (!File.Exists(userDbPath))
|
||
{
|
||
string seedPath = Path.Combine(AppContext.BaseDirectory, Database.FilePath);
|
||
if (File.Exists(seedPath))
|
||
File.Copy(seedPath, userDbPath);
|
||
}
|
||
|
||
return userDbPath;
|
||
}
|
||
}
|
||
}
|
||
}
|