2026-02-10 20:48:49 +09:00
|
|
|
#nullable enable
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
|
|
|
|
|
|
namespace UVC.UIToolkit
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Float + Dropdown 복합 속성 View 클래스입니다.
|
|
|
|
|
/// UTKFloatField(또는 UTKFloatStepper)와 UTKDropdown을 사용하여
|
|
|
|
|
/// float 값과 문자열 선택을 하나의 행에 표시/편집합니다.
|
|
|
|
|
///
|
|
|
|
|
/// <para><b>사용법 (Data 바인딩):</b></para>
|
|
|
|
|
/// <code>
|
|
|
|
|
/// var data = new UTKFloatDropdownPropertyItem("id", "Label", 1.5f,
|
2026-02-12 18:04:38 +09:00
|
|
|
/// new List<string> { "A", "B", "C" }, "A");
|
2026-02-10 20:48:49 +09:00
|
|
|
/// var view = new UTKFloatDropdownPropertyItemView();
|
|
|
|
|
/// view.Bind(data);
|
|
|
|
|
/// </code>
|
|
|
|
|
/// </summary>
|
|
|
|
|
[UxmlElement]
|
|
|
|
|
public partial class UTKFloatDropdownPropertyItemView : UTKPropertyItemViewBase, IUTKPropertyItemView<UTKFloatDropdownValue>
|
|
|
|
|
{
|
|
|
|
|
#region Fields
|
|
|
|
|
private UTKFloatField? _floatField;
|
|
|
|
|
private UTKFloatStepper? _stepper;
|
|
|
|
|
private UTKDropdown? _dropdown;
|
|
|
|
|
private UTKInputField? _readOnlyField;
|
|
|
|
|
|
|
|
|
|
private UTKFloatDropdownValue _value;
|
|
|
|
|
private List<string> _choices = new();
|
|
|
|
|
private bool _useStepper;
|
|
|
|
|
private float _floatMinValue = float.MinValue;
|
|
|
|
|
private float _floatMaxValue = float.MaxValue;
|
|
|
|
|
private float _stepperStep = 1.0f;
|
|
|
|
|
|
|
|
|
|
private IUTKPropertyItem<UTKFloatDropdownValue>? _boundData;
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
|
protected override string ViewTypeName => "UTKFloatDropdownPropertyItemView";
|
|
|
|
|
|
|
|
|
|
/// <summary>현재 값</summary>
|
|
|
|
|
public UTKFloatDropdownValue Value
|
|
|
|
|
{
|
|
|
|
|
get => _value;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (!_value.Equals(value))
|
|
|
|
|
{
|
|
|
|
|
_value = value;
|
|
|
|
|
UpdateValueUI();
|
|
|
|
|
OnValueChanged?.Invoke(value);
|
|
|
|
|
|
|
|
|
|
if (_boundData != null && !_boundData.Value.Equals(value))
|
|
|
|
|
{
|
|
|
|
|
_boundData.Value = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Dropdown 선택 목록</summary>
|
|
|
|
|
public List<string> Choices
|
|
|
|
|
{
|
|
|
|
|
get => _choices;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
_choices = value ?? new List<string>();
|
|
|
|
|
_dropdown?.SetOptions(_choices);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>스테퍼(증감 버튼) 사용 여부</summary>
|
|
|
|
|
public bool UseStepper
|
|
|
|
|
{
|
|
|
|
|
get => _useStepper;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (_useStepper != value)
|
|
|
|
|
{
|
|
|
|
|
_useStepper = value;
|
|
|
|
|
UpdateControlVisibility();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Events
|
|
|
|
|
public event Action<UTKFloatDropdownValue>? OnValueChanged;
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Constructor
|
|
|
|
|
public UTKFloatDropdownPropertyItemView() : base()
|
|
|
|
|
{
|
|
|
|
|
InitializeUI();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public UTKFloatDropdownPropertyItemView(string label, List<string> choices) : base()
|
|
|
|
|
{
|
|
|
|
|
_choices = new List<string>(choices);
|
|
|
|
|
Label = label;
|
|
|
|
|
InitializeUI();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public UTKFloatDropdownPropertyItemView(UTKFloatDropdownPropertyItem data) : base()
|
|
|
|
|
{
|
|
|
|
|
_value = data.Value;
|
|
|
|
|
_choices = new List<string>(data.Choices);
|
|
|
|
|
_useStepper = data.UseStepper;
|
|
|
|
|
_floatMinValue = data.FloatMinValue;
|
|
|
|
|
_floatMaxValue = data.FloatMaxValue;
|
|
|
|
|
_stepperStep = data.StepperStep;
|
|
|
|
|
Label = data.Name;
|
|
|
|
|
_isReadOnly = data.IsReadOnly;
|
|
|
|
|
InitializeUI();
|
|
|
|
|
Bind(data);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Initialization
|
|
|
|
|
private void InitializeUI()
|
|
|
|
|
{
|
|
|
|
|
AddToClassList("utk-property-item-view");
|
|
|
|
|
AddToClassList("utk-property-item-view--float-dropdown");
|
|
|
|
|
|
|
|
|
|
if (!CreateUIFromUxml())
|
|
|
|
|
{
|
|
|
|
|
CreateUIFallback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QueryUIElements();
|
|
|
|
|
RegisterEvents();
|
|
|
|
|
UpdateControlVisibility();
|
|
|
|
|
UpdateValueUI();
|
|
|
|
|
UpdateReadOnlyState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void QueryUIElements()
|
|
|
|
|
{
|
|
|
|
|
_floatField = this.Q<UTKFloatField>("float-field");
|
|
|
|
|
_dropdown = this.Q<UTKDropdown>("dropdown-field");
|
|
|
|
|
_stepper = this.Q<UTKFloatStepper>("stepper-field");
|
|
|
|
|
|
|
|
|
|
if (_valueContainer != null)
|
|
|
|
|
{
|
|
|
|
|
_valueContainer.style.flexDirection = FlexDirection.Row;
|
|
|
|
|
|
|
|
|
|
// FloatField 생성
|
|
|
|
|
if (_floatField == null)
|
|
|
|
|
{
|
|
|
|
|
_floatField = new UTKFloatField { name = "float-field" };
|
|
|
|
|
_floatField.AddToClassList("utk-float-dropdown-view__float-field");
|
|
|
|
|
_valueContainer.Add(_floatField);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FloatStepper 생성
|
|
|
|
|
if (_stepper == null)
|
|
|
|
|
{
|
|
|
|
|
_stepper = new UTKFloatStepper(_floatMinValue, _floatMaxValue, _value.FloatValue, _stepperStep, IsReadOnly)
|
|
|
|
|
{
|
|
|
|
|
name = "stepper-field"
|
|
|
|
|
};
|
|
|
|
|
_stepper.AddToClassList("utk-float-dropdown-view__stepper");
|
|
|
|
|
_valueContainer.Add(_stepper);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Dropdown 생성
|
|
|
|
|
if (_dropdown == null)
|
|
|
|
|
{
|
|
|
|
|
_dropdown = new UTKDropdown { name = "dropdown-field" };
|
|
|
|
|
_dropdown.AddToClassList("utk-float-dropdown-view__dropdown");
|
|
|
|
|
_valueContainer.Add(_dropdown);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 초기 값 설정
|
|
|
|
|
if (_floatField != null)
|
|
|
|
|
{
|
|
|
|
|
_floatField.SetValueWithoutNotify(_value.FloatValue);
|
|
|
|
|
_floatField.isReadOnly = IsReadOnly;
|
|
|
|
|
}
|
|
|
|
|
if (_stepper != null)
|
|
|
|
|
{
|
|
|
|
|
_stepper.MinValue = _floatMinValue;
|
|
|
|
|
_stepper.MaxValue = _floatMaxValue;
|
|
|
|
|
_stepper.Step = _stepperStep;
|
|
|
|
|
_stepper.SetValue(_value.FloatValue, false);
|
|
|
|
|
_stepper.IsReadOnly = IsReadOnly;
|
|
|
|
|
}
|
|
|
|
|
if (_dropdown != null)
|
|
|
|
|
{
|
|
|
|
|
_dropdown.SetOptions(_choices);
|
|
|
|
|
_dropdown.SetSelectedValue(_value.DropdownValue, notify: false);
|
|
|
|
|
_dropdown.IsEnabled = !IsReadOnly;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RegisterEvents()
|
|
|
|
|
{
|
|
|
|
|
if (_floatField != null)
|
|
|
|
|
{
|
|
|
|
|
_floatField.OnValueChanged += OnFloatFieldChanged;
|
|
|
|
|
}
|
|
|
|
|
if (_stepper != null)
|
|
|
|
|
{
|
|
|
|
|
_stepper.OnValueChanged += OnStepperChanged;
|
|
|
|
|
}
|
|
|
|
|
if (_dropdown != null)
|
|
|
|
|
{
|
|
|
|
|
_dropdown.OnSelectionChanged += OnDropdownChanged;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UnregisterEvents()
|
|
|
|
|
{
|
|
|
|
|
if (_floatField != null)
|
|
|
|
|
{
|
|
|
|
|
_floatField.OnValueChanged -= OnFloatFieldChanged;
|
|
|
|
|
}
|
|
|
|
|
if (_stepper != null)
|
|
|
|
|
{
|
|
|
|
|
_stepper.OnValueChanged -= OnStepperChanged;
|
|
|
|
|
}
|
|
|
|
|
if (_dropdown != null)
|
|
|
|
|
{
|
|
|
|
|
_dropdown.OnSelectionChanged -= OnDropdownChanged;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>컨트롤 가시성을 업데이트합니다.</summary>
|
|
|
|
|
private void UpdateControlVisibility()
|
|
|
|
|
{
|
|
|
|
|
bool isReadOnlyMode = IsReadOnly;
|
|
|
|
|
bool showStepper = !isReadOnlyMode && _useStepper;
|
|
|
|
|
bool showFloatField = !isReadOnlyMode && !_useStepper;
|
|
|
|
|
bool showDropdown = !isReadOnlyMode;
|
|
|
|
|
|
|
|
|
|
if (_floatField != null)
|
|
|
|
|
{
|
|
|
|
|
_floatField.style.display = showFloatField ? DisplayStyle.Flex : DisplayStyle.None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_stepper != null)
|
|
|
|
|
{
|
|
|
|
|
_stepper.style.display = showStepper ? DisplayStyle.Flex : DisplayStyle.None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_dropdown != null)
|
|
|
|
|
{
|
|
|
|
|
_dropdown.style.display = showDropdown ? DisplayStyle.Flex : DisplayStyle.None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReadOnly 모드: 단일 텍스트 필드로 표시
|
|
|
|
|
if (isReadOnlyMode)
|
|
|
|
|
{
|
|
|
|
|
EnsureReadOnlyField();
|
|
|
|
|
if (_readOnlyField != null)
|
|
|
|
|
{
|
|
|
|
|
_readOnlyField.style.display = DisplayStyle.Flex;
|
|
|
|
|
_readOnlyField.Value = _value.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (_readOnlyField != null)
|
|
|
|
|
{
|
|
|
|
|
_readOnlyField.style.display = DisplayStyle.None;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>ReadOnly 전용 필드를 필요 시 생성합니다.</summary>
|
|
|
|
|
private void EnsureReadOnlyField()
|
|
|
|
|
{
|
|
|
|
|
if (_readOnlyField != null || _valueContainer == null) return;
|
|
|
|
|
|
|
|
|
|
_readOnlyField = new UTKInputField { name = "readonly-field" };
|
|
|
|
|
_readOnlyField.AddToClassList("utk-float-dropdown-view__readonly-field");
|
|
|
|
|
_readOnlyField.isReadOnly = true;
|
|
|
|
|
_readOnlyField.Value = _value.ToString();
|
|
|
|
|
_valueContainer.Add(_readOnlyField);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Override Methods
|
|
|
|
|
protected override void CreateValueUI(VisualElement container)
|
|
|
|
|
{
|
|
|
|
|
// UXML/QueryUIElements 기반으로 생성하므로 여기서는 생성하지 않음
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void RefreshUI()
|
|
|
|
|
{
|
|
|
|
|
UpdateValueUI();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnReadOnlyStateChanged(bool isReadOnly)
|
|
|
|
|
{
|
|
|
|
|
if (_floatField != null)
|
|
|
|
|
{
|
|
|
|
|
_floatField.isReadOnly = isReadOnly;
|
|
|
|
|
}
|
|
|
|
|
if (_stepper != null)
|
|
|
|
|
{
|
|
|
|
|
_stepper.IsReadOnly = isReadOnly;
|
|
|
|
|
}
|
|
|
|
|
if (_dropdown != null)
|
|
|
|
|
{
|
|
|
|
|
_dropdown.IsEnabled = !isReadOnly;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateControlVisibility();
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Event Handling
|
|
|
|
|
private void OnFloatFieldChanged(float newFloat)
|
|
|
|
|
{
|
|
|
|
|
var newValue = new UTKFloatDropdownValue(newFloat, _value.DropdownValue);
|
|
|
|
|
if (!_value.Equals(newValue))
|
|
|
|
|
{
|
|
|
|
|
_value = newValue;
|
|
|
|
|
|
|
|
|
|
// 스테퍼가 있으면 동기화
|
|
|
|
|
if (_stepper != null && !Mathf.Approximately(_stepper.Value, newFloat))
|
|
|
|
|
{
|
|
|
|
|
_stepper.SetValue(newFloat, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OnValueChanged?.Invoke(newValue);
|
|
|
|
|
|
|
|
|
|
if (_boundData != null && !_boundData.Value.Equals(newValue))
|
|
|
|
|
{
|
|
|
|
|
_boundData.Value = newValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnStepperChanged(float newFloat)
|
|
|
|
|
{
|
|
|
|
|
var newValue = new UTKFloatDropdownValue(newFloat, _value.DropdownValue);
|
|
|
|
|
if (!_value.Equals(newValue))
|
|
|
|
|
{
|
|
|
|
|
_value = newValue;
|
|
|
|
|
|
|
|
|
|
// FloatField가 있으면 동기화
|
|
|
|
|
if (_floatField != null && !Mathf.Approximately(_floatField.Value, newFloat))
|
|
|
|
|
{
|
|
|
|
|
_floatField.SetValueWithoutNotify(newFloat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OnValueChanged?.Invoke(newValue);
|
|
|
|
|
|
|
|
|
|
if (_boundData != null && !_boundData.Value.Equals(newValue))
|
|
|
|
|
{
|
|
|
|
|
_boundData.Value = newValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDropdownChanged(int index, string newDropdownValue)
|
|
|
|
|
{
|
|
|
|
|
var newValue = new UTKFloatDropdownValue(_value.FloatValue, newDropdownValue);
|
|
|
|
|
if (!_value.Equals(newValue))
|
|
|
|
|
{
|
|
|
|
|
_value = newValue;
|
|
|
|
|
OnValueChanged?.Invoke(newValue);
|
|
|
|
|
|
|
|
|
|
if (_boundData != null && !_boundData.Value.Equals(newValue))
|
|
|
|
|
{
|
|
|
|
|
_boundData.Value = newValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Value Update
|
|
|
|
|
private void UpdateValueUI()
|
|
|
|
|
{
|
|
|
|
|
if (_floatField != null && !Mathf.Approximately(_floatField.Value, _value.FloatValue))
|
|
|
|
|
{
|
|
|
|
|
_floatField.SetValueWithoutNotify(_value.FloatValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_stepper != null && !Mathf.Approximately(_stepper.Value, _value.FloatValue))
|
|
|
|
|
{
|
|
|
|
|
_stepper.SetValue(_value.FloatValue, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_dropdown != null)
|
|
|
|
|
{
|
|
|
|
|
string? selectedValue = _dropdown.SelectedValue;
|
|
|
|
|
if (selectedValue != _value.DropdownValue)
|
|
|
|
|
{
|
|
|
|
|
_dropdown.SetSelectedValue(_value.DropdownValue, notify: false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_readOnlyField != null && IsReadOnly)
|
|
|
|
|
{
|
|
|
|
|
_readOnlyField.Value = _value.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Data Binding
|
|
|
|
|
public void Bind(IUTKPropertyItem data)
|
|
|
|
|
{
|
|
|
|
|
if (data is IUTKPropertyItem<UTKFloatDropdownValue> typedData)
|
|
|
|
|
{
|
|
|
|
|
Bind(typedData);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogWarning($"[UTKFloatDropdownPropertyItemView] Cannot bind to non-FloatDropdown data: {data.GetType().Name}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Bind(IUTKPropertyItem<UTKFloatDropdownValue> data)
|
|
|
|
|
{
|
|
|
|
|
Unbind();
|
|
|
|
|
|
|
|
|
|
_boundData = data;
|
|
|
|
|
BindBase(data);
|
|
|
|
|
|
|
|
|
|
Label = data.Name;
|
|
|
|
|
_value = data.Value;
|
|
|
|
|
IsVisible = data.IsVisible;
|
|
|
|
|
TooltipText = data.Tooltip;
|
|
|
|
|
ShowLabel = data.ShowLabel;
|
|
|
|
|
|
|
|
|
|
// UTKFloatDropdownPropertyItem의 설정 적용
|
|
|
|
|
if (data is UTKFloatDropdownPropertyItem floatDropdownItem)
|
|
|
|
|
{
|
|
|
|
|
_choices = new List<string>(floatDropdownItem.Choices);
|
|
|
|
|
_useStepper = floatDropdownItem.UseStepper;
|
|
|
|
|
_floatMinValue = floatDropdownItem.FloatMinValue;
|
|
|
|
|
_floatMaxValue = floatDropdownItem.FloatMaxValue;
|
|
|
|
|
_stepperStep = floatDropdownItem.StepperStep;
|
|
|
|
|
|
|
|
|
|
// Dropdown 옵션 업데이트
|
|
|
|
|
_dropdown?.SetOptions(_choices);
|
|
|
|
|
|
|
|
|
|
// 스테퍼 설정 업데이트
|
|
|
|
|
if (_stepper != null)
|
|
|
|
|
{
|
|
|
|
|
_stepper.MinValue = _floatMinValue;
|
|
|
|
|
_stepper.MaxValue = _floatMaxValue;
|
|
|
|
|
_stepper.Step = _stepperStep;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateControlVisibility();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data.OnTypedValueChanged += OnDataValueChanged;
|
|
|
|
|
|
|
|
|
|
UpdateValueUI();
|
|
|
|
|
IsReadOnly = data.IsReadOnly;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Unbind()
|
|
|
|
|
{
|
|
|
|
|
if (_boundData != null)
|
|
|
|
|
{
|
|
|
|
|
_boundData.OnTypedValueChanged -= OnDataValueChanged;
|
|
|
|
|
UnbindBase();
|
|
|
|
|
_boundData = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDataValueChanged(IUTKPropertyItem<UTKFloatDropdownValue> item, UTKFloatDropdownValue oldValue, UTKFloatDropdownValue newValue)
|
|
|
|
|
{
|
|
|
|
|
if (!_value.Equals(newValue))
|
|
|
|
|
{
|
|
|
|
|
_value = newValue;
|
|
|
|
|
UpdateValueUI();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Dispose
|
|
|
|
|
protected override void Dispose(bool disposing)
|
|
|
|
|
{
|
|
|
|
|
if (_disposed) return;
|
|
|
|
|
|
|
|
|
|
if (disposing)
|
|
|
|
|
{
|
|
|
|
|
UnregisterEvents();
|
|
|
|
|
Unbind();
|
|
|
|
|
|
|
|
|
|
OnValueChanged = null;
|
|
|
|
|
_floatField = null;
|
|
|
|
|
_stepper?.Dispose();
|
|
|
|
|
_stepper = null;
|
|
|
|
|
_dropdown?.Dispose();
|
|
|
|
|
_dropdown = null;
|
|
|
|
|
_readOnlyField = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
base.Dispose(disposing);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|