Esempio n. 1
0
        private void InputOnLeftMouseButtonReleased(object sender, Blish_HUD.Input.MouseEventArgs e)
        {
            if (_screenshotPickerActive && Control.ActiveControl != null)
            {
                GameService.Graphics.QueueMainThreadRender((graphicsDevice) => {
                    var activeControl  = Control.ActiveControl;
                    var absoluteBounds = activeControl.AbsoluteBounds;

                    var bounds = absoluteBounds.WithPadding(activeControl.Padding);

                    var screenshotTarget = new RenderTarget2D(graphicsDevice,
                                                              GameService.Graphics.SpriteScreen.Width,
                                                              GameService.Graphics.SpriteScreen.Height,
                                                              false,
                                                              graphicsDevice.PresentationParameters.BackBufferFormat,
                                                              DepthFormat.Depth24);

                    graphicsDevice.SetRenderTarget(screenshotTarget);
                    graphicsDevice.Clear(Color.Transparent);

                    using (var screenshotSpriteBatch = new SpriteBatch(graphicsDevice)) {
                        //GameService.Graphics.SpriteScreen.Draw(screenshotSpriteBatch, new Rectangle(Point.Zero, GameService.Graphics.SpriteScreen.Size), new Rectangle(Point.Zero, GameService.Graphics.SpriteScreen.Size));
                        activeControl.Draw(screenshotSpriteBatch, new Rectangle(Point.Zero, activeControl.Size), new Rectangle(Point.Zero, GameService.Graphics.SpriteScreen.Size));
                    }

                    using (var pngStream = new MemoryStream()) {
                        var croppedTarget = screenshotTarget.GetRegion(bounds);

                        croppedTarget.SaveAsPng(pngStream, screenshotTarget.Width, screenshotTarget.Height);
                        pngStream.Seek(0, SeekOrigin.Begin);

                        var sysImg = System.Drawing.Image.FromStream(pngStream);

                        ClipboardUtils.SetClipboardImage(new Bitmap(sysImg), null, null);
                    }

                    ScreenNotification.ShowNotification("Screenshot copied to clipboard!");

                    graphicsDevice.SetRenderTarget(null);
                });

                _screenshotPickerActive = false;
            }
            else if (_magentaPickerActive && Control.ActiveControl != null)
            {
                Control.ActiveControl.BackgroundColor = Color.Magenta;

                _magentaPickerActive = false;
            }
            else if (_runtimeViewerPickerActive && Control.ActiveControl != null)
            {
                _toolboxForm?.SetActiveControl(Control.ActiveControl);

                _runtimeViewerPickerActive = false;
            }

            _controlHighlighter.Hide();
        }
        /// <summary>
        /// Allows your module to run logic such as updating UI elements,
        /// checking for conditions, playing audio, calculating changes, etc.
        /// This method will block the primary Blish HUD loop, so any long
        /// running tasks should be executed on a separate thread to prevent
        /// slowing down the overlay.
        /// </summary>
        protected override void Update(GameTime gameTime)
        {
            _runningTime += gameTime.ElapsedGameTime.TotalMilliseconds;

            if (_runningTime > 60000)
            {
                _runningTime -= 60000;
                ScreenNotification.ShowNotification("The examples module shows this message every 60 seconds!", ScreenNotification.NotificationType.Warning);
            }
        }
        private EventNotification(string title, AsyncTexture2D icon, string message, string waypoint)
        {
            const string TOOLTIP_TEXT = "Left click to copy waypoint.\nRight click to dismiss.";

            _icon = icon;

            this.Opacity          = 0f;
            this.Size             = new Point(NOTIFICATION_WIDTH, NOTIFICATION_HEIGHT);
            this.Location         = new Point(180, 60 + (NOTIFICATION_HEIGHT + 15) * _visibleNotifications);
            this.BasicTooltipText = TOOLTIP_TEXT;

            string wrappedTitle = DrawUtil.WrapText(Content.DefaultFont14, title, this.Width - NOTIFICATION_HEIGHT - 20 - 32);

            var titleLbl = new Label()
            {
                Parent           = this,
                Location         = new Point(NOTIFICATION_HEIGHT + 10, 5),
                Size             = new Point(this.Width - NOTIFICATION_HEIGHT - 10 - 32, this.Height / 2),
                Font             = Content.DefaultFont14,
                BasicTooltipText = TOOLTIP_TEXT,
                Text             = wrappedTitle,
            };

            string wrapped = DrawUtil.WrapText(Content.DefaultFont14, message, this.Width - NOTIFICATION_HEIGHT - 20 - 32);

            var messageLbl = new Label()
            {
                Parent           = this,
                Location         = new Point(NOTIFICATION_HEIGHT + 10, this.Height / 2),
                Size             = new Point(this.Width - NOTIFICATION_HEIGHT - 10 - 32, this.Height / 2),
                BasicTooltipText = TOOLTIP_TEXT,
                Text             = wrapped,
            };

            _visibleNotifications++;

            this.RightMouseButtonReleased += delegate { this.Dispose(); };
            this.LeftMouseButtonReleased  += delegate {
                ClipboardUtil.WindowsClipboardService.SetTextAsync(waypoint)
                .ContinueWith((clipboardResult) => {
                    if (clipboardResult.IsFaulted)
                    {
                        ScreenNotification.ShowNotification("Failed to copy waypoint to clipboard. Try again.", ScreenNotification.NotificationType.Red, duration: 2);
                    }
                    else
                    {
                        ScreenNotification.ShowNotification("Copied waypoint to clipboard!", duration: 2);
                    }
                });

                this.Dispose();
            };
        }
        /// <summary>
        /// Allows you to perform an action once your module has finished loading (once
        /// <see cref="LoadAsync"/> has completed).  You must call "base.OnModuleLoaded(e)" at the
        /// end for the <see cref="Module.ModuleLoaded"/> event to fire and for
        /// <see cref="Module.Loaded" /> to update correctly.
        /// </summary>
        protected override void OnModuleLoaded(EventArgs e)
        {
            // Add a mug icon in the top left next to the other icons
            _exampleIcon = new CornerIcon()
            {
                Icon             = _mugTexture,
                BasicTooltipText = $"{this.Name} [{this.Namespace}]",
                Parent           = GameService.Graphics.SpriteScreen
            };

            // Show a notification in the middle of the screen when the icon is clicked
            _exampleIcon.Click += delegate(object sender, MouseEventArgs args) {
                ScreenNotification.ShowNotification("Hello from Blish HUD!");
            };

            // Add a right click menu to the icon that shows each Revenant legend (pulled from the API)
            _dungeonContextMenuStrip = new ContextMenuStrip();

            foreach (var dungeon in _dungeons)
            {
                var dungeonItem = _dungeonContextMenuStrip.AddMenuItem(dungeon.Id);

                var dungeonMenu = new ContextMenuStrip();

                foreach (var path in dungeon.Paths)
                {
                    dungeonMenu.AddMenuItem($"{path.Id} ({path.Type})");
                }

                dungeonItem.Submenu = dungeonMenu;
            }

            _exampleIcon.Menu = _dungeonContextMenuStrip;

            base.OnModuleLoaded(e);
        }
        private Panel BuildSettingPanel(Rectangle panelBounds)
        {
            var etPanel = new Panel()
            {
                CanScroll = false,
                Size      = panelBounds.Size
            };

            var ddSortMethod = new Dropdown()
            {
                Location = new Point(etPanel.Right - 150 - Dropdown.Standard.ControlOffset.X, Dropdown.Standard.ControlOffset.Y),
                Width    = 150,
                Parent   = etPanel,
            };

            int topOffset = ddSortMethod.Bottom + Panel.MenuStandard.ControlOffset.Y;

            var menuSection = new Panel {
                Title      = "Event Categories",
                ShowBorder = true,
                Size       = Panel.MenuStandard.Size - new Point(0, topOffset + Panel.MenuStandard.ControlOffset.Y),
                Location   = new Point(Panel.MenuStandard.PanelOffset.X, topOffset),
                Parent     = etPanel
            };

            var eventPanel = new FlowPanel()
            {
                FlowDirection  = ControlFlowDirection.LeftToRight,
                ControlPadding = new Vector2(8, 8),
                Location       = new Point(menuSection.Right + Panel.MenuStandard.ControlOffset.X, menuSection.Top),
                Size           = new Point(ddSortMethod.Right - menuSection.Right - Control.ControlStandard.ControlOffset.X, menuSection.Height),
                CanScroll      = true,
                Parent         = etPanel
            };

            GameService.Overlay.QueueMainThreadUpdate((gameTime) => {
                var searchBox = new TextBox()
                {
                    PlaceholderText = "Event Search",
                    Width           = menuSection.Width,
                    Location        = new Point(ddSortMethod.Top, menuSection.Left),
                    Parent          = etPanel
                };

                searchBox.TextChanged += delegate(object sender, EventArgs args) {
                    eventPanel.FilterChildren <DetailsButton>(db => db.Text.ToLower().Contains(searchBox.Text.ToLower()));
                };
            });

            foreach (var meta in Meta.Events)
            {
                var setting = _watchCollection.DefineSetting("watchEvent:" + meta.Name, true);

                meta.IsWatched = setting.Value;

                var es2 = new DetailsButton {
                    Parent           = eventPanel,
                    BasicTooltipText = meta.Category,
                    Text             = meta.Name,
                    IconSize         = DetailsIconSize.Small,
                    ShowVignette     = false,
                    HighlightType    = DetailsHighlightType.LightHighlight,
                    ShowToggleButton = true
                };

                if (meta.Texture.HasTexture)
                {
                    es2.Icon = meta.Texture;
                }

                var nextTimeLabel = new Label()
                {
                    Size                = new Point(65, es2.ContentRegion.Height),
                    Text                = meta.NextTime.ToShortTimeString(),
                    BasicTooltipText    = GetTimeDetails(meta),
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment   = VerticalAlignment.Middle,
                    Parent              = es2,
                };

                Adhesive.Binding.CreateOneWayBinding(() => nextTimeLabel.Height, () => es2.ContentRegion, (rectangle => rectangle.Height), true);

                if (!string.IsNullOrEmpty(meta.Wiki))
                {
                    var glowWikiBttn = new GlowButton {
                        Icon             = GameService.Content.GetTexture("102530"),
                        ActiveIcon       = GameService.Content.GetTexture("glow-wiki"),
                        BasicTooltipText = "Read about this event on the wiki.",
                        Parent           = es2,
                        GlowColor        = Color.White * 0.1f
                    };

                    glowWikiBttn.Click += delegate {
                        if (UrlIsValid(meta.Wiki))
                        {
                            Process.Start(meta.Wiki);
                        }
                    };
                }

                if (!string.IsNullOrEmpty(meta.Waypoint))
                {
                    var glowWaypointBttn = new GlowButton {
                        Icon             = GameService.Content.GetTexture("waypoint"),
                        ActiveIcon       = GameService.Content.GetTexture("glow-waypoint"),
                        BasicTooltipText = $"Nearby waypoint: {meta.Waypoint}",
                        Parent           = es2,
                        GlowColor        = Color.White * 0.1f
                    };

                    glowWaypointBttn.Click += delegate {
                        System.Windows.Forms.Clipboard.SetText(meta.Waypoint);

                        ScreenNotification.ShowNotification("Waypoint copied to clipboard.");
                    };
                }

                var toggleFollowBttn = new GlowButton()
                {
                    Icon             = _textureWatch,
                    ActiveIcon       = _textureWatchActive,
                    BasicTooltipText = "Click to toggle tracking for this event.",
                    ToggleGlow       = true,
                    Checked          = meta.IsWatched,
                    Parent           = es2,
                };

                toggleFollowBttn.Click += delegate {
                    meta.IsWatched = toggleFollowBttn.Checked;
                    setting.Value  = toggleFollowBttn.Checked;
                };

                meta.OnNextRunTimeChanged += delegate {
                    UpdateSort(ddSortMethod, EventArgs.Empty);

                    nextTimeLabel.Text             = meta.NextTime.ToShortTimeString();
                    nextTimeLabel.BasicTooltipText = GetTimeDetails(meta);
                };

                _displayedEvents.Add(es2);
            }

            // Add menu items for each category (and built-in categories)
            var eventCategories = new Menu {
                Size           = menuSection.ContentRegion.Size,
                MenuItemHeight = 40,
                Parent         = menuSection,
                CanSelect      = true
            };

            List <IGrouping <string, Meta> > submetas = Meta.Events.GroupBy(e => e.Category).ToList();

            var evAll = eventCategories.AddMenuItem(EC_ALLEVENTS);

            evAll.Select();
            evAll.Click += delegate {
                eventPanel.FilterChildren <DetailsButton>(db => true);
            };

            foreach (IGrouping <string, Meta> e in submetas)
            {
                var ev = eventCategories.AddMenuItem(e.Key);
                ev.Click += delegate {
                    eventPanel.FilterChildren <DetailsButton>(db => string.Equals(db.BasicTooltipText, e.Key));
                };
            }

            // TODO: Hidden events/timers to be added later
            //eventCategories.AddMenuItem(EC_HIDDEN);

            // Add dropdown for sorting events
            ddSortMethod.Items.Add(DD_ALPHABETICAL);
            ddSortMethod.Items.Add(DD_NEXTUP);

            ddSortMethod.ValueChanged += delegate(object sender, ValueChangedEventArgs args) {
                switch (args.CurrentValue)
                {
                case DD_ALPHABETICAL:
                    eventPanel.SortChildren <DetailsButton>((db1, db2) => string.Compare(db1.Text, db2.Text, StringComparison.CurrentCultureIgnoreCase));
                    break;

                case DD_NEXTUP:
                    break;
                }
            };

            ddSortMethod.SelectedItem = DD_NEXTUP;
            //UpdateSort(ddSortMethod, EventArgs.Empty);

            return(etPanel);
        }
        private void AddThumbnail(string filePath)
        {
            if (modulePanel == null || displayedThumbnails.ContainsKey(filePath))
            {
                return;
            }


            var texture = GetThumbnail(filePath);

            if (texture == null)
            {
                return;
            }

            var thumbnail = new Panel
            {
                Parent           = thumbnailFlowPanel,
                Size             = new Point(_thumbnailSize.X + 6, _thumbnailSize.Y + 6),
                BackgroundColor  = Color.Black,
                BasicTooltipText = filePath
            };

            var tImage = new Blish_HUD.Controls.Image
            {
                Parent   = thumbnail,
                Location = new Point(3, 3),
                Size     = _thumbnailSize,
                Texture  = texture,
                Opacity  = 0.8f
            };
            var inspectButton = new Blish_HUD.Controls.Image
            {
                Parent   = thumbnail,
                Texture  = _inspectIcon,
                Size     = new Point(64, 64),
                Location = new Point(thumbnail.Width / 2 - 32, thumbnail.Height / 2 - 32),
                Opacity  = 0.0f
            };
            var deleteBackgroundTint = new Panel
            {
                Parent          = thumbnail,
                Size            = thumbnail.Size,
                BackgroundColor = Color.Black,
                Opacity         = 0.0f
            };
            var deleteLabel = new Label
            {
                Parent              = thumbnail,
                Size                = thumbnail.Size,
                TextColor           = Color.White,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment   = VerticalAlignment.Middle,
                Font                = GameService.Content.GetFont(ContentService.FontFace.Menomonia, ContentService.FontSize.Size24,
                                                                  ContentService.FontStyle.Regular),
                Text             = FileDeletionPrompt,
                BasicTooltipText = ZoomInThumbnailTooltipText,
                StrokeText       = true,
                ShowShadow       = true,
                Opacity          = 0.0f
            };
            var favoriteMarker = new Blish_HUD.Controls.Image
            {
                Parent           = thumbnail,
                Location         = new Point(thumbnail.Size.X - 30 - PanelMargin, PanelMargin),
                Size             = new Point(30, 30),
                BasicTooltipText = favorites.Value.Contains(filePath) ? UnfavoriteMarkerTooltip : FavoriteMarkerTooltip,
                Texture          = favorites.Value.Contains(filePath) ? _completeHeartIcon : _incompleteHeartIcon,
                Opacity          = 0.5f
            };

            favoriteMarker.Click += delegate
            {
                var currentFilePath = thumbnail.BasicTooltipText;
                if (favorites.Value.Contains(currentFilePath))
                {
                    var copy = new List <string>(favorites.Value);
                    copy.Remove(currentFilePath);
                    favorites.Value                 = copy;
                    favoriteMarker.Texture          = _incompleteHeartIcon;
                    favoriteMarker.BasicTooltipText = FavoriteMarkerTooltip;
                }
                else
                {
                    var copy = new List <string>(favorites.Value)
                    {
                        currentFilePath
                    };
                    favorites.Value                 = copy;
                    favoriteMarker.Texture          = _completeHeartIcon;
                    favoriteMarker.BasicTooltipText = UnfavoriteMarkerTooltip;
                }

                SortThumbnails();
            };
            favoriteMarker.MouseEntered += delegate
            {
                GameService.Animation.Tweener.Tween(favoriteMarker, new { Opacity = 1.0f }, 0.2f);
            };
            favoriteMarker.MouseLeft += delegate
            {
                GameService.Animation.Tweener.Tween(favoriteMarker, new { Opacity = 0.5f }, 0.2f);
                favoriteMarker.Location = new Point(thumbnail.Size.X - 30 - PanelMargin, PanelMargin);
                favoriteMarker.Size     = new Point(30, 30);
            };
            favoriteMarker.LeftMouseButtonPressed += delegate
            {
                favoriteMarker.Width   -= 2;
                favoriteMarker.Height  -= 2;
                favoriteMarker.Location = new Point(favoriteMarker.Location.X + 2, favoriteMarker.Location.Y + 2);
            };
            favoriteMarker.LeftMouseButtonReleased += delegate
            {
                favoriteMarker.Location = new Point(thumbnail.Size.X - 30 - PanelMargin, PanelMargin);
                favoriteMarker.Size     = new Point(30, 30);
            };
            var fileNameTextBox = new TextBox
            {
                Parent           = thumbnail,
                Size             = new Point(thumbnail.Width / 2 + 20, 30),
                Location         = new Point(PanelMargin, thumbnail.Height - 30 - PanelMargin),
                PlaceholderText  = Path.GetFileNameWithoutExtension(filePath),
                MaxLength        = MaxFileNameLength,
                BackgroundColor  = Color.DarkBlue,
                BasicTooltipText = Path.GetFileNameWithoutExtension(filePath),
                Text             = "",
                Opacity          = 0.8f
            };
            var fileNameLengthLabel = new Label
            {
                Parent              = thumbnail,
                Size                = fileNameTextBox.Size,
                Location            = new Point(fileNameTextBox.Location.X, fileNameTextBox.Location.Y - fileNameTextBox.Height),
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment   = VerticalAlignment.Bottom,
                Text                = "0/" + MaxFileNameLength,
                Font                = GameService.Content.GetFont(ContentService.FontFace.Menomonia, ContentService.FontSize.Size11,
                                                                  ContentService.FontStyle.Regular),
                TextColor  = Color.Yellow,
                StrokeText = true,
                Visible    = false
            };

            fileNameTextBox.TextChanged += delegate
            {
                fileNameLengthLabel.Text = fileNameTextBox.Text.Length + "/" + MaxFileNameLength;
            };
            fileNameTextBox.MouseEntered += delegate
            {
                GameService.Animation.Tweener.Tween(fileNameTextBox, new { Opacity = 1.0f }, 0.2f);
            };
            fileNameTextBox.MouseLeft += delegate
            {
                if (!fileNameTextBox.Focused)
                {
                    GameService.Animation.Tweener.Tween(fileNameTextBox, new { Opacity = 0.8f }, 0.2f);
                }
            };
            var enterPressed = false;

            fileNameTextBox.EnterPressed += delegate
            {
                enterPressed = true;
                var oldFilePath = thumbnail.BasicTooltipText;
                var newFileName = fileNameTextBox.Text.Trim();
                if (newFileName.Equals(string.Empty))
                {
                    ScreenNotification.ShowNotification(ReasonEmptyFileName, ScreenNotification.NotificationType.Error);
                }
                else if (_invalidFileNameCharacters.Any(x => newFileName.Contains(x)))
                {
                    ScreenNotification.ShowNotification(ReasonInvalidFileName
                                                        + "\n" + PromptChangeFileName
                                                        + "\n" + InvalidFileNameCharactersHint + "\n"
                                                        + string.Join(" ", _invalidFileNameCharacters),
                                                        ScreenNotification.NotificationType.Error, null, 10);
                }
                else
                {
                    var newPath = Path.Combine(Directory.GetParent(Path.GetFullPath(oldFilePath)).FullName,
                                               newFileName + Path.GetExtension(oldFilePath));
                    if (newPath.Equals(oldFilePath, StringComparison.InvariantCultureIgnoreCase))
                    {
                    }
                    else if (File.Exists(newPath))
                    {
                        ScreenNotification.ShowNotification(
                            FailedToRenameFileNotification + " " + ReasonDublicateFileName,
                            ScreenNotification.NotificationType.Error);
                    }
                    else if (!File.Exists(oldFilePath))
                    {
                        ScreenNotification.ShowNotification(
                            FailedToRenameFileNotification + " " + ReasonFileNotExisting,
                            ScreenNotification.NotificationType.Error);
                        thumbnail?.Dispose();
                    }
                    else
                    {
                        var renameCompleted = false;
                        var renameTimeout   = DateTime.Now.AddMilliseconds(FileTimeOutMilliseconds);
                        while (!renameCompleted)
                        {
                            try
                            {
                                File.Move(oldFilePath, newPath);
                                renameCompleted = true;
                            }
                            catch (IOException e)
                            {
                                if (DateTime.Now < renameTimeout)
                                {
                                    continue;
                                }
                                Logger.Error(e.Message + e.StackTrace);
                            }
                        }
                    }
                }

                if (!fileNameTextBox.MouseOver)
                {
                    GameService.Animation.Tweener.Tween(fileNameTextBox, new { Opacity = 0.6f }, 0.2f);
                }
                fileNameTextBox.Text = "";
                enterPressed         = false;
            };
            fileNameTextBox.InputFocusChanged += delegate
            {
                fileNameLengthLabel.Visible        = fileNameTextBox.Focused;
                fileNameLengthLabel.Text           = "0/" + MaxFileNameLength;
                fileNameTextBox.InputFocusChanged += delegate
                {
                    Task.Run(async delegate
                    {
                        //InputFocusChanged needs to wait to not interfere with EnterPressed.
                        await Task.Delay(1).ContinueWith(delegate
                        {
                            if (!enterPressed)
                            {
                                fileNameTextBox.Text = "";
                            }
                        });
                    });
                };
            };

            deleteLabel.MouseEntered += delegate
            {
                GameService.Animation.Tweener.Tween(inspectButton, new { Opacity = 1.0f }, 0.2f);
                GameService.Animation.Tweener.Tween(tImage, new { Opacity = 1.0f }, 0.45f);
            };
            deleteLabel.MouseLeft += delegate
            {
                GameService.Animation.Tweener.Tween(inspectButton, new { Opacity = 0.0f }, 0.2f);
                GameService.Animation.Tweener.Tween(tImage, new { Opacity = 0.8f }, 0.45f);
            };
            Panel inspectPanel = null;

            deleteLabel.Click += delegate
            {
                inspectPanel?.Dispose();
                inspectPanel = CreateInspectionPanel(filePath);
            };
            var deleteButton = new Blish_HUD.Controls.Image
            {
                Parent   = thumbnail,
                Texture  = _trashcanClosedIcon64,
                Size     = new Point(45, 45),
                Location = new Point(thumbnail.Width - 45 - PanelMargin, thumbnail.Height - 45 - PanelMargin),
                Opacity  = 0.5f
            };

            deleteButton.MouseEntered += delegate
            {
                deleteButton.Texture = _trashcanOpenIcon64;
                GameService.Animation.Tweener.Tween(deleteButton, new { Opacity = 1.0f }, 0.2f);
                GameService.Animation.Tweener.Tween(deleteLabel, new { Opacity = 1.0f }, 0.2f);
                GameService.Animation.Tweener.Tween(deleteBackgroundTint, new { Opacity = 0.6f }, 0.35f);
                GameService.Animation.Tweener.Tween(fileNameTextBox, new { Opacity = 0.0f }, 0.2f);
            };
            deleteButton.MouseLeft += delegate
            {
                deleteButton.Texture = _trashcanClosedIcon64;
                GameService.Animation.Tweener.Tween(deleteButton, new { Opacity = 0.8f }, 0.2f);
                GameService.Animation.Tweener.Tween(deleteLabel, new { Opacity = 0.0f }, 0.2f);
                GameService.Animation.Tweener.Tween(deleteBackgroundTint, new { Opacity = 0.0f }, 0.2f);
                GameService.Animation.Tweener.Tween(fileNameTextBox, new { Opacity = 0.8f }, 0.2f);
            };
            deleteButton.LeftMouseButtonReleased += delegate
            {
                var oldFilePath = thumbnail.BasicTooltipText;
                if (!File.Exists(oldFilePath))
                {
                    thumbnail?.Dispose();
                }
                else
                {
                    var deletionCompleted = false;
                    var deletionTimeout   = DateTime.Now.AddMilliseconds(FileTimeOutMilliseconds);
                    while (!deletionCompleted)
                    {
                        try
                        {
                            fileNameTextBox.Text = "";
                            File.Delete(oldFilePath);
                            deletionCompleted = true;
                        }
                        catch (IOException e)
                        {
                            if (DateTime.Now < deletionTimeout)
                            {
                                continue;
                            }
                            Logger.Error(e.Message + e.StackTrace);
                            ScreenNotification.ShowNotification(FailedToDeleteFileNotification + " " + ReasonFileInUse,
                                                                ScreenNotification.NotificationType.Error);
                        }
                    }
                }
            };
            thumbnail.Disposed += delegate
            {
                var oldFilePath = thumbnail.BasicTooltipText;
                if (displayedThumbnails.ContainsKey(oldFilePath))
                {
                    displayedThumbnails.Remove(oldFilePath);
                }

                if (!favorites.Value.Contains(oldFilePath))
                {
                    return;
                }
                var copy = new List <string>(favorites.Value);
                copy.Remove(oldFilePath);
                favorites.Value = copy;
            };
            try
            {
                displayedThumbnails.Add(filePath, thumbnail);
                SortThumbnails();
            }
            catch (ArgumentException e)
            {
                Logger.Error(e.Message + e.StackTrace);
                thumbnail.Dispose();
            }
        }