internal Panel CreateInspectionPanel(string filePath)
        {
            var texture = GetScreenshot(filePath);

            if (texture == null)
            {
                return(null);
            }
            var inspectPanel = new Panel
            {
                Parent   = GameService.Graphics.SpriteScreen,
                Size     = new Point(texture.Width + 10, texture.Height + 10),
                Location = new Point(GameService.Graphics.SpriteScreen.Width / 2 - texture.Width / 2,
                                     GameService.Graphics.SpriteScreen.Height / 2 - texture.Height / 2),
                BackgroundColor = Color.Black,
                ZIndex          = 9999,
                ShowTint        = true,
                Opacity         = 0.0f
            };
            var inspImage = new Blish_HUD.Controls.Image
            {
                Parent   = inspectPanel,
                Location = new Point(5, 5),
                Size     = new Point(texture.Width, texture.Height),
                Texture  = texture
            };

            GameService.Animation.Tweener.Tween(inspectPanel, new { Opacity = 1.0f }, 0.35f);
            inspImage.Click += delegate
            {
                GameService.Animation.Tweener.Tween(inspectPanel, new { Opacity = 0.0f }, 0.15f)
                .OnComplete(() => inspectPanel?.Dispose());
            };
            return(inspectPanel);
        }
        private Panel BuildModulePanel(WindowBase wnd)
        {
            var homePanel = new Panel
            {
                Parent = wnd,
                Size   = new Point(WindowWidth, WindowHeight)
            };

            thumbnailFlowPanel = new FlowPanel
            {
                Parent         = homePanel,
                Size           = new Point(homePanel.ContentRegion.Size.X - 70, homePanel.ContentRegion.Size.Y - 130),
                Location       = new Point(35, 50),
                FlowDirection  = ControlFlowDirection.LeftToRight,
                ControlPadding = new Vector2(5, 5),
                CanCollapse    = false,
                CanScroll      = true,
                Collapsed      = false,
                ShowTint       = true,
                ShowBorder     = true
            };
            var searchBox = new TextBox
            {
                Parent          = homePanel,
                Location        = new Point(thumbnailFlowPanel.Location.X, thumbnailFlowPanel.Location.Y - 40),
                Size            = new Point(200, 40),
                PlaceholderText = SearchBoxPlaceHolder
            };
            var deleteSearchBoxContentButton = new Blish_HUD.Controls.Image
            {
                Parent   = homePanel,
                Location = new Point(searchBox.Right - 20 - PanelMargin, searchBox.Location.Y + PanelMargin),
                Size     = new Point(20, 20),
                Texture  = _deleteSearchBoxContentIcon,
                Visible  = false
            };

            deleteSearchBoxContentButton.Click += delegate
            {
                searchBox.Text = "";
                deleteSearchBoxContentButton.Hide();
            };
            deleteSearchBoxContentButton.MouseEntered += delegate
            {
                if (deleteSearchBoxContentButton.Visible)
                {
                    GameService.Animation.Tweener.Tween(deleteSearchBoxContentButton, new { Opacity = 1.0f }, 0.2f);
                }
            };
            deleteSearchBoxContentButton.MouseLeft += delegate
            {
                if (deleteSearchBoxContentButton.Visible)
                {
                    GameService.Animation.Tweener.Tween(deleteSearchBoxContentButton, new { Opacity = 0.8f }, 0.2f);
                }

                deleteSearchBoxContentButton.Size     = new Point(20, 20);
                deleteSearchBoxContentButton.Location = new Point(searchBox.Right - 20 - PanelMargin,
                                                                  searchBox.Location.Y + PanelMargin);
            };
            deleteSearchBoxContentButton.LeftMouseButtonPressed += delegate
            {
                deleteSearchBoxContentButton.Width   -= 2;
                deleteSearchBoxContentButton.Height  -= 2;
                deleteSearchBoxContentButton.Location = new Point(deleteSearchBoxContentButton.Location.X + 2,
                                                                  deleteSearchBoxContentButton.Location.Y + 2);
            };
            searchBox.InputFocusChanged += delegate { SortThumbnails(); };
            searchBox.TextChanged       += delegate
            {
                deleteSearchBoxContentButton.Visible = !searchBox.Text.Equals(string.Empty);
                thumbnailFlowPanel.SortChildren(delegate(Panel x, Panel y)
                {
                    var fileNameX  = Path.GetFileNameWithoutExtension(x.BasicTooltipText);
                    var fileNameY  = Path.GetFileNameWithoutExtension(y.BasicTooltipText);
                    x.Visible      = fileNameX.Contains(searchBox.Text);
                    y.Visible      = fileNameY.Contains(searchBox.Text);
                    var favMarkerX = (Blish_HUD.Controls.Image)x.Children.FirstOrDefault(m =>
                                                                                         m.BasicTooltipText != null && (m.BasicTooltipText.Equals(FavoriteMarkerTooltip) ||
                                                                                                                        m.BasicTooltipText.Equals(UnfavoriteMarkerTooltip)));
                    var favMarkerY = (Blish_HUD.Controls.Image)y.Children.FirstOrDefault(m =>
                                                                                         m.BasicTooltipText != null && (m.BasicTooltipText.Equals(FavoriteMarkerTooltip) ||
                                                                                                                        m.BasicTooltipText.Equals(UnfavoriteMarkerTooltip)));
                    if (favMarkerX != null && favMarkerY != null)
                    {
                        var favorite = string.Compare(favMarkerY.BasicTooltipText, favMarkerX.BasicTooltipText,
                                                      StringComparison.InvariantCultureIgnoreCase);
                        if (favorite != 0)
                        {
                            return(favorite);
                        }
                    }

                    return(string.Compare(fileNameX, fileNameY, StringComparison.InvariantCultureIgnoreCase));
                });
            };
            homePanel.Hidden += ToggleFileSystemWatchers;
            homePanel.Hidden += ToggleFileSystemWatchers;
            homePanel.Shown  += LoadImages;
            homePanel.Hidden += DisposeDisplayedThumbnails;
            return(homePanel);
        }
        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();
            }
        }