/// <summary>
        /// Saves settings to XML (on settings export)
        /// </summary>
        public override void SaveSettingsToXml(IVsSettingsWriter writer)
        {
            WriteBoolToXml(writer, "ShowFilterContext", SettingsObject.Instance.ShowContextColumn);
            WriteBoolToXml(writer, "UseReflectionInAsp", SettingsObject.Instance.UseReflectionInAsp);
            WriteIntToXml(writer, "MarkNotLocalizableStringsIndex", SettingsObject.Instance.MarkNotLocalizableStringsIndex);
            WriteIntToXml(writer, "NamespacePolicyIndex", SettingsObject.Instance.NamespacePolicyIndex);
            WriteIntToXml(writer, "BatchMoveSplitterDistance", SettingsObject.Instance.BatchMoveSplitterDistance);
            WriteIntToXml(writer, "SelectedKeyIndex", SettingsObject.Instance.SelectedKeyIndex);
            WriteBoolToXml(writer, "SelectedUseFullName", SettingsObject.Instance.SelectedUseFullName);

            if (SettingsObject.Instance.SelectedResourceFilePath != null)
            {
                writer.WriteSettingString("SelectedResourceFilePath", SettingsObject.Instance.SelectedResourceFilePath);
            }

            foreach (var pair in SettingsObject.Instance.CommonLocalizabilityCriteria)
            {
                LocalizationCommonCriterion crit = pair.Value;
                writer.WriteSettingString(crit.Name, crit.ToRegData());
            }

            WriteIntToXml(writer, "CustomCriteriaCount", SettingsObject.Instance.CustomLocalizabilityCriteria.Count);

            for (int i = 0; i < SettingsObject.Instance.CustomLocalizabilityCriteria.Count; i++)
            {
                int hr = writer.WriteSettingString("CustomCriteria" + i, SettingsObject.Instance.CustomLocalizabilityCriteria[i].ToRegData());
                if (hr != VSConstants.S_OK)
                {
                    writer.ReportError("CustomCriteria value cannot be written", (uint)__VSSETTINGSERRORTYPES.vsSettingsErrorTypeError);
                }
            }
        }
        /// <summary>
        /// Creates deep copy
        /// </summary>
        public override AbstractLocalizationCriterion DeepCopy()
        {
            LocalizationCommonCriterion crit = new LocalizationCommonCriterion();

            InternalDeepCopy(crit);
            crit.Predicate = Predicate;
            return(crit);
        }
        /// <summary>
        /// Populates the GUI with current settings data
        /// </summary>
        private void PopulateTable()
        {
            try {
                contextBox.Checked    = SettingsObject.Instance.ShowContextColumn;
                reflectionBox.Checked = SettingsObject.Instance.UseReflectionInAsp;

                foreach (var pair in SettingsObject.Instance.CommonLocalizabilityCriteria)
                {
                    LocalizationCommonCriterion crit = pair.Value;
                    DataGridViewRow             row  = commonCriteriaGrid.Rows[commonCriteriaRowMap[crit.Name]];

                    row.Cells[1].Value = actionColumn.Items[(int)crit.Action];
                    row.Cells[2].Value = crit.Weight;
                }

                // remove existing custom criteria
                for (int i = 0; i < customCriteriaTable.RowCount - 1; i++)
                {
                    customCriteriaTable.Controls.Remove(customCriteriaTable.GetControlFromPosition(0, i));
                }
                customCriteriaTable.SetRow(addCustomCriteriaButton, 0);
                customCriteriaTable.RowCount = 1;

                // add new custom criteria
                foreach (LocalizationCustomCriterion crit in SettingsObject.Instance.CustomLocalizabilityCriteria)
                {
                    AddCustomCriteriaButton_Click(null, null); // prepares the GUI

                    // fill the GUI with data
                    TableLayoutPanel t = (TableLayoutPanel)customCriteriaTable.GetControlFromPosition(0, customCriteriaTable.RowCount - 2);
                    t.Name = crit.Name;
                    ComboBox      targetBox    = (ComboBox)t.GetControlFromPosition(1, 0);
                    ComboBox      predicateBox = (ComboBox)t.GetControlFromPosition(2, 0);
                    TextBox       regexBox     = (TextBox)t.GetControlFromPosition(1, 1);
                    ComboBox      actionBox    = (ComboBox)t.GetControlFromPosition(1, 2);
                    NumericUpDown valueBox     = (NumericUpDown)t.GetControlFromPosition(2, 2);

                    targetBox.SelectedIndex    = (int)crit.Target;
                    predicateBox.SelectedIndex = (int)crit.Predicate;
                    actionBox.SelectedIndex    = (int)crit.Action;
                    regexBox.Text  = crit.Regex;
                    valueBox.Value = crit.Weight;
                }
            } catch (Exception ex) {
                VLOutputWindow.VisualLocalizerPane.WriteException(ex);
                VisualLocalizer.Library.Components.MessageBox.ShowException(ex);
            }
        }
        /// <summary>
        /// Saves settings to registry storage
        /// </summary>
        public override void SaveSettingsToStorage()
        {
            VisualLocalizerPackage package     = VisualLocalizerPackage.Instance;
            RegistryKey            rootKey     = package.UserRegistryRoot;
            RegistryKey            settingsKey = null;

            try {
                settingsKey = rootKey.CreateSubKey(REG_KEY);
                RegistryKey filterKey = settingsKey.CreateSubKey(FILTER_KEY);

                WriteBoolToRegKey(filterKey, "ShowFilterContext", SettingsObject.Instance.ShowContextColumn);
                WriteBoolToRegKey(filterKey, "UseReflectionInAsp", SettingsObject.Instance.UseReflectionInAsp);
                WriteIntToRegKey(filterKey, "NamespacePolicyIndex", SettingsObject.Instance.NamespacePolicyIndex);
                WriteIntToRegKey(filterKey, "MarkNotLocalizableStringsIndex", SettingsObject.Instance.MarkNotLocalizableStringsIndex);
                WriteIntToRegKey(filterKey, "BatchMoveSplitterDistance", SettingsObject.Instance.BatchMoveSplitterDistance);
                WriteIntToRegKey(filterKey, "SelectedKeyIndex", SettingsObject.Instance.SelectedKeyIndex);
                WriteBoolToRegKey(filterKey, "SelectedUseFullName", SettingsObject.Instance.SelectedUseFullName);

                if (SettingsObject.Instance.SelectedResourceFilePath != null)
                {
                    filterKey.SetValue("SelectedResourceFilePath", SettingsObject.Instance.SelectedResourceFilePath);
                }

                foreach (var pair in SettingsObject.Instance.CommonLocalizabilityCriteria)
                {
                    LocalizationCommonCriterion crit = pair.Value;
                    filterKey.SetValue(crit.Name, crit.ToRegData());
                }

                int count = ReadIntFromRegKey(filterKey, "CustomCriteriaCount");
                for (int i = 0; i < count; i++)
                {
                    filterKey.DeleteValue("CustomCriteria" + i, false);
                }
                for (int i = 0; i < SettingsObject.Instance.CustomLocalizabilityCriteria.Count; i++)
                {
                    filterKey.SetValue("CustomCriteria" + i, SettingsObject.Instance.CustomLocalizabilityCriteria[i].ToRegData());
                }
                WriteIntToRegKey(filterKey, "CustomCriteriaCount", SettingsObject.Instance.CustomLocalizabilityCriteria.Count);
            } finally {
                if (settingsKey != null)
                {
                    settingsKey.Close();
                }
            }
        }
        /// <summary>
        /// When "Apply" button of the settings dialog was hit; save the GUI state in the settings
        /// </summary>
        protected override void OnApply(PageApplyEventArgs e)
        {
            if (e.ApplyBehavior == ApplyKind.Apply)
            {
                try {
                    SettingsObject.Instance.IgnorePropertyChanges = true;

                    bool revalidate = SettingsObject.Instance.ShowContextColumn != contextBox.Checked;
                    SettingsObject.Instance.ShowContextColumn  = contextBox.Checked;
                    SettingsObject.Instance.UseReflectionInAsp = reflectionBox.Checked;

                    foreach (var pair in SettingsObject.Instance.CommonLocalizabilityCriteria)
                    {
                        LocalizationCommonCriterion crit = pair.Value;
                        DataGridViewRow             row  = commonCriteriaGrid.Rows[commonCriteriaRowMap[crit.Name]];

                        crit.Action = (LocalizationCriterionAction)actionColumn.Items.IndexOf(row.Cells[1].Value);

                        int    w   = 0;
                        object val = row.Cells[2].Value;
                        if (val == null || !int.TryParse(val.ToString(), out w) || w < -100 || w > 100)
                        {
                            throw new Exception("Error on '" + crit.Description + "' - invalid value '" + val + "'. Please enter an integer from -100 to 100.");
                        }

                        crit.Weight = w;
                    }

                    SettingsObject.Instance.CustomLocalizabilityCriteria.Clear();
                    for (int i = 0; i < customCriteriaTable.RowCount - 1; i++)
                    {
                        TableLayoutPanel t            = (TableLayoutPanel)customCriteriaTable.GetControlFromPosition(0, i);
                        ComboBox         targetBox    = (ComboBox)t.GetControlFromPosition(1, 0);
                        ComboBox         predicateBox = (ComboBox)t.GetControlFromPosition(2, 0);
                        TextBox          regexBox     = (TextBox)t.GetControlFromPosition(1, 1);
                        ComboBox         actionBox    = (ComboBox)t.GetControlFromPosition(1, 2);
                        NumericUpDown    valueBox     = (NumericUpDown)t.GetControlFromPosition(2, 2);

                        if (actionBox.SelectedIndex == -1)
                        {
                            throw new Exception("Error on custom rule no. " + (i + 1) + " - must select action.");
                        }
                        LocalizationCriterionAction action = (LocalizationCriterionAction)actionBox.SelectedIndex;

                        LocalizationCustomCriterion crit = new LocalizationCustomCriterion(action, (int)valueBox.Value);
                        if (!string.IsNullOrEmpty(t.Name))
                        {
                            crit.Name = t.Name;
                        }

                        if (predicateBox.SelectedIndex == -1)
                        {
                            throw new Exception("Error on custom rule no. " + (i + 1) + " - must select predicate.");
                        }
                        crit.Predicate = (LocalizationCriterionPredicate)predicateBox.SelectedIndex;

                        if (targetBox.SelectedIndex == -1)
                        {
                            throw new Exception("Error on custom rule no. " + (i + 1) + " - must select target.");
                        }
                        crit.Target = (LocalizationCriterionTarget)targetBox.SelectedIndex;

                        new Regex(regexBox.Text); // throws exception if regex is not valid
                        crit.Regex = regexBox.Text;

                        SettingsObject.Instance.CustomLocalizabilityCriteria.Add(crit);
                    }

                    if (revalidate)
                    {
                        SettingsObject.Instance.NotifyRevalidationRequested();
                    }
                } catch (Exception ex) {
                    VLOutputWindow.VisualLocalizerPane.WriteException(ex);
                    VisualLocalizer.Library.Components.MessageBox.ShowException(ex);
                    e.ApplyBehavior = ApplyKind.CancelNoNavigate;
                } finally {
                    SettingsObject.Instance.IgnorePropertyChanges = false;
                    SettingsObject.Instance.NotifyPropertyChanged(CHANGE_CATEGORY.FILTER);
                }
            }
        }
        /// <summary>
        /// Creates the GUI
        /// </summary>
        private void InitializeDialogPage()
        {
            try {
                tablePanel              = new TableLayoutPanel();
                tablePanel.Dock         = DockStyle.Fill;
                tablePanel.AutoScroll   = true;
                tablePanel.AutoSize     = true;
                tablePanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
                tablePanel.Padding      = new Padding(0, 0, 10, 0);

                tablePanel.RowCount = 2;
                tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
                tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
                tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));

                tablePanel.ColumnCount = 1;
                tablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));

                GroupBox generalBox = new GroupBox();
                generalBox.Text     = "General";
                generalBox.Dock     = DockStyle.Fill;
                generalBox.AutoSize = true;

                FlowLayoutPanel generalInnerPanel = new FlowLayoutPanel();
                generalInnerPanel.FlowDirection = FlowDirection.TopDown;
                generalInnerPanel.Dock          = DockStyle.Fill;
                generalInnerPanel.AutoSize      = true;

                contextBox          = new CheckBox();
                contextBox.Text     = "Show context column";
                contextBox.Margin   = new Padding(3, 3, 0, 0);
                contextBox.AutoSize = true;

                reflectionBox            = new CheckBox();
                reflectionBox.Text       = "Determine types of attributes in ASP .NET elements\n(potentially slow)";
                reflectionBox.CheckAlign = ContentAlignment.TopLeft;
                reflectionBox.Margin     = new Padding(3, 3, 0, 0);
                reflectionBox.AutoSize   = true;

                generalInnerPanel.Controls.Add(contextBox);
                generalInnerPanel.Controls.Add(reflectionBox);
                generalBox.Controls.Add(generalInnerPanel);

                GroupBox criteriaBox = new GroupBox();
                criteriaBox.Text     = "Localizability Criteria";
                criteriaBox.Dock     = DockStyle.Fill;
                criteriaBox.AutoSize = true;

                commonCriteriaGrid          = new DataGridView();
                commonCriteriaGrid.Dock     = DockStyle.Fill;
                commonCriteriaGrid.AutoSize = true;
                commonCriteriaGrid.AllowUserToOrderColumns = false;
                commonCriteriaGrid.SelectionMode           = DataGridViewSelectionMode.FullRowSelect;
                commonCriteriaGrid.MultiSelect             = false;
                commonCriteriaGrid.RowHeadersVisible       = false;
                commonCriteriaGrid.ScrollBars            = ScrollBars.Vertical;
                commonCriteriaGrid.BackgroundColor       = System.Drawing.SystemColors.Control;
                commonCriteriaGrid.BorderStyle           = BorderStyle.None;
                commonCriteriaGrid.AllowUserToAddRows    = false;
                commonCriteriaGrid.AllowUserToDeleteRows = false;
                commonCriteriaGrid.CellValueChanged     += new DataGridViewCellEventHandler(CommonCriteriaGrid_CellValueChanged);

                var descrColumn = new DataGridViewTextBoxColumn();
                descrColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                descrColumn.HeaderText   = "Description";
                descrColumn.ReadOnly     = true;
                commonCriteriaGrid.Columns.Add(descrColumn);

                actionColumn          = new DataGridViewComboBoxColumn();
                actionColumn.ReadOnly = false;
                actionColumn.Width    = 100;

                foreach (var o in Enum.GetValues(typeof(LocalizationCriterionAction)))
                {
                    actionColumn.Items.Add(((LocalizationCriterionAction)o).ToHumanForm());
                }

                actionColumn.HeaderText = "Action";
                commonCriteriaGrid.Columns.Add(actionColumn);

                var additionalColumns = new DataGridViewTextBoxColumn();
                additionalColumns.HeaderText = "Value";
                additionalColumns.ReadOnly   = true;
                additionalColumns.Width      = 50;
                commonCriteriaGrid.Columns.Add(additionalColumns);

                foreach (var pair in SettingsObject.Instance.CommonLocalizabilityCriteria)
                {
                    LocalizationCommonCriterion crit = pair.Value;

                    int rowIndex = commonCriteriaGrid.Rows.Add();
                    commonCriteriaGrid.Rows[rowIndex].Cells[0].Value = crit.Description;
                    commonCriteriaRowMap.Add(crit.Name, rowIndex);
                }
                criteriaBox.Controls.Add(commonCriteriaGrid);

                customCriteriaBox              = new GroupBox();
                customCriteriaBox.AutoSize     = true;
                customCriteriaBox.AutoSizeMode = AutoSizeMode.GrowAndShrink;
                customCriteriaBox.Text         = "Custom Localizability Criteria";
                customCriteriaBox.Dock         = DockStyle.Fill;

                customCriteriaTable              = new TableLayoutPanel();
                customCriteriaTable.AutoSize     = true;
                customCriteriaTable.Dock         = DockStyle.Fill;
                customCriteriaTable.AutoSizeMode = AutoSizeMode.GrowAndShrink;
                customCriteriaTable.RowStyles.Add(new RowStyle(SizeType.AutoSize));
                customCriteriaTable.RowCount = 1;

                addCustomCriteriaButton        = new Button();
                addCustomCriteriaButton.Click += new EventHandler(AddCustomCriteriaButton_Click);
                addCustomCriteriaButton.Text   = "Add criterion";
                customCriteriaTable.Controls.Add(addCustomCriteriaButton, 0, 0);

                customCriteriaBox.Controls.Add(customCriteriaTable);

                tablePanel.Controls.Add(generalBox, 0, 0);
                tablePanel.Controls.Add(criteriaBox, 0, 1);
                tablePanel.Controls.Add(customCriteriaBox, 0, 2);
            } catch (Exception ex) {
                VLOutputWindow.VisualLocalizerPane.WriteException(ex);
                VisualLocalizer.Library.Components.MessageBox.ShowException(ex);
            }
        }
        /// <summary>
        /// Loads settings from registry storage (on package load)
        /// </summary>
        public override void LoadSettingsFromStorage()
        {
            VisualLocalizerPackage package     = VisualLocalizerPackage.Instance;
            RegistryKey            rootKey     = package.UserRegistryRoot;
            RegistryKey            settingsKey = null;

            try {
                settingsKey = rootKey.OpenSubKey(REG_KEY, false);
                if (settingsKey != null)
                {
                    RegistryKey filtersKey = settingsKey.OpenSubKey(FILTER_KEY);

                    if (filtersKey != null)
                    {
                        SettingsObject.Instance.IgnorePropertyChanges = true;

                        SettingsObject.Instance.ShowContextColumn              = ReadBoolFromRegKey(filtersKey, "ShowFilterContext");
                        SettingsObject.Instance.UseReflectionInAsp             = ReadBoolFromRegKey(filtersKey, "UseReflectionInAsp");
                        SettingsObject.Instance.NamespacePolicyIndex           = ReadIntFromRegKey(filtersKey, "NamespacePolicyIndex");
                        SettingsObject.Instance.MarkNotLocalizableStringsIndex = ReadIntFromRegKey(filtersKey, "MarkNotLocalizableStringsIndex");
                        SettingsObject.Instance.BatchMoveSplitterDistance      = ReadIntFromRegKey(filtersKey, "BatchMoveSplitterDistance", 110);
                        SettingsObject.Instance.SelectedKeyIndex         = ReadIntFromRegKey(filtersKey, "SelectedKeyIndex", 0);
                        SettingsObject.Instance.SelectedUseFullName      = ReadBoolFromRegKey(filtersKey, "SelectedUseFullName");
                        SettingsObject.Instance.SelectedResourceFilePath = (string)filtersKey.GetValue("SelectedResourceFilePath", null);

                        foreach (var pair in SettingsObject.Instance.CommonLocalizabilityCriteria)
                        {
                            LocalizationCommonCriterion crit = pair.Value;
                            object val = filtersKey.GetValue(crit.Name);
                            if (val != null)
                            {
                                crit.FromRegData(val.ToString());
                            }
                        }

                        SettingsObject.Instance.CustomLocalizabilityCriteria.Clear();
                        int customCriteriaCount = ReadIntFromRegKey(filtersKey, "CustomCriteriaCount", 0);
                        for (int i = 0; i < customCriteriaCount; i++)
                        {
                            object val = filtersKey.GetValue("CustomCriteria" + i);
                            if (val != null)
                            {
                                LocalizationCustomCriterion crit = new LocalizationCustomCriterion(LocalizationCriterionAction.VALUE, 0);
                                crit.FromRegData(val.ToString());
                                SettingsObject.Instance.CustomLocalizabilityCriteria.Add(crit);
                            }
                        }
                    }
                    else
                    {
                        ResetSettings();
                    }
                }
                else
                {
                    ResetSettings();
                }
            } finally {
                if (settingsKey != null)
                {
                    settingsKey.Close();
                }

                SettingsObject.Instance.IgnorePropertyChanges = false;
                SettingsObject.Instance.NotifySettingsLoaded();
            }
        }
        /// <summary>
        /// Loads settings from XML (on import settings)
        /// </summary>
        public override void LoadSettingsFromXml(IVsSettingsReader reader)
        {
            SettingsObject.Instance.IgnorePropertyChanges = true;

            SettingsObject.Instance.ShowContextColumn              = ReadBoolFromXml(reader, "ShowFilterContext");
            SettingsObject.Instance.UseReflectionInAsp             = ReadBoolFromXml(reader, "UseReflectionInAsp");
            SettingsObject.Instance.MarkNotLocalizableStringsIndex = ReadIntFromXml(reader, "MarkNotLocalizableStringsIndex");
            SettingsObject.Instance.NamespacePolicyIndex           = ReadIntFromXml(reader, "NamespacePolicyIndex");
            SettingsObject.Instance.BatchMoveSplitterDistance      = ReadIntFromXml(reader, "BatchMoveSplitterDistance");
            SettingsObject.Instance.SelectedKeyIndex    = ReadIntFromXml(reader, "SelectedKeyIndex");
            SettingsObject.Instance.SelectedUseFullName = ReadBoolFromXml(reader, "SelectedUseFullName");

            int    hr;
            string tmp;

            hr = reader.ReadSettingString("SelectedResourceFilePath", out tmp);
            SettingsObject.Instance.SelectedResourceFilePath = tmp;
            Marshal.ThrowExceptionForHR(hr);

            foreach (var pair in SettingsObject.Instance.CommonLocalizabilityCriteria)
            {
                LocalizationCommonCriterion crit = pair.Value;

                string val;
                hr = reader.ReadSettingString(crit.Name, out val);
                if (hr != VSConstants.S_OK)
                {
                    throw new Exception("Error retrieving data from XML.");
                }

                if (val != null)
                {
                    crit.FromRegData(val.ToString());
                }
            }

            SettingsObject.Instance.CustomLocalizabilityCriteria.Clear();
            int customCriteriaCount = 0;

            hr = reader.ReadSettingLong("CustomCriteriaCount", out customCriteriaCount);
            if (hr != VSConstants.S_OK)
            {
                throw new Exception("Error retrieving data from XML.");
            }

            for (int i = 0; i < customCriteriaCount; i++)
            {
                string val;
                hr = reader.ReadSettingString("CustomCriteria" + i, out val);

                if (val != null)
                {
                    LocalizationCustomCriterion crit = new LocalizationCustomCriterion(LocalizationCriterionAction.VALUE, 0);
                    crit.FromRegData(val.ToString());
                    SettingsObject.Instance.CustomLocalizabilityCriteria.Add(crit);
                }
            }

            SettingsObject.Instance.IgnorePropertyChanges = false;
            SettingsObject.Instance.NotifySettingsLoaded();
        }