Dreamine.UI.Wpf.Equipment 1.0.1
Dreamine.UI.Wpf.Equipment 사용자 인터페이스 기능과 구성 요소를 제공합니다.
로딩중...
검색중...
일치하는것 없음
DreaminePopupService.cs
이 파일의 문서화 페이지로 가기
1using System.Collections.Generic;
2using System.Linq;
3using System.Windows;
4using System.Windows.Threading;
5using Dreamine.UI.Abstractions.Popup;
6
8{
17 public sealed class DreaminePopupService : IPopupService
18 {
19 // UI 스레드 전용 — 모든 Add/Remove는 Dispatcher.InvokeAsync 또는 WPF 이벤트 핸들러에서만 수행
28 private readonly List<Window> _opened = new();
37 private readonly Dictionary<Window, BlinkPopupOptions> _optionsByWindow = new();
38
79 public bool? ShowBlink(Window? owner, BlinkPopupOptions options)
80 => ShowBlink(owner, options, out _);
81
130 public bool? ShowBlink(Window? owner, BlinkPopupOptions options, out Window windowRef)
131 {
132 var win = new DreamineBlinkPopupWindow(options);
133
134 // Owner 설정
135 if (owner != null)
136 {
137 win.Owner = owner;
138 win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
139 }
140 else
141 {
142 var active = GetActive() ?? Application.Current?.MainWindow;
143 if (active != null)
144 {
145 win.Owner = active;
146 win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
147 }
148 else
149 {
150 win.WindowStartupLocation = WindowStartupLocation.CenterScreen;
151 }
152 }
153
154 // 추적: 창 + 옵션
155 _opened.Add(win);
156 _optionsByWindow[win] = options;
157
158 // 정리: 창 닫힐 때 제거
159 win.Closed += (_, __) =>
160 {
161 _opened.Remove(win);
162 _optionsByWindow.Remove(win);
163 };
164
165 windowRef = win;
166
167 // 표시
168 if (options.IsModal)
169 {
170 return win.ShowDialog();
171 }
172 else
173 {
174 win.Show();
175 return null;
176 }
177 }
178
187 public void CloseAll()
188 {
189 foreach (var w in _opened.ToList())
190 if (w.IsLoaded) w.Close();
191
192 _opened.Clear();
193 _optionsByWindow.Clear();
194 }
195
212 public void Close(Window window)
213 {
214 if (window == null) return;
215 if (_opened.Contains(window) && window.IsLoaded)
216 window.Close();
217 }
218
235 public void CloseOwnedBy(Window owner)
236 {
237 if (owner == null) return;
238 var targets = _opened.Where(w => Equals(w.Owner, owner)).ToList();
239 foreach (var w in targets)
240 if (w.IsLoaded) w.Close();
241 }
242
259 public Window? GetActive()
260 => _opened.LastOrDefault(w => w.IsVisible && w.IsActive)
261 ?? _opened.LastOrDefault(w => w.IsVisible);
262
303 public bool TryGetOptions(Window window, out BlinkPopupOptions? options)
304 {
305 return _optionsByWindow.TryGetValue(window, out options);
306 }
307
340 public bool TryGetOwnerOptions(Window window, out BlinkPopupOptions? ownerOptions)
341 {
342 ownerOptions = null;
343 if (window?.Owner == null) return false;
344 return _optionsByWindow.TryGetValue(window.Owner, out ownerOptions);
345 }
346
379 public void RegisterWindow(Window window, BlinkPopupOptions options)
380 {
381 if (window is null)
382 throw new ArgumentNullException(nameof(window));
383
384 // 중복 등록 방지
385 if (_opened.Contains(window))
386 return;
387
388 _opened.Add(window);
389 _optionsByWindow[window] = options;
390
391 window.Closed += (_, __) =>
392 {
393 _opened.Remove(window);
394 _optionsByWindow.Remove(window);
395 };
396 }
397
398 // ========================= 비동기 구현 =========================
399
464 public async Task<bool?> ShowBlinkAsync(
465 Window? owner,
466 BlinkPopupOptions options,
467 TimeSpan? autoCloseAfter = null,
468 CancellationToken cancellationToken = default)
469 {
470 // 모든 UI 조작은 UI 스레드에서
471 var dispatcher = (owner ?? Application.Current?.MainWindow)?.Dispatcher
472 ?? Application.Current!.Dispatcher;
473
474 if (dispatcher == null)
475 throw new InvalidOperationException("Dispatcher not available.");
476
477 var tcs = new TaskCompletionSource<bool?>(TaskCreationOptions.RunContinuationsAsynchronously);
478 Window? win = null;
479 bool wasOwnerEnabled = false;
480
481 await dispatcher.InvokeAsync(() =>
482 {
483 win = new DreamineBlinkPopupWindow(options);
484
485 // Owner 결정
486 if (owner != null)
487 {
488 win.Owner = owner;
489 win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
490 }
491 else
492 {
493 var active = GetActive() ?? Application.Current?.MainWindow;
494 if (active != null)
495 {
496 win.Owner = active;
497 win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
498 }
499 else
500 {
501 win.WindowStartupLocation = WindowStartupLocation.CenterScreen;
502 }
503 }
504
505 // 등록
506 _opened.Add(win);
507 _optionsByWindow[win] = options;
508
509 // 닫힘 시 정리 + 결과 완료
510 win.Closed += (_, __) =>
511 {
512 _opened.Remove(win);
513 _optionsByWindow.Remove(win);
514
515 // 모달 효과 복원
516 if (options.IsModal && win.Owner != null && wasOwnerEnabled)
517 win.Owner.IsEnabled = true;
518
519 // Show()로 열린 경우 DialogResult는 항상 null → PopupResult 사용
520 var result = (win as DreamineBlinkPopupWindow)?.PopupResult
521 ?? (win as Window)?.DialogResult;
522 _ = tcs.TrySetResult(result);
523 };
524
525 // 모달 효과: Owner 잠시 비활성화
526 if (options.IsModal && win.Owner != null)
527 {
528 wasOwnerEnabled = win.Owner.IsEnabled;
529 win.Owner.IsEnabled = false;
530 }
531
532 // 표시(비동기 모달 시뮬레이션: ShowDialog 대신 Show 사용)
533 win.Show();
534
535 // 자동 종료 타이머
536 if (autoCloseAfter is TimeSpan delay && delay > TimeSpan.Zero)
537 {
538 var timer = new DispatcherTimer { Interval = delay };
539 timer.Tick += (s, e) =>
540 {
541 timer.Stop();
542 if (win.IsLoaded) win.Close();
543 };
544 timer.Start();
545 }
546 });
547
548 // 취소 토큰 연동: 취소 시 UI 스레드에서 닫기
549 using (cancellationToken.Register(() =>
550 {
551 if (win != null)
552 {
553 _ = dispatcher.InvokeAsync(() =>
554 {
555 if (win.IsLoaded) win.Close();
556 });
557 }
558 }))
559 {
560 return await tcs.Task.ConfigureAwait(false);
561 }
562 }
563 }
564}
bool? ShowBlink(Window? owner, BlinkPopupOptions options, out Window windowRef)
readonly Dictionary< Window, BlinkPopupOptions > _optionsByWindow
bool? ShowBlink(Window? owner, BlinkPopupOptions options)
void RegisterWindow(Window window, BlinkPopupOptions options)
bool TryGetOptions(Window window, out BlinkPopupOptions? options)
async Task< bool?> ShowBlinkAsync(Window? owner, BlinkPopupOptions options, TimeSpan? autoCloseAfter=null, CancellationToken cancellationToken=default)
bool TryGetOwnerOptions(Window window, out BlinkPopupOptions? ownerOptions)