mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-11 02:52:35 +02:00
v2.5.0
* (Add) Help - Material manager (F10): Allow to manage material stock and costs with statistic over time * (Add) File - I printed this file (CTRL + P): Allow to select a material and consume resin from stock and print time from the loaded file
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
# Changelog
|
||||
|
||||
## 21/02/2021 - v2.5.0
|
||||
|
||||
* (Add) Help - Material manager (F10): Allow to manage material stock and costs with statistic over time
|
||||
* (Add) File - I printed this file (CTRL + P): Allow to select a material and consume resin from stock and print time from the loaded file
|
||||
|
||||
## 19/02/2021 - v2.4.9
|
||||
|
||||
* **(Fix) PhotonWorkshop files: (#149)**
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using UVtools.Core.Objects;
|
||||
|
||||
namespace UVtools.Core.Managers
|
||||
{
|
||||
public class MaterialManager : BindableBase, IList<Material>
|
||||
{
|
||||
#region Settings
|
||||
|
||||
public static string FilePath;
|
||||
#endregion
|
||||
|
||||
#region Singleton
|
||||
|
||||
private static Lazy<MaterialManager> _instanceHolder =
|
||||
new(() => new MaterialManager());
|
||||
|
||||
/// <summary>
|
||||
/// Instance of <see cref="UserSettings"/> (singleton)
|
||||
/// </summary>
|
||||
public static MaterialManager Instance => _instanceHolder.Value;
|
||||
|
||||
//public static List<Operation> Operations => _instance.Operations;
|
||||
#endregion
|
||||
|
||||
#region Members
|
||||
|
||||
private ObservableCollection<Material> _materials = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public ObservableCollection<Material> Materials
|
||||
{
|
||||
get => _materials;
|
||||
set => RaiseAndSetIfChanged(ref _materials, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total number of bottles in stock
|
||||
/// </summary>
|
||||
public int BottlesInStock => this.Sum(material => material.BottlesInStock);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total number of bottles ever owned
|
||||
/// </summary>
|
||||
public int OwnedBottles => this.Sum(material => material.OwnedBottles);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total of consumed volume in milliliters
|
||||
/// </summary>
|
||||
public decimal ConsumedVolume => this.Sum(material => material.ConsumedVolume);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total of consumed volume in liters
|
||||
/// </summary>
|
||||
public decimal ConsumedVolumeLiters => this.Sum(material => material.ConsumedVolumeLiters);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total volume in stock in milliliters
|
||||
/// </summary>
|
||||
public decimal VolumeInStock => this.Sum(material => material.VolumeInStock);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total volume in stock in liters
|
||||
/// </summary>
|
||||
public decimal VolumeInStockLiters => VolumeInStock / 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total costs
|
||||
/// </summary>
|
||||
public decimal TotalCost => this.Sum(material => material.TotalCost);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total print time in hours
|
||||
/// </summary>
|
||||
public double PrintTime => this.Sum(material => material.PrintTime);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total print time
|
||||
/// </summary>
|
||||
public TimeSpan PrintTimeSpan => TimeSpan.FromHours(PrintTime);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
private MaterialManager()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public Material this[int index]
|
||||
{
|
||||
get => _materials[index];
|
||||
set => _materials[index] = value;
|
||||
}
|
||||
|
||||
public Material this[uint index]
|
||||
{
|
||||
get => _materials[(int) index];
|
||||
set => _materials[(int) index] = value;
|
||||
}
|
||||
|
||||
public Material this[Material material]
|
||||
{
|
||||
get
|
||||
{
|
||||
var index = IndexOf(material);
|
||||
return index < 0 ? this[index] : null;
|
||||
}
|
||||
set
|
||||
{
|
||||
var index = IndexOf(material);
|
||||
if(index >= 0) this[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<Material> GetEnumerator() => _materials.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public void Add(Material item)
|
||||
{
|
||||
_materials.Add(item);
|
||||
RaisePropertiesChanged();
|
||||
}
|
||||
|
||||
public void Add(Material item, bool save)
|
||||
{
|
||||
Add(item);
|
||||
if (save) Save();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_materials.Clear();
|
||||
RaisePropertiesChanged();
|
||||
}
|
||||
|
||||
public void Clear(bool save)
|
||||
{
|
||||
Clear();
|
||||
if(save) Save();
|
||||
}
|
||||
|
||||
|
||||
public bool Contains(Material item) => _materials.Contains(item);
|
||||
|
||||
public void CopyTo(Material[] array, int arrayIndex)
|
||||
{
|
||||
_materials.CopyTo(array, arrayIndex);
|
||||
RaisePropertiesChanged();
|
||||
}
|
||||
|
||||
public bool Remove(Material item)
|
||||
{
|
||||
if (_materials.Remove(item))
|
||||
{
|
||||
RaisePropertiesChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Remove(Material item, bool save)
|
||||
{
|
||||
Remove(item);
|
||||
if (save) Save();
|
||||
}
|
||||
|
||||
public int Count => _materials.Count;
|
||||
public bool IsReadOnly => false;
|
||||
public int IndexOf(Material item) => _materials.IndexOf(item);
|
||||
|
||||
public void Insert(int index, Material item)
|
||||
{
|
||||
_materials.Insert(index, item);
|
||||
RaisePropertiesChanged();
|
||||
}
|
||||
|
||||
public void Insert(int index, Material item, bool save)
|
||||
{
|
||||
Insert(index, item);
|
||||
if (save) Save();
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
_materials.RemoveAt(index);
|
||||
RaisePropertiesChanged();
|
||||
}
|
||||
|
||||
public void RemoveAt(int index, bool save)
|
||||
{
|
||||
RemoveAt(index);
|
||||
if (save) Save();
|
||||
}
|
||||
|
||||
public void RaisePropertiesChanged()
|
||||
{
|
||||
RaisePropertyChanged(nameof(BottlesInStock));
|
||||
RaisePropertyChanged(nameof(OwnedBottles));
|
||||
RaisePropertyChanged(nameof(ConsumedVolume));
|
||||
RaisePropertyChanged(nameof(ConsumedVolumeLiters));
|
||||
RaisePropertyChanged(nameof(VolumeInStock));
|
||||
RaisePropertyChanged(nameof(VolumeInStockLiters));
|
||||
RaisePropertyChanged(nameof(TotalCost));
|
||||
RaisePropertyChanged(nameof(PrintTime));
|
||||
RaisePropertyChanged(nameof(PrintTimeSpan));
|
||||
RaisePropertyChanged(nameof(Count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load settings from file
|
||||
/// </summary>
|
||||
public static void Load()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(FilePath) || !File.Exists(FilePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var serializer = new XmlSerializer(Instance.GetType());
|
||||
try
|
||||
{
|
||||
using var myXmlReader = new StreamReader(FilePath);
|
||||
var instance = (MaterialManager)serializer.Deserialize(myXmlReader);
|
||||
_instanceHolder = new Lazy<MaterialManager>(() => instance);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save settings to file
|
||||
/// </summary>
|
||||
public static void Save()
|
||||
{
|
||||
var serializer = new XmlSerializer(Instance.GetType());
|
||||
try
|
||||
{
|
||||
using var myXmlWriter = new StreamWriter(FilePath);
|
||||
serializer.Serialize(myXmlWriter, Instance);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void SortByName()
|
||||
{
|
||||
var materials = _materials.ToList();
|
||||
materials.Sort((material, material1) => string.Compare(material.Name, material1.Name, StringComparison.Ordinal));
|
||||
Materials = new ObservableCollection<Material>(materials);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,17 @@ namespace UVtools.Core.Objects
|
||||
/// <summary>
|
||||
/// Represents a material to feed in the printer
|
||||
/// </summary>
|
||||
public class Material : BindableBase
|
||||
public class Material : BindableBase, ICloneable
|
||||
{
|
||||
#region Members
|
||||
private string _name;
|
||||
private decimal _bottleVolume = 1000;
|
||||
private uint _bottleVolume = 1000;
|
||||
private decimal _density = 1;
|
||||
private decimal _bottleCost = 30;
|
||||
private int _bottlesInStock = 1;
|
||||
private decimal _bottleRemainingVolume = 1000;
|
||||
private decimal _totalConsumedVolume;
|
||||
private double _totalPrintTime;
|
||||
private decimal _consumedVolume;
|
||||
private double _printTime;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -37,14 +37,16 @@ namespace UVtools.Core.Objects
|
||||
/// <summary>
|
||||
/// Gets or sets the bottle volume in milliliters
|
||||
/// </summary>
|
||||
public decimal BottleVolume
|
||||
public uint BottleVolume
|
||||
{
|
||||
get => _bottleVolume;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _bottleVolume, value)) return;
|
||||
RaisePropertyChanged(nameof(BottleWeight));
|
||||
RaisePropertyChanged(nameof(TotalConsumedBottles));
|
||||
RaisePropertyChanged(nameof(ConsumedBottles));
|
||||
RaisePropertyChanged(nameof(TotalCost));
|
||||
RaisePropertyChanged(nameof(VolumeInStock));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,16 +74,28 @@ namespace UVtools.Core.Objects
|
||||
public decimal BottleCost
|
||||
{
|
||||
get => _bottleCost;
|
||||
set => RaiseAndSetIfChanged(ref _bottleCost, value);
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _bottleCost, value)) return;
|
||||
RaisePropertyChanged(nameof(TotalCost));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal TotalCost => OwnedBottles * _bottleCost;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of bottles in stock
|
||||
/// </summary>
|
||||
public int BottlesInStock
|
||||
{
|
||||
get => _bottlesInStock;
|
||||
set => RaiseAndSetIfChanged(ref _bottlesInStock, value);
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _bottlesInStock, value)) return;
|
||||
RaisePropertyChanged(nameof(OwnedBottles));
|
||||
RaisePropertyChanged(nameof(TotalCost));
|
||||
RaisePropertyChanged(nameof(VolumeInStock));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -89,47 +103,75 @@ namespace UVtools.Core.Objects
|
||||
/// </summary>
|
||||
public decimal BottleRemainingVolume
|
||||
{
|
||||
get => _bottleRemainingVolume;
|
||||
set => RaiseAndSetIfChanged(ref _bottleRemainingVolume, value);
|
||||
get => Math.Round(_bottleRemainingVolume, 2);
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _bottleRemainingVolume, value)) return;
|
||||
RaisePropertyChanged(nameof(VolumeInStock));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total available volume in stock in milliliters
|
||||
/// </summary>
|
||||
public decimal VolumeInStock => _bottlesInStock * _bottleVolume - (_bottleVolume - _bottleRemainingVolume);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of consumed bottles
|
||||
/// </summary>
|
||||
public uint TotalConsumedBottles => (uint) Math.Floor(_totalConsumedVolume / _bottleVolume);
|
||||
public uint ConsumedBottles => (uint) Math.Floor(_consumedVolume / _bottleVolume);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total number of owned bottles
|
||||
/// </summary>
|
||||
public int OwnedBottles => (int) (_bottlesInStock + ConsumedBottles);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total number of consumed volume in milliliters
|
||||
/// </summary>
|
||||
public decimal TotalConsumedVolume
|
||||
public decimal ConsumedVolume
|
||||
{
|
||||
get => _totalConsumedVolume;
|
||||
set => RaiseAndSetIfChanged(ref _totalConsumedVolume, value);
|
||||
get => _consumedVolume;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _consumedVolume, value)) return;
|
||||
RaisePropertyChanged(nameof(ConsumedVolumeLiters));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets total number of consumed volume in liters
|
||||
/// </summary>
|
||||
public decimal ConsumedVolumeLiters => ConsumedVolume / 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total print time using with material in hours
|
||||
/// </summary>
|
||||
public double TotalPrintTime
|
||||
public double PrintTime
|
||||
{
|
||||
get => _totalPrintTime;
|
||||
set => RaiseAndSetIfChanged(ref _totalPrintTime, value);
|
||||
get => _printTime;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _printTime, value)) return;
|
||||
RaisePropertyChanged(nameof(PrintTimeSpan));
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan TotalPrintTimeSpan => TimeSpan.FromHours(_totalPrintTime);
|
||||
public TimeSpan PrintTimeSpan => TimeSpan.FromHours(_printTime);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public Material() { }
|
||||
|
||||
public Material(string name, decimal bottleVolume = 1000, decimal density = 1, decimal bottleCost = 30, int bottlesInStock = 1)
|
||||
public Material(string name, uint bottleVolume = 1000, decimal density = 1, decimal bottleCost = 30, int bottlesInStock = 1)
|
||||
{
|
||||
_name = name;
|
||||
_bottleVolume = bottleVolume;
|
||||
_density = density;
|
||||
_bottleCost = bottleCost;
|
||||
_bottlesInStock = bottlesInStock;
|
||||
_bottleRemainingVolume = bottleVolume;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -155,7 +197,17 @@ namespace UVtools.Core.Objects
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Name)}: {Name}, {nameof(BottleVolume)}: {BottleVolume}ml, {nameof(BottleWeight)}: {BottleWeight}g, {nameof(Density)}: {Density}g/ml, {nameof(BottleCost)}: {BottleCost}, {nameof(BottlesInStock)}: {BottlesInStock}, {nameof(BottleRemainingVolume)}: {BottleRemainingVolume}ml, {nameof(TotalConsumedBottles)}: {TotalConsumedBottles}, {nameof(TotalConsumedVolume)}: {TotalConsumedVolume}ml, {nameof(TotalPrintTime)}: {TotalPrintTime:F4}h";
|
||||
return $"{_name} ({_bottleRemainingVolume}/{VolumeInStock}ml)";
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return MemberwiseClone();
|
||||
}
|
||||
|
||||
public Material CloneMaterial()
|
||||
{
|
||||
return (Material)Clone();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -200,8 +252,9 @@ namespace UVtools.Core.Objects
|
||||
}
|
||||
|
||||
BottlesInStock -= consumedBottles;
|
||||
ConsumedVolume += volume;
|
||||
|
||||
AddPrintTime(printSeconds);
|
||||
AddPrintTimeSeconds(printSeconds);
|
||||
|
||||
return _bottlesInStock > 0;
|
||||
}
|
||||
@@ -210,10 +263,10 @@ namespace UVtools.Core.Objects
|
||||
/// Add print time with this material
|
||||
/// </summary>
|
||||
/// <param name="seconds">Seconds to add</param>
|
||||
public void AddPrintTime(double seconds)
|
||||
public void AddPrintTimeSeconds(double seconds)
|
||||
{
|
||||
if (seconds <= 0) return;
|
||||
TotalPrintTime += seconds / 60 / 60;
|
||||
PrintTime += seconds / 60 / 60;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Managers;
|
||||
using UVtools.Core.Objects;
|
||||
|
||||
namespace UVtools.Core.Operations
|
||||
{
|
||||
[Serializable]
|
||||
public class OperationIPrintedThisFile : Operation
|
||||
{
|
||||
#region Members
|
||||
private decimal _volume;
|
||||
private float _printTime;
|
||||
private Material _materialItem;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
|
||||
|
||||
public override bool CanROI => false;
|
||||
public override bool CanHaveProfiles => false;
|
||||
public override string ButtonOkText => "Consume";
|
||||
|
||||
public override string Title => "I printed this file";
|
||||
public override string Description => "Select a material and consume resin from stock and print time.";
|
||||
|
||||
public override string ConfirmationText =>
|
||||
$"consume {_volume}ml and {PrintTimeHours}h on:\n{_materialItem} ?";
|
||||
|
||||
public override string ProgressTitle =>
|
||||
$"Consuming";
|
||||
|
||||
public override string ProgressAction => "Consumed";
|
||||
|
||||
public override StringTag Validate(params object[] parameters)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (_materialItem is null)
|
||||
{
|
||||
sb.AppendLine("You must select an material.");
|
||||
}
|
||||
if (_volume <= 0)
|
||||
{
|
||||
sb.AppendLine("Volume must be higher than 0ml.");
|
||||
}
|
||||
if (_printTime <= 0)
|
||||
{
|
||||
sb.AppendLine("Print time must be higher than 0s.");
|
||||
}
|
||||
|
||||
return new StringTag(sb.ToString());
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var result = $"{_volume}ml {PrintTimeHours}h";
|
||||
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public Material MaterialItem
|
||||
{
|
||||
get => _materialItem;
|
||||
set => RaiseAndSetIfChanged(ref _materialItem, value);
|
||||
}
|
||||
|
||||
public decimal Volume
|
||||
{
|
||||
get => _volume;
|
||||
set => RaiseAndSetIfChanged(ref _volume, value);
|
||||
}
|
||||
|
||||
public float PrintTime
|
||||
{
|
||||
get => _printTime;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _printTime, value)) return;
|
||||
RaisePropertyChanged(nameof(PrintTimeHours));
|
||||
}
|
||||
}
|
||||
|
||||
public float PrintTimeHours => _printTime / 60 / 60;
|
||||
|
||||
public MaterialManager Manager => MaterialManager.Instance;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public OperationIPrintedThisFile() { }
|
||||
|
||||
public OperationIPrintedThisFile(FileFormat slicerFile) : base(slicerFile) { }
|
||||
|
||||
public override void InitWithSlicerFile()
|
||||
{
|
||||
base.InitWithSlicerFile();
|
||||
_volume = (decimal) SlicerFile.MaterialMilliliters;
|
||||
_printTime = SlicerFile.PrintTime;
|
||||
MaterialManager.Load();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
if (MaterialItem is null) return !progress.Token.IsCancellationRequested;
|
||||
|
||||
MaterialItem.Consume(_volume, _printTime);
|
||||
|
||||
MaterialManager.Save();
|
||||
return !progress.Token.IsCancellationRequested;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
|
||||
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
|
||||
<Version>2.4.9</Version>
|
||||
<Version>2.5.0</Version>
|
||||
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
||||
<PackageIcon>UVtools.png</PackageIcon>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
@@ -44,7 +44,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinarySerializer" Version="8.5.3" />
|
||||
<PackageReference Include="BinarySerializer" Version="8.6.0" />
|
||||
<PackageReference Include="Emgu.CV" Version="4.5.1.4349" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
|
||||
@@ -22,6 +22,7 @@ using Avalonia.ThemeManager;
|
||||
using Emgu.CV;
|
||||
using UVtools.Core;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Managers;
|
||||
using UVtools.WPF.Extensions;
|
||||
using UVtools.WPF.Structures;
|
||||
|
||||
@@ -52,6 +53,9 @@ namespace UVtools.WPF
|
||||
|
||||
OperationProfiles.Load();
|
||||
|
||||
MaterialManager.FilePath = Path.Combine(UserSettings.SettingsFolder, "materials.xml");
|
||||
MaterialManager.Load();
|
||||
|
||||
/*ThemeSelector = ThemeSelector.Create(Path.Combine(ApplicationPath, "Assets", "Themes"));
|
||||
ThemeSelector.LoadSelectedTheme(Path.Combine(UserSettings.SettingsFolder, "selected.theme"));
|
||||
if (ThemeSelector.SelectedTheme.Name == "UVtoolsDark" || ThemeSelector.SelectedTheme.Name == "Light")
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 162 B |
@@ -0,0 +1,53 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="UVtools.WPF.Controls.Tools.ToolIPrintedThisFileControl">
|
||||
|
||||
<Grid RowDefinitions="Auto,10,Auto,10,Auto"
|
||||
ColumnDefinitions="Auto,10,Auto">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="The material you want to consume from (remaining in current bottle / total in stock)"
|
||||
Text="Material:"/>
|
||||
<ComboBox Grid.Row="0" Grid.Column="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
MinWidth="600"
|
||||
Items="{Binding Operation.Manager}"
|
||||
SelectedItem="{Binding Operation.MaterialItem}"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="Volume:"/>
|
||||
|
||||
<StackPanel Grid.Row="2" Grid.Column="2"
|
||||
Orientation="Horizontal" Spacing="5">
|
||||
<NumericUpDown Minimum="1"
|
||||
Maximum="1000000"
|
||||
Increment="1"
|
||||
MinWidth="200"
|
||||
Value="{Binding Operation.Volume}"/>
|
||||
<TextBlock VerticalAlignment="Center" Text="ml"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="Print time:"/>
|
||||
|
||||
<StackPanel Grid.Row="4" Grid.Column="2"
|
||||
Orientation="Horizontal" Spacing="5">
|
||||
<NumericUpDown Minimum="1"
|
||||
Maximum="100000000"
|
||||
Increment="1"
|
||||
MinWidth="200"
|
||||
FormatString="F2"
|
||||
Value="{Binding Operation.PrintTime}"/>
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Text="{Binding Operation.PrintTimeHours, StringFormat=s / {0:N4}h}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Avalonia.Markup.Xaml;
|
||||
using UVtools.Core.Operations;
|
||||
|
||||
namespace UVtools.WPF.Controls.Tools
|
||||
{
|
||||
public class ToolIPrintedThisFileControl : ToolControl
|
||||
{
|
||||
public OperationIPrintedThisFile Operation => BaseOperation as OperationIPrintedThisFile;
|
||||
|
||||
public ToolIPrintedThisFileControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
BaseOperation = new OperationIPrintedThisFile(SlicerFile);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,15 @@
|
||||
</MenuItem>
|
||||
|
||||
<Separator/>
|
||||
|
||||
<MenuItem
|
||||
Header="I _printed this file" HotKey="Ctrl+P" InputGesture="Ctrl+P"
|
||||
IsEnabled="{Binding IsFileLoaded}"
|
||||
Command="{Binding IPrintedThisFile}">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="\Assets\Icons\flask-16x16.png"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
Name="MainMenu.File.Extract"
|
||||
@@ -182,6 +191,16 @@
|
||||
|
||||
<Separator/>
|
||||
|
||||
<MenuItem
|
||||
Header="_Material manager"
|
||||
HotKey="F10"
|
||||
InputGesture="F10"
|
||||
Command="{Binding MenuHelpMaterialManagerClicked}">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="\Assets\Icons\flask-16x16.png"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
Header="_Install profiles into PrusaSlicer"
|
||||
Command="{Binding MenuHelpInstallProfilesClicked}">
|
||||
@@ -189,6 +208,8 @@
|
||||
<Image Source="\Assets\Icons\CNCMachine-16x16.png"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
|
||||
<Separator/>
|
||||
|
||||
<MenuItem
|
||||
Header="_Open settings folder"
|
||||
|
||||
@@ -805,6 +805,11 @@ namespace UVtools.WPF
|
||||
App.StartProcess(UserSettings.SettingsFolder);
|
||||
}
|
||||
|
||||
private async void MenuHelpMaterialManagerClicked()
|
||||
{
|
||||
await new MaterialManagerWindow().ShowDialog(this);
|
||||
}
|
||||
|
||||
public async void MenuHelpInstallProfilesClicked()
|
||||
{
|
||||
var PEFolder = App.GetPrusaSlicerDirectory();
|
||||
@@ -818,7 +823,7 @@ namespace UVtools.WPF
|
||||
"Unable to detect PrusaSlicer") == ButtonResult.Yes) App.OpenBrowser("https://www.prusa3d.com/prusaslicer/");
|
||||
return;
|
||||
}
|
||||
await new PrusaSlicerManager().ShowDialog(this);
|
||||
await new PrusaSlicerManagerWindow().ShowDialog(this);
|
||||
}
|
||||
|
||||
public async void MenuNewVersionClicked()
|
||||
@@ -1149,6 +1154,8 @@ namespace UVtools.WPF
|
||||
ProgressWindow = new ProgressWindow(title);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async void ConvertToOnTapped(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not MenuItem item) return;
|
||||
@@ -1295,6 +1302,11 @@ namespace UVtools.WPF
|
||||
return task;
|
||||
}
|
||||
|
||||
public async void IPrintedThisFile()
|
||||
{
|
||||
await ShowRunOperation(typeof(OperationIPrintedThisFile));
|
||||
}
|
||||
|
||||
public async void ExtractFile()
|
||||
{
|
||||
if (!IsFileLoaded) return;
|
||||
@@ -1413,6 +1425,9 @@ namespace UVtools.WPF
|
||||
|
||||
CanSave = true;
|
||||
return true;
|
||||
case OperationIPrintedThisFile operation:
|
||||
operation.Execute();
|
||||
return true;
|
||||
case OperationRepairLayers operation:
|
||||
if (Issues is null)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<Version>2.4.9</Version>
|
||||
<Version>2.5.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
@@ -75,4 +75,9 @@
|
||||
</AvaloniaResource>
|
||||
<AvaloniaResource Include="Assets\Icons\*" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Windows\PrusaSlicerManagerWindow.axaml.cs">
|
||||
<DependentUpon>PrusaSlicerManagerWindow.axaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
<controls:WindowEx xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:UVtools.WPF.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="450"
|
||||
x:Class="UVtools.WPF.Windows.MaterialManagerWindow"
|
||||
Title="Material manager"
|
||||
MinWidth="900"
|
||||
MinHeight="600"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Icon="/Assets/Icons/UVtools.ico">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,Auto,*">
|
||||
<Border Grid.Row="0" Padding="5">
|
||||
<Expander IsExpanded="True">
|
||||
<Expander.Header>
|
||||
<TextBlock Text="Global statistics"
|
||||
FontWeight="Bold"
|
||||
Cursor="Hand"/>
|
||||
</Expander.Header>
|
||||
|
||||
<StackPanel>
|
||||
<!--<Button VerticalAlignment="Center"
|
||||
Command="{Binding RefreshStatistics}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<Image Source="/Assets/Icons/refresh-16x16.png"/>
|
||||
<TextBlock Text="Refresh statistics"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
!-->
|
||||
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="Bottles in stock:" VerticalAlignment="Center" FontWeight="Bold"/>
|
||||
<TextBox Classes="TransparentReadOnly"
|
||||
Text="{Binding Manager.BottlesInStock, StringFormat=\{0:N0\}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock Text="Owned bottles:" VerticalAlignment="Center" FontWeight="Bold"/>
|
||||
<TextBox Classes="TransparentReadOnly"
|
||||
Text="{Binding Manager.OwnedBottles, StringFormat=\{0:N0\}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock Text="Consumed volume:" VerticalAlignment="Center" FontWeight="Bold"/>
|
||||
<TextBox Classes="TransparentReadOnly"
|
||||
Text="{Binding Manager.ConsumedVolumeLiters, StringFormat=\{0:N4\}}"/>
|
||||
<TextBlock Text="liters" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock Text="Volume in stock:" VerticalAlignment="Center" FontWeight="Bold"/>
|
||||
<TextBox Classes="TransparentReadOnly"
|
||||
Text="{Binding Manager.VolumeInStockLiters, StringFormat=\{0:N4\}}"/>
|
||||
<TextBlock Text="liters" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock Text="Spent:" VerticalAlignment="Center" FontWeight="Bold"/>
|
||||
<TextBox Classes="TransparentReadOnly"
|
||||
Text="{Binding Manager.TotalCost, StringFormat=\{0:N2\}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock Text="Print time:" VerticalAlignment="Center" FontWeight="Bold"/>
|
||||
<TextBox Classes="TransparentReadOnly"
|
||||
Text="{Binding Manager.PrintTimeSpan.TotalDays, StringFormat=\{0:N4\}}"/>
|
||||
<TextBlock Text="days" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</Expander>
|
||||
</Border>
|
||||
|
||||
|
||||
<Border Grid.Row="1" BorderBrush="Black" BorderThickness="1" Padding="5">
|
||||
<Expander IsExpanded="False">
|
||||
<Expander.Header>
|
||||
<TextBlock Text="Add new material"
|
||||
FontWeight="Bold"
|
||||
Cursor="Hand"/>
|
||||
</Expander.Header>
|
||||
|
||||
<Grid
|
||||
RowDefinitions="Auto,10,Auto,10,Auto,10,Auto"
|
||||
ColumnDefinitions="Auto,10,150,5,Auto,20,Auto,10,Auto,5,Auto,20,Auto,10,150,5,Auto,20,Auto,10,Auto,5,Auto">
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="Name:"/>
|
||||
|
||||
<TextBox Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="17"
|
||||
HorizontalAlignment="Stretch"
|
||||
Watermark="A descriptive material name, eg: Epax Hard Grey"
|
||||
Text="{Binding Material.Name}"/>
|
||||
|
||||
<Button
|
||||
Grid.Row="0" Grid.Column="20" Grid.ColumnSpan="3"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{Binding AddNewMaterial}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<Image Source="/Assets/Icons/plus-16x16.png"/>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="Add new material"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="Bottle material volume"
|
||||
Text="Volume:"/>
|
||||
|
||||
<NumericUpDown Grid.Row="2" Grid.Column="2"
|
||||
Minimum="100"
|
||||
Maximum="100000"
|
||||
Increment="100"
|
||||
Value="{Binding Material.BottleVolume}"
|
||||
/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="4"
|
||||
VerticalAlignment="Center"
|
||||
Text="ml"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="6"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="Used to calculate weight and cost"
|
||||
Text="Density:"/>
|
||||
|
||||
<NumericUpDown Grid.Row="2" Grid.Column="8"
|
||||
Minimum="0.1"
|
||||
Maximum="10"
|
||||
Increment="0.1"
|
||||
Value="{Binding Material.Density}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="10"
|
||||
VerticalAlignment="Center"
|
||||
Text="g/ml"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="12"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="One bottle unit cost"
|
||||
Text="Cost:"/>
|
||||
|
||||
<NumericUpDown Grid.Row="2" Grid.Column="14"
|
||||
Minimum="1"
|
||||
Maximum="100000"
|
||||
Increment="1"
|
||||
Value="{Binding Material.BottleCost}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="16"
|
||||
VerticalAlignment="Center"
|
||||
Text=""/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="18"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="Number of bottles in stock"
|
||||
Text="Stock:"/>
|
||||
|
||||
<NumericUpDown Grid.Row="2" Grid.Column="20"
|
||||
Minimum="1"
|
||||
Maximum="100000"
|
||||
Increment="1"
|
||||
Value="{Binding Material.BottlesInStock}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="22"
|
||||
VerticalAlignment="Center"
|
||||
Text="units"/>
|
||||
</Grid>
|
||||
</Expander>
|
||||
</Border>
|
||||
|
||||
<TextBlock Grid.Row="2"
|
||||
VerticalAlignment="Center" FontWeight="Bold"
|
||||
Margin="10,0,0,0"
|
||||
Text="{Binding Manager.Count, StringFormat=Materials: {0}}"/>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="1">
|
||||
|
||||
<Button VerticalAlignment="Center"
|
||||
IsEnabled="{Binding #MaterialsTable.SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Command="{Binding RemoveSelectedMaterials}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<Image Source="/Assets/Icons/trash-16x16.png"/>
|
||||
<TextBlock Text="Remove selected materials"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button VerticalAlignment="Center"
|
||||
IsEnabled="{Binding Manager.Count}"
|
||||
Command="{Binding ClearMaterials}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<Image Source="/Assets/Icons/delete-16x16.png"/>
|
||||
<TextBlock Text="{Binding Manager.Count, StringFormat=Clear {0} materials}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
|
||||
<DataGrid Grid.Row="3"
|
||||
Name="MaterialsTable"
|
||||
CanUserReorderColumns="True"
|
||||
CanUserResizeColumns="True"
|
||||
CanUserSortColumns="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
ClipboardCopyMode="IncludeHeader"
|
||||
VerticalAlignment="Stretch"
|
||||
Items="{Binding Manager.Materials}">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Name"
|
||||
Binding="{Binding Name}"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn Header="Volume (ml)"
|
||||
Binding="{Binding BottleVolume}"
|
||||
Width="Auto" />
|
||||
<!--
|
||||
<DataGridTextColumn Header="Density (g/ml)"
|
||||
Binding="{Binding Density}"
|
||||
Width="Auto" />!-->
|
||||
<DataGridTextColumn Header="Cost"
|
||||
Binding="{Binding BottleCost}"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn Header="In stock"
|
||||
Binding="{Binding BottlesInStock}"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn Header="Consumed bottles"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding ConsumedBottles, StringFormat=\{0:N0\}}"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn Header="Spent"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding TotalCost, StringFormat=\{0:N2\}}"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn Header="Remaining volume (ml)"
|
||||
Binding="{Binding BottleRemainingVolume}"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn Header="Consumed volume (l)"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding ConsumedVolumeLiters, StringFormat=\{0:N3\}}"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn Header="Print time (days)"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding PrintTimeSpan.TotalDays, StringFormat=\{0:N4\}}"
|
||||
Width="Auto" />
|
||||
</DataGrid.Columns>
|
||||
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
|
||||
</controls:WindowEx>
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using DynamicData;
|
||||
using MessageBox.Avalonia.Enums;
|
||||
using UVtools.Core.Managers;
|
||||
using UVtools.Core.Objects;
|
||||
using UVtools.WPF.Controls;
|
||||
using UVtools.WPF.Extensions;
|
||||
|
||||
namespace UVtools.WPF.Windows
|
||||
{
|
||||
public class MaterialManagerWindow : WindowEx
|
||||
{
|
||||
private Material _material = new();
|
||||
private readonly DataGrid _grid;
|
||||
public MaterialManager Manager => MaterialManager.Instance;
|
||||
|
||||
public Material Material
|
||||
{
|
||||
get => _material;
|
||||
set => RaiseAndSetIfChanged(ref _material, value);
|
||||
}
|
||||
|
||||
public MaterialManagerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
|
||||
_grid = this.FindControl<DataGrid>("MaterialsTable");
|
||||
|
||||
MaterialManager.Load(); // Reload
|
||||
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
base.OnClosed(e);
|
||||
MaterialManager.Save(); // Apply changes
|
||||
}
|
||||
|
||||
public void RefreshStatistics()
|
||||
{
|
||||
Manager.RaisePropertiesChanged();
|
||||
}
|
||||
|
||||
public async void AddNewMaterial()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Material.Name))
|
||||
{
|
||||
await this.MessageBoxError("Material name can't be empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Manager.Contains(Material))
|
||||
{
|
||||
await this.MessageBoxError("A material with same name already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
Material.BottleRemainingVolume = Material.BottleVolume;
|
||||
|
||||
if (await this.MessageBoxQuestion("Are you sure you want to add the following material:\n" +
|
||||
$"{Material}") != ButtonResult.Yes) return;
|
||||
|
||||
Manager.Add(Material);
|
||||
Manager.SortByName();
|
||||
MaterialManager.Save();
|
||||
Material = new();
|
||||
}
|
||||
|
||||
public async void RemoveSelectedMaterials()
|
||||
{
|
||||
if (_grid.SelectedItems.Count <= 0) return;
|
||||
if (await this.MessageBoxQuestion($"Are you sure you want to remove {_grid.SelectedItems.Count} materials?") != ButtonResult.Yes) return;
|
||||
Manager.RemoveMany(_grid.SelectedItems.Cast<Material>());
|
||||
MaterialManager.Save();
|
||||
}
|
||||
|
||||
public async void ClearMaterials()
|
||||
{
|
||||
if (Manager.Count == 0) return;
|
||||
if (await this.MessageBoxQuestion($"Are you sure you want to clear {Manager.Count} materials?") != ButtonResult.Yes) return;
|
||||
Manager.Clear(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:UVtools.WPF.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="700"
|
||||
x:Class="UVtools.WPF.Windows.PrusaSlicerManager"
|
||||
x:Class="UVtools.WPF.Windows.PrusaSlicerManagerWindow"
|
||||
Title="Install profiles into PrusaSlicer"
|
||||
Width="900"
|
||||
MinWidth="900"
|
||||
+2
-2
@@ -10,11 +10,11 @@ using UVtools.WPF.Structures;
|
||||
|
||||
namespace UVtools.WPF.Windows
|
||||
{
|
||||
public class PrusaSlicerManager : WindowEx
|
||||
public class PrusaSlicerManagerWindow : WindowEx
|
||||
{
|
||||
public PEProfileFolder[] Profiles { get;}
|
||||
|
||||
public PrusaSlicerManager()
|
||||
public PrusaSlicerManagerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Profiles = new[]
|
||||
Reference in New Issue
Block a user