void OnBrowseImagePathClick(object sender, EventArgs e)
        {
            //select file with dialog
            OpenFileDialog ofd = new OpenFileDialog
            {
                Filter          = "PNG Files|*.png",
                CheckFileExists = true,
                Multiselect     = false
            };

            //show dialog
            if (ofd.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            //get path
            txtImagePath.Text = ofd.FileName;

            #region Image URL prediction
            //dont try to predict if there is no manager config
            if (CurrentManagerConfig == null)
            {
                return;
            }

            //exit if already have url
            if (!string.IsNullOrWhiteSpace(txtImageUrl.Text))
            {
                if (MessageBox.Show(this, "The image has already a URL! Do you want to override it with a prediction based on the current file path?", "Replace Image URL?", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    //user said no
                    return;
                }
            }

            //make relative path
            string collectionRoot = Path.GetDirectoryName(EditingParentCollection.LoadedFrom);
            string relPath        = LibUtil.MakeRelativePath(collectionRoot, ofd.FileName);

            //try to predict url
            string imgUrl = CurrentManagerConfig.PredictImageUrl(relPath);

            //check built url is valid
            if (string.IsNullOrWhiteSpace(imgUrl) || !Uri.IsWellFormedUriString(imgUrl, UriKind.Absolute))
            {
                return;
            }

            //set textbox
            txtImageUrl.Text = imgUrl;
            #endregion
        }
        /// <summary>
        /// Check if all required fields are filled. Also highlights the fields that need to be filled
        /// </summary>
        /// <remarks>Required are: URL, PATH, Name, Creator Name, Contributor Name</remarks>
        /// <returns>are all required fields filled?</returns>
        bool CheckRequiredFields()
        {
            //setup shared variables
            bool  anyMissing = false;
            Color bgOk       = SystemColors.Window;
            Color bgBd       = Color.Red;

            //image url
            if (string.IsNullOrWhiteSpace(txtImageUrl.Text))
            {
                anyMissing            = true;
                txtImageUrl.BackColor = bgBd;
            }
            else
            {
                txtImageUrl.BackColor = bgOk;
            }

            //image path is special because it also has to be possible to be made a relative path
            if (EditingParentCollection != null)
            {
                string collectionRoot = Path.GetDirectoryName(EditingParentCollection.LoadedFrom);
                if (string.IsNullOrWhiteSpace(txtImagePath.Text) || string.IsNullOrWhiteSpace(LibUtil.MakeRelativePath(collectionRoot, txtImagePath.Text)))
                {
                    anyMissing             = true;
                    txtImagePath.BackColor = bgBd;
                }
                else
                {
                    txtImagePath.BackColor = bgOk;
                }
            }

            //character name
            if (string.IsNullOrWhiteSpace(txtCharacterName.Text))
            {
                anyMissing = true;
                txtCharacterName.BackColor = bgBd;
            }
            else
            {
                txtCharacterName.BackColor = bgOk;
            }

            //contributor name
            if (string.IsNullOrWhiteSpace(txtImageContributor.Text))
            {
                anyMissing = true;
                txtImageContributor.BackColor = bgBd;
            }
            else
            {
                txtImageContributor.BackColor = bgOk;
            }

            //creator name
            if (string.IsNullOrWhiteSpace(txtImageCreator.Text))
            {
                anyMissing = true;
                txtImageCreator.BackColor = bgBd;
            }
            else
            {
                txtImageCreator.BackColor = bgOk;
            }

            return(!anyMissing);
        }