Dreamine.UI.Maui 1.0.1
Windows(WinUI)의 네이티브 `CheckBox`는 `WidthRequest`로 줄일 수 없는 거대한 최소 너비를 가져서 라벨과의 간격이 벌어지는 문제가 있어, 처음부터 직접 그려서 만들었습니다.
로딩중...
검색중...
일치하는것 없음
HangulComposer.cs
이 파일의 문서화 페이지로 가기
1namespace Dreamine.UI.Maui;
2
19internal sealed class HangulComposer
20{
29 private static readonly string[] Cho =
30 [
31 "ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", "ㅃ", "ㅅ",
32 "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ"
33 ];
34
43 private static readonly string[] Jung =
44 [
45 "ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ",
46 "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ", "ㅣ"
47 ];
48
57 private static readonly string[] Jong =
58 [
59 "", "ㄱ", "ㄲ", "ㄳ", "ㄴ", "ㄵ", "ㄶ", "ㄷ", "ㄹ", "ㄺ",
60 "ㄻ", "ㄼ", "ㄽ", "ㄾ", "ㄿ", "ㅀ", "ㅁ", "ㅂ", "ㅄ", "ㅅ",
61 "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ"
62 ];
63
72 private static readonly Dictionary<string, int> ChoIndex = Cho.Select((v, i) => (v, i)).ToDictionary(x => x.v, x => x.i);
81 private static readonly Dictionary<string, int> JungIndex = Jung.Select((v, i) => (v, i)).ToDictionary(x => x.v, x => x.i);
90 private static readonly Dictionary<string, int> JongIndex = Jong.Select((v, i) => (v, i)).Where(x => x.v.Length > 0).ToDictionary(x => x.v, x => x.i);
91
100 private static readonly Dictionary<(int First, int Second), int> CombinedJung = new()
101 {
102 [(8, 0)] = 9, [(8, 1)] = 10, [(8, 20)] = 11,
103 [(13, 4)] = 14, [(13, 5)] = 15, [(13, 20)] = 16,
104 [(18, 20)] = 19,
105 };
106
115 private static readonly Dictionary<(int First, int Second), int> CombinedJong = new()
116 {
117 [(1, 19)] = 3, [(4, 22)] = 5, [(4, 27)] = 6,
118 [(8, 1)] = 9, [(8, 16)] = 10, [(8, 17)] = 11,
119 [(8, 19)] = 12, [(8, 25)] = 13, [(8, 26)] = 14,
120 [(8, 27)] = 15, [(17, 19)] = 18,
121 };
122
131 private static readonly Dictionary<int, (int First, int Second)> SplitJong = CombinedJong.ToDictionary(x => x.Value, x => x.Key);
132
141 private int _cho = -1;
150 private int _jung = -1;
159 private int _jong;
160
169 public void Reset()
170 {
171 _cho = -1;
172 _jung = -1;
173 _jong = 0;
174 }
175
208 public static bool IsComposableJamo(string text)
209 {
210 return text.Length == 1 && (ChoIndex.ContainsKey(text) || JungIndex.ContainsKey(text));
211 }
212
245 public HangulEdit Input(string text, string textBeforeCaret)
246 {
247 if (string.IsNullOrEmpty(text) || text.Length != 1)
248 {
249 Reset();
250 return new HangulEdit(0, text);
251 }
252
253 if (ChoIndex.TryGetValue(text, out var cho))
254 {
255 if (TryComposeConsonantWithTrailingText(textBeforeCaret, text, out var edit))
256 return edit;
257
258 if (!string.IsNullOrEmpty(textBeforeCaret))
259 {
260 Reset();
261 return new HangulEdit(0, text);
262 }
263
264 return InputConsonant(text, cho);
265 }
266
267 if (JungIndex.TryGetValue(text, out var jung))
268 {
269 if (TryComposeVowelWithTrailingText(textBeforeCaret, jung, out var edit))
270 return edit;
271
272 if (!string.IsNullOrEmpty(textBeforeCaret))
273 {
274 Reset();
275 return new HangulEdit(0, text);
276 }
277
278 return InputVowel(text, jung);
279 }
280
281 Reset();
282 return new HangulEdit(0, text);
283 }
284
325 private bool TryComposeConsonantWithTrailingText(string textBeforeCaret, string text, out HangulEdit edit)
326 {
327 edit = default;
328 if (string.IsNullOrEmpty(textBeforeCaret) || !JongIndex.TryGetValue(text, out var jong))
329 return false;
330
331 var last = textBeforeCaret[^1];
332 if (!TryDecompose(last, out var cho, out var jung, out var currentJong))
333 return false;
334
335 if (currentJong == 0)
336 {
337 _cho = cho;
338 _jung = jung;
339 _jong = jong;
340 edit = new HangulEdit(1, Compose(_cho, _jung, _jong));
341 return true;
342 }
343
344 if (CombinedJong.TryGetValue((currentJong, jong), out var combinedJong))
345 {
346 _cho = cho;
347 _jung = jung;
348 _jong = combinedJong;
349 edit = new HangulEdit(1, Compose(_cho, _jung, _jong));
350 return true;
351 }
352
353 return false;
354 }
355
396 private bool TryComposeVowelWithTrailingText(string textBeforeCaret, int jung, out HangulEdit edit)
397 {
398 edit = default;
399 if (string.IsNullOrEmpty(textBeforeCaret))
400 return false;
401
402 var last = textBeforeCaret[^1].ToString();
403 if (ChoIndex.TryGetValue(last, out var trailingCho))
404 {
405 _cho = trailingCho;
406 _jung = jung;
407 _jong = 0;
408 edit = new HangulEdit(1, Compose(_cho, _jung, 0));
409 return true;
410 }
411
412 var lastChar = textBeforeCaret[^1];
413 if (!TryDecompose(lastChar, out var cho, out var currentJung, out var jong) || jong == 0)
414 return false;
415
416 if (SplitJong.TryGetValue(jong, out var split))
417 {
418 var previous = Compose(cho, currentJung, split.First);
419 _cho = ToChoIndex(Jong[split.Second]);
420 _jung = jung;
421 _jong = 0;
422 edit = new HangulEdit(1, previous + Compose(_cho, _jung, 0));
423 return true;
424 }
425
426 _cho = ToChoIndex(Jong[jong]);
427 _jung = jung;
428 _jong = 0;
429 edit = new HangulEdit(1, Compose(cho, currentJung, 0) + Compose(_cho, _jung, 0));
430 return true;
431 }
432
465 private HangulEdit InputConsonant(string text, int cho)
466 {
467 if (_cho < 0 || _jung < 0)
468 {
469 _cho = cho;
470 return new HangulEdit(0, text);
471 }
472
473 if (_jong == 0 && JongIndex.TryGetValue(text, out var jong))
474 {
475 _jong = jong;
476 return new HangulEdit(1, Compose(_cho, _jung, _jong));
477 }
478
479 if (JongIndex.TryGetValue(text, out var nextJong) && CombinedJong.TryGetValue((_jong, nextJong), out var combinedJong))
480 {
481 _jong = combinedJong;
482 return new HangulEdit(1, Compose(_cho, _jung, _jong));
483 }
484
485 _cho = cho;
486 _jung = -1;
487 _jong = 0;
488 return new HangulEdit(0, text);
489 }
490
523 private HangulEdit InputVowel(string text, int jung)
524 {
525 if (_cho < 0)
526 {
527 Reset();
528 return new HangulEdit(0, text);
529 }
530
531 if (_jung < 0)
532 {
533 _jung = jung;
534 return new HangulEdit(1, Compose(_cho, _jung, 0));
535 }
536
537 if (_jong == 0 && CombinedJung.TryGetValue((_jung, jung), out var combinedJung))
538 {
539 _jung = combinedJung;
540 return new HangulEdit(1, Compose(_cho, _jung, 0));
541 }
542
543 Reset();
544 return new HangulEdit(0, text);
545 }
546
571 private static int ToChoIndex(string jong)
572 {
573 return ChoIndex.TryGetValue(jong, out var cho) ? cho : ChoIndex["ㅇ"];
574 }
575
624 private static string Compose(int cho, int jung, int jong)
625 {
626 return char.ConvertFromUtf32(0xAC00 + ((cho * 21) + jung) * 28 + jong);
627 }
628
677 private static bool TryDecompose(char value, out int cho, out int jung, out int jong)
678 {
679 var code = value - 0xAC00;
680 if (code < 0 || code >= 11172)
681 {
682 cho = -1;
683 jung = -1;
684 jong = 0;
685 return false;
686 }
687
688 cho = code / (21 * 28);
689 jung = (code % (21 * 28)) / 28;
690 jong = code % 28;
691 return true;
692 }
693}
694
719internal readonly record struct HangulEdit(int ReplaceCount, string Text);