/// <summary>
        /// Called when the selection changes in the list box. We need to prevent
        /// the user from selecting disabled plugins and warn him/her about
        /// incompatible plugins.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event arguments.</param>
        private void PipelinePluginsLst_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Watch for stack overflows.
            if (!reselecting)
            {
                reselecting = true;
                try {
                    PipelinePluginsLst.BeginUpdate();
                    try {
                        // Deselect any non-importable plugins and warn about any
                        // non-compatible plugins.
                        for (int i = 0; i < PipelinePluginsLst.Items.Count; ++i)
                        {
                            if (!((PluginToImportDisplayInfo)PipelinePluginsLst.Items[i]).Importable)
                            {
                                // If this is the first time user does this, warn him/her.
                                if (!warnedAboutGlobalOverwrites && PipelinePluginsLst.SelectedIndices.Contains(i))
                                {
                                    MessageBox.Show(this, Resources.ImportPipelinePluginsForm_CantOverwriteGlobalMsg,
                                                    Resources.ImportPipelinePluginsForm_MsgTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
                                    warnedAboutGlobalOverwrites = true;
                                }
                                PipelinePluginsLst.SetSelected(i, false);
                            }
                            if (!((PluginToImportDisplayInfo)PipelinePluginsLst.Items[i]).Compatible)
                            {
                                // If this is the first time user does this, warn him/her.
                                if (!warnedAboutIncompatiblePlugins && PipelinePluginsLst.SelectedIndices.Contains(i))
                                {
                                    MessageBox.Show(this, Resources.ImportPipelinePluginsForm_IncompatiblePluginsMsg,
                                                    Resources.ImportPipelinePluginsForm_MsgTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
                                    warnedAboutIncompatiblePlugins = true;
                                }
                            }
                        }
                    } finally {
                        PipelinePluginsLst.EndUpdate();
                    }
                } finally {
                    reselecting = false;
                }
            }

            // Update buttons to match the new selection.
            UpdateButtons();
        }
        /// <summary>
        /// Shows the form as a modal dialog, asking the user which plugins among
        /// the given list he/she wants to import.
        /// </summary>
        /// <param name="owner">Owner window of the dialog. Can be <c>null</c>.</param>
        /// <param name="pluginCollection">List of plugins available for importing.
        /// Upon exit, if the method returns <c>true</c>, the list will be modified
        /// to only contain those plugins selected by the user.</param>
        /// <param name="pluginOverwrites">Container of information about plugins
        /// overwriting existing ones. Upon exit, if the method returns <c>true</c>,
        /// the list will be modified to only contain plugins that are also in
        /// <paramref name="pluginCollection"/>.</param>
        /// <returns><c>true</c> if the user pressed OK to import selected
        /// plugins.</returns>
        public bool SelectPlugins(IWin32Window owner, ref PipelinePluginCollection pluginCollection,
                                  ref ImportedPipelinePluginOverwrites pluginOverwrites)
        {
            Debug.Assert(pluginCollection != null);
            Debug.Assert(pluginOverwrites != null);

            PipelinePluginsLst.BeginUpdate();
            try {
                // Populate the list with given plugins.
                foreach (PipelinePluginInfo pluginInfo in pluginCollection.Plugins)
                {
                    PipelinePluginsLst.Items.Add(new PluginToImportDisplayInfo {
                        PluginInfo = pluginInfo,
                        Importable = true,
                    });
                }

                // Disable any plugin that would overwrite a global one set by the administrator.
                for (int i = 0; i < PipelinePluginsLst.Items.Count; ++i)
                {
                    PluginToImportDisplayInfo newPlugin = (PluginToImportDisplayInfo)PipelinePluginsLst.Items[i];
                    ImportedPipelinePluginOverwrites.OverwriteInfo overwriteInfo;
                    if (pluginOverwrites.OverwriteInfos.TryGetValue(newPlugin.PluginInfo, out overwriteInfo) && overwriteInfo.OldInfo.Global)
                    {
                        newPlugin.Importable = false;
                    }
                }

                // Default is to want to select them all importable, compatible plugins.
                reselecting = true;
                try {
                    for (int i = 0; i < PipelinePluginsLst.Items.Count; ++i)
                    {
                        PluginToImportDisplayInfo newPlugin = (PluginToImportDisplayInfo)PipelinePluginsLst.Items[i];
                        if (newPlugin.Importable && newPlugin.Compatible)
                        {
                            PipelinePluginsLst.SetSelected(i, true);
                        }
                    }
                } finally {
                    reselecting = false;
                }

                // Update buttons to match the initial selection state.
                UpdateButtons();
            } finally {
                PipelinePluginsLst.EndUpdate();
            }

            // Show dialog to allow user to select plugins.
            bool res = ShowDialog(owner) == DialogResult.OK;

            if (res)
            {
                // Rebuild list of plugins in the collection.
                pluginCollection.Plugins.Clear();
                foreach (var item in PipelinePluginsLst.SelectedItems)
                {
                    pluginCollection.Plugins.Add(((PluginToImportDisplayInfo)item).PluginInfo);
                }

                // Also rebuild the list of overwrites to only include those we included in the collection.
                ImportedPipelinePluginOverwrites newOverwrites = new ImportedPipelinePluginOverwrites();
                foreach (var pluginInfo in pluginCollection.Plugins)
                {
                    ImportedPipelinePluginOverwrites.OverwriteInfo overwriteInfo;
                    if (pluginOverwrites.OverwriteInfos.TryGetValue(pluginInfo, out overwriteInfo))
                    {
                        newOverwrites.OverwriteInfos.Add(pluginInfo, overwriteInfo);
                    }
                }
                pluginOverwrites = newOverwrites;
            }
            return(res);
        }