Growl.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Documents;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Threading;
  10. using HandyControl.Data;
  11. using HandyControl.Interactivity;
  12. using HandyControl.Properties.Langs;
  13. using HandyControl.Tools;
  14. using HandyControl.Tools.Extension;
  15. namespace HandyControl.Controls;
  16. /// <summary>
  17. /// 消息提醒
  18. /// </summary>
  19. [TemplatePart(Name = ElementPanelMore, Type = typeof(Panel))]
  20. [TemplatePart(Name = ElementGridMain, Type = typeof(Grid))]
  21. [TemplatePart(Name = ElementButtonClose, Type = typeof(Button))]
  22. public class Growl : Control
  23. {
  24. private const string ElementPanelMore = "PART_PanelMore";
  25. private const string ElementGridMain = "PART_GridMain";
  26. private const string ElementButtonClose = "PART_ButtonClose";
  27. private const int MinWaitTime = 2;
  28. public static readonly DependencyProperty GrowlParentProperty = DependencyProperty.RegisterAttached(
  29. "GrowlParent", typeof(bool), typeof(Growl), new PropertyMetadata(ValueBoxes.FalseBox, (o, args) =>
  30. {
  31. if ((bool) args.NewValue && o is Panel panel)
  32. {
  33. SetGrowlPanel(panel);
  34. }
  35. }));
  36. public static readonly DependencyProperty ShowModeProperty = DependencyProperty.RegisterAttached(
  37. "ShowMode", typeof(GrowlShowMode), typeof(Growl),
  38. new FrameworkPropertyMetadata(default(GrowlShowMode), FrameworkPropertyMetadataOptions.Inherits));
  39. public static readonly DependencyProperty ShowDateTimeProperty = DependencyProperty.Register(
  40. nameof(ShowDateTime), typeof(bool), typeof(Growl), new PropertyMetadata(ValueBoxes.TrueBox));
  41. public static readonly DependencyProperty MessageProperty = DependencyProperty.Register(
  42. nameof(Message), typeof(string), typeof(Growl), new PropertyMetadata(default(string)));
  43. public static readonly DependencyProperty TimeProperty = DependencyProperty.Register(
  44. nameof(Time), typeof(DateTime), typeof(Growl), new PropertyMetadata(default(DateTime)));
  45. public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
  46. nameof(Icon), typeof(Geometry), typeof(Growl), new PropertyMetadata(default(Geometry)));
  47. public static readonly DependencyProperty IconBrushProperty = DependencyProperty.Register(
  48. nameof(IconBrush), typeof(Brush), typeof(Growl), new PropertyMetadata(default(Brush)));
  49. public static readonly DependencyProperty TypeProperty = DependencyProperty.Register(
  50. nameof(Type), typeof(InfoType), typeof(Growl), new PropertyMetadata(default(InfoType)));
  51. public static readonly DependencyProperty TokenProperty = DependencyProperty.RegisterAttached(
  52. "Token", typeof(string), typeof(Growl), new PropertyMetadata(default(string), OnTokenChanged));
  53. internal static readonly DependencyProperty CancelStrProperty = DependencyProperty.Register(
  54. nameof(CancelStr), typeof(string), typeof(Growl), new PropertyMetadata(default(string)));
  55. internal static readonly DependencyProperty ConfirmStrProperty = DependencyProperty.Register(
  56. nameof(ConfirmStr), typeof(string), typeof(Growl), new PropertyMetadata(default(string)));
  57. private static readonly DependencyProperty IsCreatedAutomaticallyProperty = DependencyProperty.RegisterAttached(
  58. "IsCreatedAutomatically", typeof(bool), typeof(Growl), new PropertyMetadata(ValueBoxes.FalseBox));
  59. private static GrowlWindow GrowlWindow;
  60. private static readonly Dictionary<string, Panel> PanelDic = new();
  61. private Panel _panelMore;
  62. private Grid _gridMain;
  63. private Button _buttonClose;
  64. private bool _showCloseButton;
  65. private bool _staysOpen;
  66. private int _waitTime = 6;
  67. /// <summary>
  68. /// 计数
  69. /// </summary>
  70. private int _tickCount;
  71. /// <summary>
  72. /// 关闭计时器
  73. /// </summary>
  74. private DispatcherTimer _timerClose;
  75. /// <summary>
  76. /// 消息容器
  77. /// </summary>
  78. public static Panel GrowlPanel { get; set; }
  79. public InfoType Type
  80. {
  81. get => (InfoType) GetValue(TypeProperty);
  82. set => SetValue(TypeProperty, value);
  83. }
  84. public bool ShowDateTime
  85. {
  86. get => (bool) GetValue(ShowDateTimeProperty);
  87. set => SetValue(ShowDateTimeProperty, ValueBoxes.BooleanBox(value));
  88. }
  89. public string Message
  90. {
  91. get => (string) GetValue(MessageProperty);
  92. set => SetValue(MessageProperty, value);
  93. }
  94. public DateTime Time
  95. {
  96. get => (DateTime) GetValue(TimeProperty);
  97. set => SetValue(TimeProperty, value);
  98. }
  99. public Geometry Icon
  100. {
  101. get => (Geometry) GetValue(IconProperty);
  102. set => SetValue(IconProperty, value);
  103. }
  104. public Brush IconBrush
  105. {
  106. get => (Brush) GetValue(IconBrushProperty);
  107. set => SetValue(IconBrushProperty, value);
  108. }
  109. internal string CancelStr
  110. {
  111. get => (string) GetValue(CancelStrProperty);
  112. set => SetValue(CancelStrProperty, value);
  113. }
  114. internal string ConfirmStr
  115. {
  116. get => (string) GetValue(ConfirmStrProperty);
  117. set => SetValue(ConfirmStrProperty, value);
  118. }
  119. private Func<bool, bool> ActionBeforeClose { get; set; }
  120. public Growl()
  121. {
  122. CommandBindings.Add(new CommandBinding(ControlCommands.Close, ButtonClose_OnClick));
  123. CommandBindings.Add(new CommandBinding(ControlCommands.Cancel, ButtonCancel_OnClick));
  124. CommandBindings.Add(new CommandBinding(ControlCommands.Confirm, ButtonOk_OnClick));
  125. }
  126. public static void Register(string token, Panel panel)
  127. {
  128. if (string.IsNullOrEmpty(token) || panel == null) return;
  129. PanelDic[token] = panel;
  130. InitGrowlPanel(panel);
  131. }
  132. public static void Unregister(string token, Panel panel)
  133. {
  134. if (string.IsNullOrEmpty(token) || panel == null) return;
  135. if (PanelDic.ContainsKey(token))
  136. {
  137. if (ReferenceEquals(PanelDic[token], panel))
  138. {
  139. PanelDic.Remove(token);
  140. panel.ContextMenu = null;
  141. panel.SetCurrentValue(PanelElement.FluidMoveBehaviorProperty, DependencyProperty.UnsetValue);
  142. }
  143. }
  144. }
  145. public static void Unregister(Panel panel)
  146. {
  147. if (panel == null) return;
  148. var first = PanelDic.FirstOrDefault(item => ReferenceEquals(panel, item.Value));
  149. if (!string.IsNullOrEmpty(first.Key))
  150. {
  151. PanelDic.Remove(first.Key);
  152. panel.ContextMenu = null;
  153. panel.SetCurrentValue(PanelElement.FluidMoveBehaviorProperty, DependencyProperty.UnsetValue);
  154. }
  155. }
  156. public static void Unregister(string token)
  157. {
  158. if (string.IsNullOrEmpty(token)) return;
  159. if (PanelDic.ContainsKey(token))
  160. {
  161. var panel = PanelDic[token];
  162. PanelDic.Remove(token);
  163. panel.ContextMenu = null;
  164. panel.SetCurrentValue(PanelElement.FluidMoveBehaviorProperty, DependencyProperty.UnsetValue);
  165. }
  166. }
  167. protected override void OnMouseEnter(MouseEventArgs e)
  168. {
  169. base.OnMouseEnter(e);
  170. _buttonClose.Show(_showCloseButton);
  171. }
  172. protected override void OnMouseLeave(MouseEventArgs e)
  173. {
  174. base.OnMouseLeave(e);
  175. _buttonClose.Collapse();
  176. }
  177. public override void OnApplyTemplate()
  178. {
  179. base.OnApplyTemplate();
  180. _panelMore = GetTemplateChild(ElementPanelMore) as Panel;
  181. _gridMain = GetTemplateChild(ElementGridMain) as Grid;
  182. _buttonClose = GetTemplateChild(ElementButtonClose) as Button;
  183. CheckNull();
  184. Update();
  185. }
  186. private void CheckNull()
  187. {
  188. if (_panelMore == null || _gridMain == null || _buttonClose == null) throw new Exception();
  189. }
  190. private static void OnTokenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  191. {
  192. if (d is Panel panel)
  193. {
  194. if (e.NewValue == null)
  195. {
  196. Unregister(panel);
  197. }
  198. else
  199. {
  200. Register(e.NewValue.ToString(), panel);
  201. }
  202. }
  203. }
  204. public static void SetToken(DependencyObject element, string value) => element.SetValue(TokenProperty, value);
  205. public static string GetToken(DependencyObject element) => (string) element.GetValue(TokenProperty);
  206. public static void SetShowMode(DependencyObject element, GrowlShowMode value) => element.SetValue(ShowModeProperty, value);
  207. public static GrowlShowMode GetShowMode(DependencyObject element) => (GrowlShowMode) element.GetValue(ShowModeProperty);
  208. public static void SetGrowlParent(DependencyObject element, bool value) => element.SetValue(GrowlParentProperty, ValueBoxes.BooleanBox(value));
  209. public static bool GetGrowlParent(DependencyObject element) => (bool) element.GetValue(GrowlParentProperty);
  210. private static void SetIsCreatedAutomatically(DependencyObject element, bool value) => element.SetValue(IsCreatedAutomaticallyProperty, ValueBoxes.BooleanBox(value));
  211. private static bool GetIsCreatedAutomatically(DependencyObject element) => (bool) element.GetValue(IsCreatedAutomaticallyProperty);
  212. /// <summary>
  213. /// 开始计时器
  214. /// </summary>
  215. private void StartTimer()
  216. {
  217. _timerClose = new DispatcherTimer
  218. {
  219. Interval = TimeSpan.FromSeconds(1)
  220. };
  221. _timerClose.Tick += delegate
  222. {
  223. if (IsMouseOver)
  224. {
  225. _tickCount = 0;
  226. return;
  227. }
  228. _tickCount++;
  229. if (_tickCount >= _waitTime)
  230. {
  231. Close(true);
  232. }
  233. };
  234. _timerClose.Start();
  235. }
  236. /// <summary>
  237. /// 消息容器
  238. /// </summary>
  239. /// <param name="panel"></param>
  240. private static void SetGrowlPanel(Panel panel)
  241. {
  242. GrowlPanel = panel;
  243. InitGrowlPanel(panel);
  244. }
  245. private static void InitGrowlPanel(Panel panel)
  246. {
  247. if (panel == null) return;
  248. var menuItem = new MenuItem();
  249. LangProvider.SetLang(menuItem, HeaderedItemsControl.HeaderProperty, LangKeys.Clear);
  250. menuItem.Click += (s, e) =>
  251. {
  252. foreach (var item in panel.Children.OfType<Growl>())
  253. {
  254. item.Close(false);
  255. }
  256. };
  257. panel.ContextMenu = new ContextMenu
  258. {
  259. Items =
  260. {
  261. menuItem
  262. }
  263. };
  264. PanelElement.SetFluidMoveBehavior(panel, ResourceHelper.GetResourceInternal<FluidMoveBehavior>(ResourceToken.BehaviorXY400));
  265. }
  266. private void Update()
  267. {
  268. if (DesignerHelper.IsInDesignMode) return;
  269. if (Type == InfoType.Ask)
  270. {
  271. _panelMore.IsEnabled = true;
  272. _panelMore.Show();
  273. }
  274. var transform = new TranslateTransform
  275. {
  276. X = FlowDirection == FlowDirection.LeftToRight ? MaxWidth : -MaxWidth
  277. };
  278. _gridMain.RenderTransform = transform;
  279. transform.BeginAnimation(TranslateTransform.XProperty, AnimationHelper.CreateAnimation(0));
  280. if (!_staysOpen) StartTimer();
  281. }
  282. private static void ShowInternal(Panel panel, UIElement growl)
  283. {
  284. if (panel is null)
  285. {
  286. return;
  287. }
  288. if (GetShowMode(panel) == GrowlShowMode.Prepend)
  289. {
  290. panel.Children.Insert(0, growl);
  291. }
  292. else
  293. {
  294. panel.Children.Add(growl);
  295. }
  296. }
  297. private static void ShowGlobal(GrowlInfo growlInfo)
  298. {
  299. Application.Current.Dispatcher?.Invoke(
  300. #if NET40
  301. new Action(
  302. #endif
  303. () =>
  304. {
  305. if (GrowlWindow == null)
  306. {
  307. GrowlWindow = new GrowlWindow();
  308. GrowlWindow.Show();
  309. InitGrowlPanel(GrowlWindow.GrowlPanel);
  310. GrowlWindow.Init();
  311. }
  312. GrowlWindow.Show(true);
  313. var ctl = new Growl
  314. {
  315. Message = growlInfo.Message,
  316. Time = DateTime.Now,
  317. Icon = ResourceHelper.GetResource<Geometry>(growlInfo.IconKey) ?? growlInfo.Icon,
  318. IconBrush = ResourceHelper.GetResource<Brush>(growlInfo.IconBrushKey) ?? growlInfo.IconBrush,
  319. _showCloseButton = growlInfo.ShowCloseButton,
  320. ActionBeforeClose = growlInfo.ActionBeforeClose,
  321. _staysOpen = growlInfo.StaysOpen,
  322. ShowDateTime = growlInfo.ShowDateTime,
  323. ConfirmStr = growlInfo.ConfirmStr,
  324. CancelStr = growlInfo.CancelStr,
  325. Type = growlInfo.Type,
  326. _waitTime = Math.Max(growlInfo.WaitTime, MinWaitTime),
  327. FlowDirection = growlInfo.FlowDirection
  328. };
  329. ShowInternal(GrowlWindow.GrowlPanel, ctl);
  330. }
  331. #if NET40
  332. )
  333. #endif
  334. );
  335. }
  336. /// <summary>
  337. /// 显示信息
  338. /// </summary>
  339. /// <param name="growlInfo"></param>
  340. private static void Show(GrowlInfo growlInfo)
  341. {
  342. (Application.Current.Dispatcher ?? growlInfo.Dispatcher)?.Invoke(
  343. #if NET40
  344. new Action(
  345. #endif
  346. () =>
  347. {
  348. var ctl = new Growl
  349. {
  350. Message = growlInfo.Message,
  351. Time = DateTime.Now,
  352. Icon = ResourceHelper.GetResource<Geometry>(growlInfo.IconKey) ?? growlInfo.Icon,
  353. IconBrush = ResourceHelper.GetResource<Brush>(growlInfo.IconBrushKey) ?? growlInfo.IconBrush,
  354. _showCloseButton = growlInfo.ShowCloseButton,
  355. ActionBeforeClose = growlInfo.ActionBeforeClose,
  356. _staysOpen = growlInfo.StaysOpen,
  357. ShowDateTime = growlInfo.ShowDateTime,
  358. ConfirmStr = growlInfo.ConfirmStr,
  359. CancelStr = growlInfo.CancelStr,
  360. Type = growlInfo.Type,
  361. _waitTime = Math.Max(growlInfo.WaitTime, MinWaitTime)
  362. };
  363. if (!string.IsNullOrEmpty(growlInfo.Token))
  364. {
  365. if (PanelDic.TryGetValue(growlInfo.Token, out var panel))
  366. {
  367. ShowInternal(panel, ctl);
  368. }
  369. }
  370. else
  371. {
  372. // GrowlPanel is null, we create it automatically
  373. GrowlPanel ??= CreateDefaultPanel();
  374. ShowInternal(GrowlPanel, ctl);
  375. }
  376. }
  377. #if NET40
  378. )
  379. #endif
  380. );
  381. }
  382. private static Panel CreateDefaultPanel()
  383. {
  384. FrameworkElement element = WindowHelper.GetActiveWindow();
  385. var decorator = VisualHelper.GetChild<AdornerDecorator>(element);
  386. if (decorator != null)
  387. {
  388. var layer = decorator.AdornerLayer;
  389. if (layer != null)
  390. {
  391. var panel = new StackPanel
  392. {
  393. VerticalAlignment = VerticalAlignment.Top
  394. };
  395. InitGrowlPanel(panel);
  396. SetIsCreatedAutomatically(panel, true);
  397. var scrollViewer = new ScrollViewer
  398. {
  399. HorizontalAlignment = HorizontalAlignment.Right,
  400. VerticalScrollBarVisibility = ScrollBarVisibility.Hidden,
  401. IsInertiaEnabled = true,
  402. IsPenetrating = true,
  403. Content = panel
  404. };
  405. var container = new AdornerContainer(layer)
  406. {
  407. Child = scrollViewer
  408. };
  409. layer.Add(container);
  410. return panel;
  411. }
  412. }
  413. return null;
  414. }
  415. private static void RemoveDefaultPanel(Panel panel)
  416. {
  417. FrameworkElement element = WindowHelper.GetActiveWindow();
  418. var decorator = VisualHelper.GetChild<AdornerDecorator>(element);
  419. if (decorator != null)
  420. {
  421. var layer = decorator.AdornerLayer;
  422. var adorner = VisualHelper.GetParent<Adorner>(panel);
  423. if (adorner != null)
  424. {
  425. layer?.Remove(adorner);
  426. }
  427. }
  428. }
  429. private static void InitGrowlInfo(ref GrowlInfo growlInfo, InfoType infoType)
  430. {
  431. if (growlInfo == null) throw new ArgumentNullException(nameof(growlInfo));
  432. growlInfo.Type = infoType;
  433. switch (infoType)
  434. {
  435. case InfoType.Success:
  436. if (!growlInfo.IsCustom)
  437. {
  438. growlInfo.IconKey = ResourceToken.SuccessGeometry;
  439. growlInfo.IconBrushKey = ResourceToken.SuccessBrush;
  440. }
  441. else
  442. {
  443. growlInfo.IconKey ??= ResourceToken.SuccessGeometry;
  444. growlInfo.IconBrushKey ??= ResourceToken.SuccessBrush;
  445. }
  446. break;
  447. case InfoType.Info:
  448. if (!growlInfo.IsCustom)
  449. {
  450. growlInfo.IconKey = ResourceToken.InfoGeometry;
  451. growlInfo.IconBrushKey = ResourceToken.InfoBrush;
  452. }
  453. else
  454. {
  455. growlInfo.IconKey ??= ResourceToken.InfoGeometry;
  456. growlInfo.IconBrushKey ??= ResourceToken.InfoBrush;
  457. }
  458. break;
  459. case InfoType.Warning:
  460. if (!growlInfo.IsCustom)
  461. {
  462. growlInfo.IconKey = ResourceToken.WarningGeometry;
  463. growlInfo.IconBrushKey = ResourceToken.WarningBrush;
  464. }
  465. else
  466. {
  467. growlInfo.IconKey ??= ResourceToken.WarningGeometry;
  468. growlInfo.IconBrushKey ??= ResourceToken.WarningBrush;
  469. }
  470. break;
  471. case InfoType.Error:
  472. if (!growlInfo.IsCustom)
  473. {
  474. growlInfo.IconKey = ResourceToken.ErrorGeometry;
  475. growlInfo.IconBrushKey = ResourceToken.DangerBrush;
  476. growlInfo.StaysOpen = true;
  477. }
  478. else
  479. {
  480. growlInfo.IconKey ??= ResourceToken.ErrorGeometry;
  481. growlInfo.IconBrushKey ??= ResourceToken.DangerBrush;
  482. }
  483. break;
  484. case InfoType.Fatal:
  485. if (!growlInfo.IsCustom)
  486. {
  487. growlInfo.IconKey = ResourceToken.FatalGeometry;
  488. growlInfo.IconBrushKey = ResourceToken.PrimaryTextBrush;
  489. growlInfo.StaysOpen = true;
  490. growlInfo.ShowCloseButton = false;
  491. }
  492. else
  493. {
  494. growlInfo.IconKey ??= ResourceToken.FatalGeometry;
  495. growlInfo.IconBrushKey ??= ResourceToken.PrimaryTextBrush;
  496. }
  497. break;
  498. case InfoType.Ask:
  499. growlInfo.StaysOpen = true;
  500. growlInfo.ShowCloseButton = false;
  501. if (!growlInfo.IsCustom)
  502. {
  503. growlInfo.IconKey = ResourceToken.AskGeometry;
  504. growlInfo.IconBrushKey = ResourceToken.AccentBrush;
  505. }
  506. else
  507. {
  508. growlInfo.IconKey ??= ResourceToken.AskGeometry;
  509. growlInfo.IconBrushKey ??= ResourceToken.AccentBrush;
  510. }
  511. break;
  512. default:
  513. throw new ArgumentOutOfRangeException(nameof(infoType), infoType, null);
  514. }
  515. }
  516. /// <summary>
  517. /// 成功
  518. /// </summary>
  519. /// <param name="message"></param>
  520. /// <param name="token"></param>
  521. public static void Success(string message, string token = "") => Success(new GrowlInfo
  522. {
  523. Message = message,
  524. Token = token
  525. });
  526. /// <summary>
  527. /// 成功
  528. /// </summary>
  529. /// <param name="growlInfo"></param>
  530. public static void Success(GrowlInfo growlInfo)
  531. {
  532. InitGrowlInfo(ref growlInfo, InfoType.Success);
  533. Show(growlInfo);
  534. }
  535. /// <summary>
  536. /// 成功
  537. /// </summary>
  538. /// <param name="message"></param>
  539. public static void SuccessGlobal(string message) => SuccessGlobal(new GrowlInfo
  540. {
  541. Message = message
  542. });
  543. /// <summary>
  544. /// 成功
  545. /// </summary>
  546. /// <param name="growlInfo"></param>
  547. public static void SuccessGlobal(GrowlInfo growlInfo)
  548. {
  549. InitGrowlInfo(ref growlInfo, InfoType.Success);
  550. ShowGlobal(growlInfo);
  551. }
  552. /// <summary>
  553. /// 消息
  554. /// </summary>
  555. /// <param name="message"></param>
  556. /// <param name="token"></param>
  557. public static void Info(string message, string token = "") => Info(new GrowlInfo
  558. {
  559. Message = message,
  560. Token = token
  561. });
  562. /// <summary>
  563. /// 消息
  564. /// </summary>
  565. /// <param name="growlInfo"></param>
  566. public static void Info(GrowlInfo growlInfo)
  567. {
  568. InitGrowlInfo(ref growlInfo, InfoType.Info);
  569. Show(growlInfo);
  570. }
  571. /// <summary>
  572. /// 消息
  573. /// </summary>
  574. /// <param name="message"></param>
  575. public static void InfoGlobal(string message) => InfoGlobal(new GrowlInfo
  576. {
  577. Message = message
  578. });
  579. /// <summary>
  580. /// 消息
  581. /// </summary>
  582. /// <param name="growlInfo"></param>
  583. public static void InfoGlobal(GrowlInfo growlInfo)
  584. {
  585. InitGrowlInfo(ref growlInfo, InfoType.Info);
  586. ShowGlobal(growlInfo);
  587. }
  588. /// <summary>
  589. /// 警告
  590. /// </summary>
  591. /// <param name="message"></param>
  592. /// <param name="token"></param>
  593. public static void Warning(string message, string token = "") => Warning(new GrowlInfo
  594. {
  595. Message = message,
  596. Token = token
  597. });
  598. /// <summary>
  599. /// 警告
  600. /// </summary>
  601. /// <param name="growlInfo"></param>
  602. public static void Warning(GrowlInfo growlInfo)
  603. {
  604. InitGrowlInfo(ref growlInfo, InfoType.Warning);
  605. Show(growlInfo);
  606. }
  607. /// <summary>
  608. /// 警告
  609. /// </summary>
  610. /// <param name="message"></param>
  611. public static void WarningGlobal(string message) => WarningGlobal(new GrowlInfo
  612. {
  613. Message = message
  614. });
  615. /// <summary>
  616. /// 警告
  617. /// </summary>
  618. /// <param name="growlInfo"></param>
  619. public static void WarningGlobal(GrowlInfo growlInfo)
  620. {
  621. InitGrowlInfo(ref growlInfo, InfoType.Warning);
  622. ShowGlobal(growlInfo);
  623. }
  624. /// <summary>
  625. /// 错误
  626. /// </summary>
  627. /// <param name="message"></param>
  628. /// <param name="token"></param>
  629. public static void Error(string message, string token = "") => Error(new GrowlInfo
  630. {
  631. Message = message,
  632. Token = token
  633. });
  634. /// <summary>
  635. /// 错误
  636. /// </summary>
  637. /// <param name="growlInfo"></param>
  638. public static void Error(GrowlInfo growlInfo)
  639. {
  640. InitGrowlInfo(ref growlInfo, InfoType.Error);
  641. Show(growlInfo);
  642. }
  643. /// <summary>
  644. /// 错误
  645. /// </summary>
  646. /// <param name="message"></param>
  647. public static void ErrorGlobal(string message) => ErrorGlobal(new GrowlInfo
  648. {
  649. Message = message
  650. });
  651. /// <summary>
  652. /// 错误
  653. /// </summary>
  654. /// <param name="growlInfo"></param>
  655. public static void ErrorGlobal(GrowlInfo growlInfo)
  656. {
  657. InitGrowlInfo(ref growlInfo, InfoType.Error);
  658. ShowGlobal(growlInfo);
  659. }
  660. /// <summary>
  661. /// 严重
  662. /// </summary>
  663. /// <param name="message"></param>
  664. /// <param name="token"></param>
  665. public static void Fatal(string message, string token = "") => Fatal(new GrowlInfo
  666. {
  667. Message = message,
  668. Token = token
  669. });
  670. /// <summary>
  671. /// 严重
  672. /// </summary>
  673. /// <param name="growlInfo"></param>
  674. public static void Fatal(GrowlInfo growlInfo)
  675. {
  676. InitGrowlInfo(ref growlInfo, InfoType.Fatal);
  677. Show(growlInfo);
  678. }
  679. /// <summary>
  680. /// 严重
  681. /// </summary>
  682. /// <param name="message"></param>
  683. public static void FatalGlobal(string message) => FatalGlobal(new GrowlInfo
  684. {
  685. Message = message
  686. });
  687. /// <summary>
  688. /// 严重
  689. /// </summary>
  690. /// <param name="growlInfo"></param>
  691. public static void FatalGlobal(GrowlInfo growlInfo)
  692. {
  693. InitGrowlInfo(ref growlInfo, InfoType.Fatal);
  694. ShowGlobal(growlInfo);
  695. }
  696. /// <summary>
  697. /// 询问
  698. /// </summary>
  699. /// <param name="message"></param>
  700. /// <param name="actionBeforeClose"></param>
  701. /// <param name="token"></param>
  702. public static void Ask(string message, Func<bool, bool> actionBeforeClose, string token = "") => Ask(new GrowlInfo
  703. {
  704. Message = message,
  705. ActionBeforeClose = actionBeforeClose,
  706. Token = token
  707. });
  708. /// <summary>
  709. /// 询问
  710. /// </summary>
  711. /// <param name="growlInfo"></param>
  712. public static void Ask(GrowlInfo growlInfo)
  713. {
  714. InitGrowlInfo(ref growlInfo, InfoType.Ask);
  715. Show(growlInfo);
  716. }
  717. /// <summary>
  718. /// 询问
  719. /// </summary>
  720. /// <param name="message"></param>
  721. /// <param name="actionBeforeClose"></param>
  722. public static void AskGlobal(string message, Func<bool, bool> actionBeforeClose) => AskGlobal(new GrowlInfo
  723. {
  724. Message = message,
  725. ActionBeforeClose = actionBeforeClose
  726. });
  727. /// <summary>
  728. /// 询问
  729. /// </summary>
  730. /// <param name="growlInfo"></param>
  731. public static void AskGlobal(GrowlInfo growlInfo)
  732. {
  733. InitGrowlInfo(ref growlInfo, InfoType.Ask);
  734. ShowGlobal(growlInfo);
  735. }
  736. private void ButtonClose_OnClick(object sender, RoutedEventArgs e) => Close(false);
  737. /// <summary>
  738. /// 关闭
  739. /// </summary>
  740. private void Close(bool invokeParam)
  741. {
  742. if (ActionBeforeClose?.Invoke(invokeParam) == false)
  743. {
  744. return;
  745. }
  746. _timerClose?.Stop();
  747. var transform = new TranslateTransform();
  748. _gridMain.RenderTransform = transform;
  749. var animation = AnimationHelper.CreateAnimation(FlowDirection == FlowDirection.LeftToRight ? ActualWidth : -ActualWidth);
  750. animation.Completed += (s, e) =>
  751. {
  752. if (Parent is Panel panel)
  753. {
  754. panel.Children.Remove(this);
  755. if (GrowlWindow != null)
  756. {
  757. if (GrowlWindow.GrowlPanel != null && GrowlWindow.GrowlPanel.Children.Count == 0)
  758. {
  759. GrowlWindow.Close();
  760. GrowlWindow = null;
  761. }
  762. }
  763. else
  764. {
  765. if (GrowlPanel != null && GrowlPanel.Children.Count == 0 && GetIsCreatedAutomatically(GrowlPanel))
  766. {
  767. // If the count of children is zero, we need to remove the panel, provided that the panel was created automatically
  768. RemoveDefaultPanel(GrowlPanel);
  769. GrowlPanel = null;
  770. }
  771. }
  772. }
  773. };
  774. transform.BeginAnimation(TranslateTransform.XProperty, animation);
  775. }
  776. /// <summary>
  777. /// 清除
  778. /// </summary>
  779. /// <param name="token"></param>
  780. public static void Clear(string token = "")
  781. {
  782. if (!string.IsNullOrEmpty(token))
  783. {
  784. if (PanelDic.TryGetValue(token, out var panel))
  785. {
  786. Clear(panel);
  787. }
  788. }
  789. else
  790. {
  791. Clear(GrowlPanel);
  792. }
  793. }
  794. /// <summary>
  795. /// 清除
  796. /// </summary>
  797. /// <param name="panel"></param>
  798. private static void Clear(Panel panel) => panel?.Children.Clear();
  799. /// <summary>
  800. /// 清除
  801. /// </summary>
  802. public static void ClearGlobal()
  803. {
  804. if (GrowlWindow == null) return;
  805. Clear(GrowlWindow.GrowlPanel);
  806. GrowlWindow.Close();
  807. GrowlWindow = null;
  808. }
  809. private void ButtonCancel_OnClick(object sender, RoutedEventArgs e) => Close(false);
  810. private void ButtonOk_OnClick(object sender, RoutedEventArgs e) => Close(true);
  811. }