feat: Add three-section tank properties and converters for enhanced fluid management
This commit is contained in:
parent
3635169f86
commit
b39c58e6d6
2
App.xaml
2
App.xaml
|
@ -28,6 +28,8 @@
|
||||||
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
<converters:TankLevelToHeightConverter x:Key="TankLevelToHeightConverter"/>
|
<converters:TankLevelToHeightConverter x:Key="TankLevelToHeightConverter"/>
|
||||||
<converters:TankSectionMarginConverter x:Key="TankSectionMarginConverter"/>
|
<converters:TankSectionMarginConverter x:Key="TankSectionMarginConverter"/>
|
||||||
|
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
|
||||||
|
<converters:SubtractConverter x:Key="SubtractConverter"/>
|
||||||
|
|
||||||
<!-- DropShadowEffect para efectos de sombra en texto -->
|
<!-- DropShadowEffect para efectos de sombra en texto -->
|
||||||
<DropShadowEffect x:Key="DropShadowEffect"
|
<DropShadowEffect x:Key="DropShadowEffect"
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace CtrEditor.Converters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converter that converts boolean values to Visibility, with inverse logic
|
||||||
|
/// (true -> Collapsed, false -> Visible)
|
||||||
|
/// </summary>
|
||||||
|
public class InverseBooleanToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is bool boolValue)
|
||||||
|
{
|
||||||
|
return boolValue ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is Visibility visibility)
|
||||||
|
{
|
||||||
|
return visibility == Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace CtrEditor.Converters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converter that subtracts a parameter value from the input value
|
||||||
|
/// Useful for calculations like width - margin, etc.
|
||||||
|
/// </summary>
|
||||||
|
public class SubtractConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (value != null && parameter != null)
|
||||||
|
{
|
||||||
|
var inputValue = System.Convert.ToDouble(value);
|
||||||
|
var subtractValue = System.Convert.ToDouble(parameter);
|
||||||
|
|
||||||
|
var result = inputValue - subtractValue;
|
||||||
|
return Math.Max(0, result); // Ensure result is not negative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"SubtractConverter.Convert: Exception - {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (value != null && parameter != null)
|
||||||
|
{
|
||||||
|
var inputValue = System.Convert.ToDouble(value);
|
||||||
|
var addValue = System.Convert.ToDouble(parameter);
|
||||||
|
|
||||||
|
return inputValue + addValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"SubtractConverter.ConvertBack: Exception - {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Documentation\BEPU Forces.cs" />
|
<Compile Remove="Documentation\BEPU Forces.cs" />
|
||||||
<Compile Remove="Documentation\PlantillaEstandarizacion.cs" />
|
<Compile Remove="Documentation\PlantillaEstandarizacion.cs" />
|
||||||
|
<Compile Remove="Documentation\Hidraulic\Patches\osHydTank_OutputModeEnhancements.cs" />
|
||||||
<Compile Remove="ObjetosSim\ucTransporteCurva.xaml.cs" />
|
<Compile Remove="ObjetosSim\ucTransporteCurva.xaml.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,43 @@ namespace CtrEditor.ObjetosSim
|
||||||
[property: Name("Color")]
|
[property: Name("Color")]
|
||||||
private Brush colorButton_oculto = Brushes.LightBlue;
|
private Brush colorButton_oculto = Brushes.LightBlue;
|
||||||
|
|
||||||
|
// Three-section tank properties
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: Category("🏭 Configuración Tanque")]
|
||||||
|
[property: Description("Habilitar sistema de tres secciones")]
|
||||||
|
[property: Name("Tres Secciones")]
|
||||||
|
private bool enableThreeSection = false;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: Category("🏭 Configuración Tanque")]
|
||||||
|
[property: Description("Altura de la sección de mezcla (m)")]
|
||||||
|
[property: Name("Altura Mezcla")]
|
||||||
|
private double mixingSectionHeight = 0.20;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: Category("📊 Niveles")]
|
||||||
|
[property: Description("Nivel secundario en metros")]
|
||||||
|
[property: Name("Nivel Secundario")]
|
||||||
|
private double secondaryLevelM = 0.0;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: Category("📊 Niveles")]
|
||||||
|
[property: Description("Nivel primario en metros")]
|
||||||
|
[property: Name("Nivel Primario")]
|
||||||
|
private double primaryLevelM = 0.0;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: Category("📊 Porcentajes")]
|
||||||
|
[property: Description("Porcentaje de llenado sección secundaria")]
|
||||||
|
[property: Name("% Secundario")]
|
||||||
|
private double secondaryPercentage = 0.0;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[property: Category("📊 Porcentajes")]
|
||||||
|
[property: Description("Porcentaje de llenado sección primaria")]
|
||||||
|
[property: Name("% Primario")]
|
||||||
|
private double primaryPercentage = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
|
@ -112,7 +149,15 @@ namespace CtrEditor.ObjetosSim
|
||||||
SafeUpdateTankPressure();
|
SafeUpdateTankPressure();
|
||||||
|
|
||||||
// Inicializar estado de mezcla
|
// Inicializar estado de mezcla
|
||||||
UpdateMixingState(); // Debug: Confirmar que el constructor se ejecuta
|
UpdateMixingState();
|
||||||
|
|
||||||
|
// Inicializar sistema de tres secciones
|
||||||
|
if (EnableThreeSection)
|
||||||
|
{
|
||||||
|
ConfigureThreeSectionLevels();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug: Confirmar que el constructor se ejecuta
|
||||||
Debug.WriteLine($"osHydTank Constructor: Nombre='{Nombre}', Tamaño={Tamano}, ZIndex={zIndex_fromFrames}, IsVisFilter={IsVisFilter}, Lock_movement={Lock_movement}");
|
Debug.WriteLine($"osHydTank Constructor: Nombre='{Nombre}', Tamaño={Tamano}, ZIndex={zIndex_fromFrames}, IsVisFilter={IsVisFilter}, Lock_movement={Lock_movement}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -1095,6 +1140,12 @@ namespace CtrEditor.ObjetosSim
|
||||||
// Actualizar volúmenes de fluidos según el estado de mezcla
|
// Actualizar volúmenes de fluidos según el estado de mezcla
|
||||||
UpdateFluidVolumesFromFlow(volumeChangeL);
|
UpdateFluidVolumesFromFlow(volumeChangeL);
|
||||||
|
|
||||||
|
// Actualizar sistema de tres secciones si está habilitado
|
||||||
|
if (EnableThreeSection)
|
||||||
|
{
|
||||||
|
UpdateThreeSectionLevels();
|
||||||
|
}
|
||||||
|
|
||||||
// Debug para verificar cambios
|
// Debug para verificar cambios
|
||||||
if (VerboseLogging() && Math.Abs(volumeChangeL) > 0.1)
|
if (VerboseLogging() && Math.Abs(volumeChangeL) > 0.1)
|
||||||
{
|
{
|
||||||
|
@ -1326,6 +1377,127 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Three-Section Tank Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Obtiene la altura total del tanque
|
||||||
|
/// </summary>
|
||||||
|
private double GetHeightFromVolume()
|
||||||
|
{
|
||||||
|
return Tamano * 100; // Convertir tamaño a píxeles/altura
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configura los niveles para el sistema de tres secciones
|
||||||
|
/// </summary>
|
||||||
|
public void ConfigureThreeSectionLevels()
|
||||||
|
{
|
||||||
|
if (!EnableThreeSection) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (_levelLock)
|
||||||
|
{
|
||||||
|
var totalHeight = GetHeightFromVolume();
|
||||||
|
var mixingHeight = MixingSectionHeight;
|
||||||
|
|
||||||
|
// Validar que la altura de mezcla no sea mayor que la altura total
|
||||||
|
if (mixingHeight > totalHeight)
|
||||||
|
{
|
||||||
|
mixingHeight = totalHeight * 0.3; // Máximo 30% de la altura total
|
||||||
|
MixingSectionHeight = mixingHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcular niveles basados en la altura actual del líquido
|
||||||
|
var currentLevel = CurrentLevelM;
|
||||||
|
|
||||||
|
if (currentLevel <= mixingHeight)
|
||||||
|
{
|
||||||
|
// Solo sección de mezcla
|
||||||
|
SecondaryLevelM = 0.0;
|
||||||
|
PrimaryLevelM = currentLevel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Mezcla completa + nivel adicional
|
||||||
|
SecondaryLevelM = currentLevel - mixingHeight;
|
||||||
|
PrimaryLevelM = mixingHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateThreeSectionPercentages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Error configurando niveles de tres secciones: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Actualiza los porcentajes de llenado para cada sección
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateThreeSectionPercentages()
|
||||||
|
{
|
||||||
|
if (!EnableThreeSection) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (_levelLock)
|
||||||
|
{
|
||||||
|
var totalHeight = GetHeightFromVolume();
|
||||||
|
var mixingHeight = MixingSectionHeight;
|
||||||
|
var secondaryHeight = totalHeight - mixingHeight;
|
||||||
|
|
||||||
|
// Calcular porcentajes
|
||||||
|
if (mixingHeight > 0)
|
||||||
|
{
|
||||||
|
PrimaryPercentage = (PrimaryLevelM / mixingHeight) * 100.0;
|
||||||
|
PrimaryPercentage = Math.Min(100.0, Math.Max(0.0, PrimaryPercentage));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrimaryPercentage = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondaryHeight > 0)
|
||||||
|
{
|
||||||
|
SecondaryPercentage = (SecondaryLevelM / secondaryHeight) * 100.0;
|
||||||
|
SecondaryPercentage = Math.Min(100.0, Math.Max(0.0, SecondaryPercentage));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SecondaryPercentage = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Error actualizando porcentajes de tres secciones: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Actualiza los niveles basados en el nivel total actual
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateThreeSectionLevels()
|
||||||
|
{
|
||||||
|
if (!EnableThreeSection) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (_levelLock)
|
||||||
|
{
|
||||||
|
ConfigureThreeSectionLevels();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Error actualizando niveles de tres secciones: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Serialization Support
|
// Serialization Support
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -22,33 +22,46 @@
|
||||||
</TransformGroup>
|
</TransformGroup>
|
||||||
</Canvas.RenderTransform>
|
</Canvas.RenderTransform>
|
||||||
|
|
||||||
<!-- Contenedor principal del tanque -->
|
<!-- Contenedor principal del tanque con diseño mejorado -->
|
||||||
<Grid Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}"
|
<Grid Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}"
|
||||||
Height="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}">
|
Height="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=1.4}">
|
||||||
|
|
||||||
<!-- Fondo del tanque (contenedor vacío) -->
|
<!-- Fondo del tanque (contenedor vacío) con diseño 3D -->
|
||||||
<Rectangle x:Name="rectTankContainer"
|
<Rectangle x:Name="rectTankContainer"
|
||||||
Fill="LightGray"
|
Fill="#FFE6E6E6"
|
||||||
Stroke="DarkGray"
|
Stroke="#FF606060"
|
||||||
StrokeThickness="2"
|
StrokeThickness="3"
|
||||||
RadiusX="5"
|
RadiusX="8"
|
||||||
RadiusY="5"/>
|
RadiusY="8"
|
||||||
|
Effect="{StaticResource DropShadowEffect}"/>
|
||||||
|
|
||||||
<!-- Nivel del líquido - 3 secciones -->
|
<!-- Marco interno del tanque -->
|
||||||
|
<Rectangle Fill="Transparent"
|
||||||
|
Stroke="#FF404040"
|
||||||
|
StrokeThickness="1"
|
||||||
|
RadiusX="6"
|
||||||
|
RadiusY="6"
|
||||||
|
Margin="6"/>
|
||||||
|
|
||||||
|
<!-- Sistema de tres secciones (solo si está habilitado) -->
|
||||||
|
<Grid x:Name="ThreeSectionContainer"
|
||||||
|
Margin="8"
|
||||||
|
Visibility="{Binding EnableThreeSection, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
|
||||||
<!-- Sección secundaria (abajo) -->
|
<!-- Sección secundaria (abajo) -->
|
||||||
<Rectangle x:Name="rectSecondaryLevel"
|
<Rectangle x:Name="rectSecondaryLevel"
|
||||||
Fill="{Binding SecondaryLevelColor}"
|
Fill="{Binding SecondaryLevelColor}"
|
||||||
Stroke="DarkBlue"
|
Stroke="#FF1E90FF"
|
||||||
StrokeThickness="0.5"
|
StrokeThickness="1.5"
|
||||||
RadiusX="3"
|
RadiusX="4"
|
||||||
RadiusY="3"
|
RadiusY="4"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
Margin="4,4,4,4">
|
Opacity="0.85">
|
||||||
<Rectangle.Height>
|
<Rectangle.Height>
|
||||||
<MultiBinding Converter="{StaticResource TankLevelToHeightConverter}">
|
<MultiBinding Converter="{StaticResource TankLevelToHeightConverter}">
|
||||||
<Binding Path="SecondaryDisplayPercentage"/>
|
<Binding Path="SecondaryPercentage"/>
|
||||||
<Binding Path="Tamano"/>
|
<Binding Path="Tamano"/>
|
||||||
|
<Binding Source="0.33"/>
|
||||||
</MultiBinding>
|
</MultiBinding>
|
||||||
</Rectangle.Height>
|
</Rectangle.Height>
|
||||||
</Rectangle>
|
</Rectangle>
|
||||||
|
@ -56,167 +69,268 @@
|
||||||
<!-- Sección de mezcla (medio) -->
|
<!-- Sección de mezcla (medio) -->
|
||||||
<Rectangle x:Name="rectMixLevel"
|
<Rectangle x:Name="rectMixLevel"
|
||||||
Fill="{Binding MixLevelColor}"
|
Fill="{Binding MixLevelColor}"
|
||||||
Stroke="Purple"
|
Stroke="#FFFF6347"
|
||||||
StrokeThickness="0.5"
|
StrokeThickness="1.5"
|
||||||
RadiusX="3"
|
RadiusX="4"
|
||||||
RadiusY="3"
|
RadiusY="4"
|
||||||
VerticalAlignment="Bottom">
|
VerticalAlignment="Bottom"
|
||||||
|
Opacity="0.85">
|
||||||
<Rectangle.Height>
|
<Rectangle.Height>
|
||||||
<MultiBinding Converter="{StaticResource TankLevelToHeightConverter}">
|
<MultiBinding Converter="{StaticResource TankLevelToHeightConverter}">
|
||||||
<Binding Path="MixDisplayPercentage"/>
|
<Binding Path="PrimaryPercentage"/>
|
||||||
<Binding Path="Tamano"/>
|
<Binding Path="Tamano"/>
|
||||||
|
<Binding Source="0.33"/>
|
||||||
</MultiBinding>
|
</MultiBinding>
|
||||||
</Rectangle.Height>
|
</Rectangle.Height>
|
||||||
<Rectangle.Margin>
|
<Rectangle.Margin>
|
||||||
<MultiBinding Converter="{StaticResource TankSectionMarginConverter}">
|
<MultiBinding Converter="{StaticResource TankSectionMarginConverter}">
|
||||||
<Binding Path="SecondaryDisplayPercentage"/>
|
<Binding Path="SecondaryPercentage"/>
|
||||||
<Binding Path="Tamano"/>
|
<Binding Path="Tamano"/>
|
||||||
|
<Binding Source="0.33"/>
|
||||||
</MultiBinding>
|
</MultiBinding>
|
||||||
</Rectangle.Margin>
|
</Rectangle.Margin>
|
||||||
</Rectangle>
|
</Rectangle>
|
||||||
|
|
||||||
<!-- Sección primaria (arriba) -->
|
<!-- Etiquetas de sección -->
|
||||||
<Rectangle x:Name="rectPrimaryLevel"
|
|
||||||
Fill="{Binding PrimaryLevelColor}"
|
|
||||||
Stroke="DarkGreen"
|
|
||||||
StrokeThickness="0.5"
|
|
||||||
RadiusX="3"
|
|
||||||
RadiusY="3"
|
|
||||||
VerticalAlignment="Bottom">
|
|
||||||
<Rectangle.Height>
|
|
||||||
<MultiBinding Converter="{StaticResource TankLevelToHeightConverter}">
|
|
||||||
<Binding Path="PrimaryDisplayPercentage"/>
|
|
||||||
<Binding Path="Tamano"/>
|
|
||||||
</MultiBinding>
|
|
||||||
</Rectangle.Height>
|
|
||||||
<Rectangle.Margin>
|
|
||||||
<MultiBinding Converter="{StaticResource TankSectionMarginConverter}">
|
|
||||||
<Binding Path="SecondaryDisplayPercentage"/>
|
|
||||||
<Binding Path="MixDisplayPercentage"/>
|
|
||||||
<Binding Path="Tamano"/>
|
|
||||||
</MultiBinding>
|
|
||||||
</Rectangle.Margin>
|
|
||||||
</Rectangle>
|
|
||||||
|
|
||||||
<!-- Líneas de nivel (marcas visuales) -->
|
|
||||||
<Canvas>
|
<Canvas>
|
||||||
|
<!-- Etiqueta sección secundaria -->
|
||||||
|
<Border Background="#AA1E90FF" CornerRadius="2" Padding="2,1"
|
||||||
|
Canvas.Left="2" Canvas.Bottom="2">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="Sec:" Foreground="White" FontSize="6" FontWeight="Bold"/>
|
||||||
|
<TextBlock Text="{Binding SecondaryPercentage, StringFormat='{}{0:F0}%'}"
|
||||||
|
Foreground="White" FontSize="6" Margin="1,0,0,0"/>
|
||||||
|
<TextBlock Text="{Binding SecondaryVolumeL, StringFormat=' ({0:F0}L)'}"
|
||||||
|
Foreground="White" FontSize="5" Opacity="0.9"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Etiqueta sección primaria -->
|
||||||
|
<Border Background="#AAFF6347" CornerRadius="2" Padding="2,1"
|
||||||
|
Canvas.Right="2" Canvas.Top="2">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="Pri:" Foreground="White" FontSize="6" FontWeight="Bold"/>
|
||||||
|
<TextBlock Text="{Binding PrimaryPercentage, StringFormat='{}{0:F0}%'}"
|
||||||
|
Foreground="White" FontSize="6" Margin="1,0,0,0"/>
|
||||||
|
<TextBlock Text="{Binding PrimaryVolumeL, StringFormat=' ({0:F0}L)'}"
|
||||||
|
Foreground="White" FontSize="5" Opacity="0.9"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Sistema de una sección (clásico) -->
|
||||||
|
<Grid x:Name="SingleSectionContainer"
|
||||||
|
Margin="8"
|
||||||
|
Visibility="{Binding EnableThreeSection, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
|
||||||
|
|
||||||
|
<!-- Nivel del líquido tradicional -->
|
||||||
|
<Rectangle x:Name="rectFluidLevel"
|
||||||
|
Fill="{Binding LevelColor}"
|
||||||
|
Stroke="{Binding LevelBorderColor}"
|
||||||
|
StrokeThickness="1.5"
|
||||||
|
RadiusX="4"
|
||||||
|
RadiusY="4"
|
||||||
|
VerticalAlignment="Bottom"
|
||||||
|
Opacity="0.85">
|
||||||
|
<Rectangle.Height>
|
||||||
|
<MultiBinding Converter="{StaticResource TankLevelToHeightConverter}">
|
||||||
|
<Binding Path="FillPercentage"/>
|
||||||
|
<Binding Path="Tamano"/>
|
||||||
|
<Binding Source="1.0"/>
|
||||||
|
</MultiBinding>
|
||||||
|
</Rectangle.Height>
|
||||||
|
</Rectangle>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Líneas de nivel mejoradas -->
|
||||||
|
<Canvas Margin="8">
|
||||||
<!-- Línea de nivel máximo -->
|
<!-- Línea de nivel máximo -->
|
||||||
<Line X1="0" Y1="8" X2="{Binding ActualWidth, ElementName=rectTankContainer}" Y2="8"
|
<Line X1="0" Y1="4" X2="{Binding ActualWidth, ElementName=rectTankContainer, Converter={StaticResource SubtractConverter}, ConverterParameter=16}" Y2="4"
|
||||||
Stroke="Red" StrokeThickness="1" StrokeDashArray="2,2" Opacity="0.7"/>
|
Stroke="#FFB22222" StrokeThickness="2" StrokeDashArray="4,2" Opacity="0.8"/>
|
||||||
|
<TextBlock Canvas.Right="2" Canvas.Top="-2" Text="MAX" Foreground="#FFB22222" FontSize="6" FontWeight="Bold"/>
|
||||||
|
|
||||||
<!-- Línea de nivel medio -->
|
<!-- Línea de nivel medio -->
|
||||||
<Line X1="0" Y1="{Binding MidLevelY}" X2="{Binding ActualWidth, ElementName=rectTankContainer}" Y2="{Binding MidLevelY}"
|
<Line X1="0" Y1="{Binding MidLevelY}" X2="{Binding ActualWidth, ElementName=rectTankContainer, Converter={StaticResource SubtractConverter}, ConverterParameter=16}" Y2="{Binding MidLevelY}"
|
||||||
Stroke="Orange" StrokeThickness="1" StrokeDashArray="2,2" Opacity="0.5"/>
|
Stroke="#FFFF8C00" StrokeThickness="1" StrokeDashArray="2,2" Opacity="0.6"/>
|
||||||
|
<TextBlock Canvas.Right="2" Canvas.Top="{Binding MidLevelY, Converter={StaticResource SubtractConverter}, ConverterParameter=8}"
|
||||||
|
Text="50%" Foreground="#FFFF8C00" FontSize="5"/>
|
||||||
|
|
||||||
<!-- Línea de nivel mínimo -->
|
<!-- Línea de nivel mínimo -->
|
||||||
<Line X1="0" Y1="{Binding MinLevelY}" X2="{Binding ActualWidth, ElementName=rectTankContainer}" Y2="{Binding MinLevelY}"
|
<Line X1="0" Y1="{Binding MinLevelY}" X2="{Binding ActualWidth, ElementName=rectTankContainer, Converter={StaticResource SubtractConverter}, ConverterParameter=16}" Y2="{Binding MinLevelY}"
|
||||||
Stroke="Red" StrokeThickness="1" StrokeDashArray="2,2" Opacity="0.7"/>
|
Stroke="#FFB22222" StrokeThickness="2" StrokeDashArray="4,2" Opacity="0.8"/>
|
||||||
|
<TextBlock Canvas.Right="2" Canvas.Bottom="2" Text="MIN" Foreground="#FFB22222" FontSize="6" FontWeight="Bold"/>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
|
||||||
<!-- Texto del porcentaje de llenado -->
|
<!-- Información central del tanque -->
|
||||||
|
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
|
<!-- Nivel total y volumen -->
|
||||||
|
<Border Background="#AA000000" CornerRadius="4" Padding="6,4">
|
||||||
|
<StackPanel HorizontalAlignment="Center">
|
||||||
|
<!-- Porcentaje principal -->
|
||||||
<TextBlock Text="{Binding FillPercentage, StringFormat='{}{0:F0}%'}"
|
<TextBlock Text="{Binding FillPercentage, StringFormat='{}{0:F0}%'}"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
|
||||||
Foreground="White"
|
Foreground="White"
|
||||||
FontWeight="Bold"
|
FontWeight="Bold"
|
||||||
FontSize="12"
|
FontSize="14"/>
|
||||||
Effect="{StaticResource DropShadowEffect}"/>
|
|
||||||
|
|
||||||
<!-- Indicador de tipo de tanque y fluido -->
|
<!-- Volumen actual -->
|
||||||
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="2,2,0,0">
|
<TextBlock Text="{Binding CurrentVolumeL, StringFormat='{}{0:F0} L'}"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Foreground="LightCyan"
|
||||||
|
FontSize="8"
|
||||||
|
Margin="0,1,0,0"/>
|
||||||
|
|
||||||
|
<!-- Nivel sobre el mar -->
|
||||||
|
<TextBlock Text="{Binding CurrentLevelM, StringFormat='⌂ {0:F2} m'}"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Foreground="LightGreen"
|
||||||
|
FontSize="7"
|
||||||
|
Margin="0,1,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Indicadores superiores -->
|
||||||
|
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="4,4,0,0">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Tipo de tanque -->
|
<!-- Tipo de tanque -->
|
||||||
<Border Grid.Row="0" Background="Navy" CornerRadius="2" Padding="3,1">
|
<Border Grid.Row="0" Background="#FF000080" CornerRadius="3" Padding="4,2">
|
||||||
<TextBlock Text="{Binding TankTypeIndicator}"
|
<TextBlock Text="{Binding TankTypeIndicator}"
|
||||||
Foreground="White"
|
Foreground="White"
|
||||||
FontWeight="Bold"
|
FontWeight="Bold"
|
||||||
FontSize="8" />
|
FontSize="10" />
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Tipo de fluido -->
|
<!-- Tipo de fluido actual -->
|
||||||
<Border Grid.Row="1" Background="DarkGreen" CornerRadius="2" Padding="2,1" Margin="0,1,0,0">
|
<Border Grid.Row="1" Background="#FF006400" CornerRadius="3" Padding="3,2" Margin="0,2,0,0">
|
||||||
<TextBlock Text="{Binding CurrentFluidDescription}"
|
<TextBlock Text="{Binding CurrentFluidDescription}"
|
||||||
|
Foreground="White"
|
||||||
|
FontSize="7"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
MaxWidth="60"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Estado de mezcla -->
|
||||||
|
<Border Grid.Row="2" Background="#FF8B4513" CornerRadius="3" Padding="3,2" Margin="0,2,0,0"
|
||||||
|
Visibility="{Binding EnableThreeSection, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<TextBlock Text="{Binding MixingState}"
|
||||||
Foreground="White"
|
Foreground="White"
|
||||||
FontSize="6"
|
FontSize="6"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
TextTrimming="CharacterEllipsis"
|
TextTrimming="CharacterEllipsis"
|
||||||
MaxWidth="40"/>
|
MaxWidth="60"/>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Panel de información mejorado -->
|
<!-- Panel de información detallado -->
|
||||||
<Grid Canvas.Top="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=1.08}"
|
<Grid Canvas.Top="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}, ConverterParameter=1.5}"
|
||||||
Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}">
|
Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}">
|
||||||
|
|
||||||
<!-- Fondo semitransparente para el panel de información -->
|
<!-- Fondo del panel con gradiente -->
|
||||||
<Border Background="#CC000000" CornerRadius="3" Margin="0,2,0,0" Padding="2">
|
<Border CornerRadius="5" Margin="0,4,0,0" Padding="4">
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||||
|
|
||||||
<!-- Fila superior: Presión y Nivel -->
|
<!-- Fila 1: Presión y Nivel absoluto -->
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,1">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,2">
|
||||||
<!-- Presión actual -->
|
<!-- Presión actual -->
|
||||||
<Border Background="#FF1E90FF" CornerRadius="2" Padding="3,2" Margin="1">
|
<Border Background="#FF1E90FF" CornerRadius="3" Padding="4,3" Margin="2">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="P:" Foreground="White" FontSize="7" FontWeight="Bold"/>
|
<TextBlock Text="⚡" Foreground="White" FontSize="9" FontWeight="Bold"/>
|
||||||
<TextBlock Text="{Binding CurrentPressure, StringFormat='{}{0:F1}'}"
|
<TextBlock Text="{Binding CurrentPressure, StringFormat='{}{0:F2}'}"
|
||||||
Foreground="White" FontSize="7" FontWeight="SemiBold" Margin="1,0,0,0"/>
|
Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/>
|
||||||
<TextBlock Text="bar" Foreground="White" FontSize="6" Opacity="0.9" Margin="1,0,0,0"/>
|
<TextBlock Text="bar" Foreground="LightCyan" FontSize="7" Opacity="0.9" Margin="1,0,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Nivel actual -->
|
<!-- Nivel absoluto -->
|
||||||
<Border Background="#FF32CD32" CornerRadius="2" Padding="3,2" Margin="1">
|
<Border Background="#FF32CD32" CornerRadius="3" Padding="4,3" Margin="2">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="N:" Foreground="White" FontSize="7" FontWeight="Bold"/>
|
<TextBlock Text="🌊" Foreground="White" FontSize="9" FontWeight="Bold"/>
|
||||||
<TextBlock Text="{Binding CurrentLevelM, StringFormat='{}{0:F2}'}"
|
<TextBlock Text="{Binding CurrentLevelM, StringFormat='{}{0:F3}'}"
|
||||||
Foreground="White" FontSize="7" FontWeight="SemiBold" Margin="1,0,0,0"/>
|
Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/>
|
||||||
<TextBlock Text="m" Foreground="White" FontSize="6" Opacity="0.9" Margin="1,0,0,0"/>
|
<TextBlock Text="m" Foreground="LightGreen" FontSize="7" Opacity="0.9" Margin="1,0,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Fila inferior: Flujos -->
|
<!-- Fila 2: Flujos de entrada y salida -->
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,1">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,2">
|
||||||
<!-- Flujo de entrada -->
|
<!-- Flujo de entrada -->
|
||||||
<Border Background="#FF228B22" CornerRadius="2" Padding="3,2" Margin="1">
|
<Border Background="#FF228B22" CornerRadius="3" Padding="4,3" Margin="2">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="↓" Foreground="White" FontSize="8" FontWeight="Bold"/>
|
<TextBlock Text="▼" Foreground="White" FontSize="9" FontWeight="Bold"/>
|
||||||
<TextBlock Text="{Binding InletFlow, StringFormat='{}{0:F1}'}"
|
<TextBlock Text="{Binding InletFlow, StringFormat='{}{0:F1}'}"
|
||||||
Foreground="White" FontSize="7" FontWeight="SemiBold" Margin="1,0,0,0"/>
|
Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/>
|
||||||
|
<TextBlock Text="L/min" Foreground="LightGreen" FontSize="6" Opacity="0.9" Margin="1,0,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Flujo de salida -->
|
<!-- Flujo de salida -->
|
||||||
<Border Background="#FFDC143C" CornerRadius="2" Padding="3,2" Margin="1">
|
<Border Background="#FFDC143C" CornerRadius="3" Padding="4,3" Margin="2">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="↑" Foreground="White" FontSize="8" FontWeight="Bold"/>
|
<TextBlock Text="▲" Foreground="White" FontSize="9" FontWeight="Bold"/>
|
||||||
<TextBlock Text="{Binding OutletFlow, StringFormat='{}{0:F1}'}"
|
<TextBlock Text="{Binding OutletFlow, StringFormat='{}{0:F1}'}"
|
||||||
Foreground="White" FontSize="7" FontWeight="SemiBold" Margin="1,0,0,0"/>
|
Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/>
|
||||||
|
<TextBlock Text="L/min" Foreground="LightPink" FontSize="6" Opacity="0.9" Margin="1,0,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Balance de flujo -->
|
<!-- Balance de flujo -->
|
||||||
<Border Background="{Binding FlowBalanceColor}" CornerRadius="2" Padding="3,2" Margin="1">
|
<Border Background="{Binding FlowBalanceColor}" CornerRadius="3" Padding="4,3" Margin="2">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="Δ:" Foreground="White" FontSize="7" FontWeight="Bold"/>
|
<TextBlock Text="Δ" Foreground="White" FontSize="9" FontWeight="Bold"/>
|
||||||
<TextBlock Text="{Binding FlowBalance, StringFormat='{}{0:F1}'}"
|
<TextBlock Text="{Binding FlowBalance, StringFormat='{}{0:F1}'}"
|
||||||
Foreground="White" FontSize="7" FontWeight="SemiBold" Margin="1,0,0,0"/>
|
Foreground="White" FontSize="8" FontWeight="SemiBold" Margin="2,0,0,0"/>
|
||||||
|
<TextBlock Text="L/min" Foreground="White" FontSize="6" Opacity="0.9" Margin="1,0,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Fila 3: Información de tres secciones (solo si está habilitado) -->
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,2"
|
||||||
|
Visibility="{Binding EnableThreeSection, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
|
||||||
|
<!-- Sección secundaria -->
|
||||||
|
<Border Background="#AA1E90FF" CornerRadius="3" Padding="3,2" Margin="1">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="S:" Foreground="White" FontSize="7" FontWeight="Bold"/>
|
||||||
|
<TextBlock Text="{Binding SecondaryLevelM, StringFormat='{}{0:F2}m'}"
|
||||||
|
Foreground="White" FontSize="7" Margin="1,0,0,0"/>
|
||||||
|
<TextBlock Text="{Binding SecondaryVolumeL, StringFormat=' {0:F0}L'}"
|
||||||
|
Foreground="LightCyan" FontSize="6" Opacity="0.9"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Sección primaria -->
|
||||||
|
<Border Background="#AAFF6347" CornerRadius="3" Padding="3,2" Margin="1">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="P:" Foreground="White" FontSize="7" FontWeight="Bold"/>
|
||||||
|
<TextBlock Text="{Binding PrimaryLevelM, StringFormat='{}{0:F2}m'}"
|
||||||
|
Foreground="White" FontSize="7" Margin="1,0,0,0"/>
|
||||||
|
<TextBlock Text="{Binding PrimaryVolumeL, StringFormat=' {0:F0}L'}"
|
||||||
|
Foreground="LightYellow" FontSize="6" Opacity="0.9"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Ratio de mezcla -->
|
||||||
|
<Border Background="#AA8B4513" CornerRadius="3" Padding="3,2" Margin="1">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="Mix:" Foreground="White" FontSize="7" FontWeight="Bold"/>
|
||||||
|
<TextBlock Text="{Binding CurrentMixRatio, StringFormat='{}{0:P0}'}"
|
||||||
|
Foreground="White" FontSize="7" Margin="1,0,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Unidades comunes -->
|
|
||||||
<TextBlock Text="L/min"
|
|
||||||
Foreground="White"
|
|
||||||
FontSize="6"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Opacity="0.8"
|
|
||||||
Margin="0,1,0,0"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
Loading…
Reference in New Issue