200 lines
7.2 KiB
C#
200 lines
7.2 KiB
C#
/*
|
|
* Copyright (c) 2022 LG Electronics Inc.
|
|
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
|
|
*/
|
|
using Aurora.View;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
|
|
namespace AuroraUIComponent.UserControls.KeyValueBase
|
|
{
|
|
public abstract class UCKeyValueNumber : UCKeyValueBase
|
|
{
|
|
protected readonly CultureInfo Culture;
|
|
|
|
public static readonly DependencyProperty ValueProperty
|
|
= DependencyProperty.Register(
|
|
nameof(Value),
|
|
typeof(decimal),
|
|
typeof(UCKeyValueNumber),
|
|
// 2번째 인자: a PropertyChangedCallback delegate: called only when the property really changes
|
|
// 3번째 인자: a CoerceValueCallback delegate: called when Value is set
|
|
new FrameworkPropertyMetadata(
|
|
0m, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null, CoerceValueCallback)
|
|
);
|
|
|
|
|
|
public decimal Value {
|
|
get { return (decimal)GetValue(ValueProperty); }
|
|
set { SetValue(ValueProperty, value); }
|
|
}
|
|
|
|
protected static object CoerceValueCallback(DependencyObject d, object baseValue)
|
|
{
|
|
var control = (UCKeyValueNumber)d;
|
|
var value = (decimal)baseValue;
|
|
|
|
control.CoerceValue2Bounds(ref value);
|
|
|
|
// Get the text representation of Value
|
|
var valueString = value.ToString(control.Culture);
|
|
// Count all decimal places
|
|
var decimalPlaces = control.GetDecimalPlacesCount(valueString);
|
|
if (decimalPlaces > control.DecimalPlaces) {
|
|
// Remove all overflowing decimal places
|
|
value = control.TruncateValue(valueString, decimalPlaces);
|
|
}
|
|
|
|
control.ChangeThousandSeparator(value);
|
|
|
|
return value;
|
|
}
|
|
|
|
public static readonly DependencyProperty DecimalPlacesProperty =
|
|
DependencyProperty.Register(
|
|
nameof(DecimalPlaces),
|
|
typeof(int),
|
|
typeof(UCKeyValueNumber),
|
|
new PropertyMetadata(
|
|
0, OnDecimalPlacesChanged, CoerceDecimalPlacesCallback)
|
|
);
|
|
|
|
private static object CoerceDecimalPlacesCallback(DependencyObject d, object baseValue)
|
|
{
|
|
var decimalPlaces = (int)baseValue;
|
|
|
|
// 흠, 윈폼 문서에는 [0, 99] 범위인것 같은데, 참고자료에서
|
|
// the number of decimal places cannot be a negative number and by the architecture's limitation, there can only be up to 28 decimal places.
|
|
// 왜 28일까...??
|
|
if (decimalPlaces < 0) {
|
|
decimalPlaces = 0;
|
|
} else if (decimalPlaces > 28) {
|
|
decimalPlaces = 28;
|
|
}
|
|
|
|
return decimalPlaces;
|
|
}
|
|
|
|
public int DecimalPlaces {
|
|
get { return (int)GetValue(DecimalPlacesProperty); }
|
|
set { SetValue(DecimalPlacesProperty, value); }
|
|
}
|
|
|
|
private static void OnDecimalPlacesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var control = (UCKeyValueNumber)d;
|
|
var decimalPlaces = (int)e.NewValue;
|
|
|
|
control.Culture.NumberFormat.NumberDecimalDigits = decimalPlaces;
|
|
|
|
// tell Value to invalidate itself (run the CoerceValueCallback() method again)
|
|
control.InvalidateProperty(ValueProperty);
|
|
}
|
|
|
|
|
|
public static readonly DependencyProperty ThousandSeparatorProperty =
|
|
DependencyProperty.Register(
|
|
nameof(ThousandSeparator),
|
|
typeof(bool),
|
|
typeof(UCKeyValueNumber),
|
|
new PropertyMetadata(
|
|
false, OnIsThousandSeperatorVisibleChanged)
|
|
);
|
|
|
|
public bool ThousandSeparator {
|
|
get { return (bool)GetValue(ThousandSeparatorProperty); }
|
|
set { SetValue(ThousandSeparatorProperty, value); }
|
|
}
|
|
|
|
private static void OnIsThousandSeperatorVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
var control = (UCKeyValueNumber)d;
|
|
|
|
control.InvalidateProperty(ValueProperty);
|
|
}
|
|
|
|
public static readonly DependencyProperty UnitProperty
|
|
= DependencyProperty.Register(nameof(Unit),
|
|
typeof(string),
|
|
typeof(UCKeyValueNumber),
|
|
new FrameworkPropertyMetadata(
|
|
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
|
|
|
public string Unit {
|
|
get { return (string)GetValue(UnitProperty); }
|
|
set { SetValue(UnitProperty, value); }
|
|
}
|
|
|
|
public static readonly DependencyProperty ShowKeypadProperty
|
|
= DependencyProperty.Register(nameof(ShowKeypad), typeof(bool), typeof(UCKeyValueNumber),
|
|
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
|
|
|
public bool ShowKeypad {
|
|
get { return (bool)GetValue(ShowKeypadProperty); }
|
|
set { SetValue(ShowKeypadProperty, value); }
|
|
}
|
|
|
|
public UCKeyValueNumber()
|
|
{
|
|
//===============
|
|
// 국가마다 숫자 표기 (특히 소수점)가 다르므로, 소수점 표기 관련
|
|
Culture = (CultureInfo)CultureInfo.CurrentCulture.Clone(); // 복사
|
|
// 소수점 속성 변경
|
|
Culture.NumberFormat.NumberDecimalDigits = DecimalPlaces;
|
|
}
|
|
|
|
public int GetDecimalPlacesCount(String valueString)
|
|
{
|
|
// 첫번째 소수점을 찾은 후, counts all characters that follow
|
|
return valueString.SkipWhile(c => c.ToString(Culture) != Culture.NumberFormat.NumberDecimalSeparator).Skip(1).Count();
|
|
}
|
|
|
|
private decimal TruncateValue(string valueString, int decimalPlaces)
|
|
{
|
|
var endPoint = valueString.Length - (decimalPlaces - DecimalPlaces);
|
|
var tempValueString = valueString.Substring(0, endPoint);
|
|
|
|
return decimal.Parse(tempValueString, Culture);
|
|
}
|
|
|
|
protected abstract void ChangeThousandSeparator(decimal value);
|
|
|
|
protected void ShowNumberKeypad(TextBox text)
|
|
{
|
|
WinKBDNumber window = new WinKBDNumber();
|
|
window.IsAllowPoint = DecimalPlaces == 0 ? false : true;
|
|
window.IsAllowMinus = true;
|
|
window.Unit = Unit;
|
|
window.Value = Value.ToString();
|
|
window.Owner = Window.GetWindow(this);
|
|
window.ResultCallback = KBDWindowResult;
|
|
window.SetWindowControl(Window.GetWindow(this), text);
|
|
window.Show();
|
|
}
|
|
|
|
private void KBDWindowResult(string strValue)
|
|
{
|
|
Value = Convert.ToDecimal(strValue);
|
|
}
|
|
|
|
private void CoerceValue2Bounds(ref decimal value)
|
|
{
|
|
|
|
}
|
|
|
|
protected decimal ParseString2Decimal(string source)
|
|
{
|
|
_ = decimal.TryParse(source, out decimal value);
|
|
|
|
return value;
|
|
}
|
|
}
|
|
}
|