/// <summary> /// Called before editting a cell - suspends reference lookuper thread and sets current key as last valid /// </summary> protected override void OnCellBeginEdit(DataGridViewCellCancelEventArgs e) { try { if (Columns[e.ColumnIndex].Name == KeyColumnName && e.RowIndex >= 0) { ResXStringGridRow row = (ResXStringGridRow)Rows[e.RowIndex]; if (row.CodeReferenceContainsReadonly) { e.Cancel = true; VisualLocalizer.Library.Components.MessageBox.ShowError("This operation cannot be executed, because some of the references are located in readonly files."); return; } } base.OnCellBeginEdit(e); if (e.ColumnIndex == 0) { ResXStringGridRow row = (ResXStringGridRow)Rows[e.RowIndex]; editorControl.ReferenceCounterThreadSuspended = true; editorControl.UpdateReferencesCount(row); } } catch (Exception ex) { VLOutputWindow.VisualLocalizerPane.WriteException(ex); VisualLocalizer.Library.Components.MessageBox.ShowException(ex); } }
/// <summary> /// Called after key was changed - adds undo unit and performs refactoring of code /// </summary> public void KeyRenamed(ResXStringGridRow row, string newKey) { string oldKey = row.Status == KEY_STATUS.ERROR ? null : row.DataSourceItem.Name; GridRenameKeyUndoUnit unit = new GridRenameKeyUndoUnit(row, editorControl, oldKey, newKey); editorControl.Editor.AddUndoUnit(unit); if (VisualLocalizerPackage.Instance.DTE.Solution.ContainsProjectItem(editorControl.Editor.ProjectItem.InternalProjectItem)) { // obtain ResX project item ResXProjectItem resxItem = editorControl.Editor.ProjectItem; resxItem.ResolveNamespaceClass(resxItem.InternalProjectItem.ContainingProject.GetResXItemsAround(false, true)); if (row.ConflictItems.Count == 0 && resxItem != null && !resxItem.IsCultureSpecific() && !string.IsNullOrEmpty(newKey)) { int errors = 0; int count = row.CodeReferences.Count; // set new key row.CodeReferences.ForEach((item) => { item.KeyAfterRename = newKey.CreateIdentifier(resxItem.DesignerLanguage); }); // run the replacer try { editorControl.ReferenceCounterThreadSuspended = true; BatchReferenceReplacer replacer = new BatchReferenceReplacer(); replacer.Inline(row.CodeReferences, true, ref errors); } finally { editorControl.ReferenceCounterThreadSuspended = false; } VLOutputWindow.VisualLocalizerPane.WriteLine("Renamed {0} key references in code, {1} errors", count, errors); } } }
/// <summary> /// Adds given resource to the control /// </summary> public virtual IKeyValueSource Add(string key, ResXDataNode value) { if (key == null) { throw new ArgumentNullException("key"); } if (value == null) { throw new ArgumentNullException("value"); } ResXStringGridRow row = new ResXStringGridRow(); PopulateRow(row, value); Rows.Add(row); Validate(row); if (row.ErrorMessages.Count > 0) { row.Status = KEY_STATUS.ERROR; } else { row.Status = KEY_STATUS.OK; row.LastValidKey = row.Key; } return(row); }
/// <summary> /// Public wrapper for Validate(ResXStringGridRow) method /// </summary> public void ValidateRow(ResXStringGridRow row) { if (row == null) { throw new ArgumentNullException("row"); } Validate(row); }
/// <summary> /// Serializes resource data to a string /// </summary> protected virtual string CreateMangledComment(ResXStringGridRow row) { if (row == null) { throw new ArgumentNullException("row"); } return(string.Format("@@@{0}-@-{1}-@-{2}-@-{3}", (int)row.Status, row.DataSourceItem.Name, row.DataSourceItem.Comment, row.Value)); }
/// <summary> /// Called after value was changed - adds undo unit /// </summary> public void ValueChanged(ResXStringGridRow row, string oldValue, string newValue) { string key = row.Status == KEY_STATUS.ERROR ? null : row.DataSourceItem.Name; GridChangeValueUndoUnit unit = new GridChangeValueUndoUnit(row, this, key, oldValue, newValue, row.DataSourceItem.Comment); editorControl.Editor.AddUndoUnit(unit); VLOutputWindow.VisualLocalizerPane.WriteLine("Edited value of \"{0}\"", key); }
/// <summary> /// Serializes resource data to a string /// </summary> protected override string CreateMangledComment(ResXStringGridRow r) { if (r == null) { throw new ArgumentNullException("row"); } ResXOthersGridRow row = (ResXOthersGridRow)r; return(string.Format("@@@{0}-@-{1}-@-{2}-@-{3}-@-{4}", (int)row.Status, row.DataSourceItem.Name, row.DataSourceItem.Comment, row.Value, row.DataType.AssemblyQualifiedName)); }
/// <summary> /// Called when new row was added to the grid /// </summary> public void NewRowAdded(ResXStringGridRow row) { if (row == null) { throw new ArgumentNullException("row"); } NewRowsAdded(new List <ResXStringGridRow>() { row }); }
/// <summary> /// Updates row's status according to a new key /// </summary> protected void SetNewKey(ResXStringGridRow row, string newKey) { if (row == null) { throw new ArgumentNullException("row"); } if (string.IsNullOrEmpty(newKey)) { row.Status = KEY_STATUS.ERROR; } else { row.Status = KEY_STATUS.OK; row.DataSourceItem.Name = newKey; row.LastValidKey = newKey; } }
/// <summary> /// Initializes a new instance of the <see cref="AbstractResXEditorGrid"/> class. /// </summary> public AbstractResXEditorGrid(ResXEditorControl editorControl) : base(false, editorControl.conflictResolver) { this.editorControl = editorControl; this.AllowUserToAddRows = true; this.ShowEditingIcon = false; this.MultiSelect = true; this.Dock = DockStyle.Fill; this.BackColor = Color.White; this.BorderStyle = BorderStyle.None; this.ClipboardCopyMode = DataGridViewClipboardCopyMode.Disable; this.ScrollBars = ScrollBars.Both; this.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; this.AutoSize = true; // to remove rows this.editorControl.RemoveRequested += new Action <REMOVEKIND>(EditorControl_RemoveRequested); // to change depending buttons and context menu state (enabled/disabled) this.SelectionChanged += new EventHandler((o, e) => { NotifyItemsStateChanged(); }); this.NewRowNeeded += new DataGridViewRowEventHandler((o, e) => { NotifyItemsStateChanged(); }); this.MouseDown += new MouseEventHandler(Grid_MouseDown); this.Resize += new EventHandler(Grid_Resize); this.ColumnWidthChanged += new DataGridViewColumnEventHandler(Grid_ColumnWidthChanged); ResXStringGridRow rowTemplate = new ResXStringGridRow(); rowTemplate.MinimumHeight = 24; this.RowTemplate = rowTemplate; this.ContextMenu = BuildContextMenu(); this.ContextMenu.Popup += new EventHandler(ContextMenu_Popup); this.ColumnHeadersHeight = 24; UpdateContextItemsEnabled(); }
/// <summary> /// Adds given clipboard text to the grid - values separated with , and rows separated with ; format is expected /// </summary> public virtual void AddClipboardText(List <List <string> > data) { if (data == null) { throw new ArgumentNullException("data"); } List <ResXStringGridRow> addedRows = new List <ResXStringGridRow>(); foreach (List <string> columns in data) { if (columns.Count == 0) { continue; } string key = columns.Count >= 1 ? columns[0].CreateIdentifier(editorControl.Editor.ProjectItem.DesignerLanguage) : ""; // modify key so that is a valid identifier string value = columns.Count >= 2 ? columns[1] : ""; string comment = columns.Count >= 3 ? columns[2] : ""; ResXDataNode node = new ResXDataNode(key, value); // create new resource node.Comment = comment; ResXStringGridRow newRow = Add(key, node) as ResXStringGridRow; // add a row with the resource addedRows.Add(newRow); } if (addedRows.Count > 0) { NewRowsAdded(addedRows); NotifyDataChanged(); NotifyItemsStateChanged(); VLOutputWindow.VisualLocalizerPane.WriteLine("Added {0} new rows from clipboard", addedRows.Count); } }
/// <summary> /// Populates given row with data from given ResX node /// </summary> protected virtual void PopulateRow(ResXStringGridRow row, ResXDataNode node) { if (row == null) { throw new ArgumentNullException("row"); } if (node == null) { throw new ArgumentNullException("node"); } string name, value, comment; if (node.Comment.StartsWith("@@@")) // it's a mangled comment (row was not valid when saving) { string[] data = GetMangledCommentData(node.Comment); row.Status = (KEY_STATUS)int.Parse(data[0]); name = data[1]; comment = data[2]; value = data[3]; // set key if (row.Status == KEY_STATUS.OK) { node.Name = name; } else { name = string.Empty; } node = new ResXDataNode(name, value); node.Comment = comment; } else // the node is ok { name = node.Name; value = node.GetValue <string>(); comment = node.Comment; } DataGridViewTextBoxCell keyCell = new DataGridViewTextBoxCell(); keyCell.Value = name; DataGridViewTextBoxCell valueCell = new DataGridViewTextBoxCell(); valueCell.Value = value; DataGridViewTextBoxCell commentCell = new DataGridViewTextBoxCell(); commentCell.Value = comment; DataGridViewTextBoxCell referencesCell = new DataGridViewTextBoxCell(); referencesCell.Value = "?"; row.Cells.Add(keyCell); row.Cells.Add(valueCell); row.Cells.Add(commentCell); row.Cells.Add(referencesCell); row.DataSourceItem = node; referencesCell.ReadOnly = true; row.MinimumHeight = 25; }
/// <summary> /// Called after editting a cell /// </summary> protected override void OnCellEndEdit(DataGridViewCellEventArgs e) { try { if (e.RowIndex == Rows.Count - 1) { return; } base.OnCellEndEdit(e); if (e.ColumnIndex >= 0 && e.RowIndex >= 0) { ResXStringGridRow row = Rows[e.RowIndex] as ResXStringGridRow; bool isNewRow = false; if (row.DataSourceItem == null) // last empty row was edited, new row has been added { isNewRow = true; row.DataSourceItem = new ResXDataNode("(new)", string.Empty); } ResXDataNode node = row.DataSourceItem; if (Columns[e.ColumnIndex].Name == KeyColumnName) // key was edited { string newKey = (string)row.Cells[KeyColumnName].Value; if (isNewRow) { SetNewKey(row, newKey); row.Cells[ReferencesColumnName].Value = "?"; NewRowAdded(row); NotifyDataChanged(); } else if (string.Compare(newKey, node.Name) != 0) { // key has changed KeyRenamed(row, newKey); SetNewKey(row, newKey); NotifyDataChanged(); } } else if (Columns[e.ColumnIndex].Name == ValueColumnName) // value was edited { string newValue = (string)row.Cells[ValueColumnName].Value; if (newValue == null) { newValue = string.Empty; } if (isNewRow) { row.Status = KEY_STATUS.ERROR; row.Cells[ReferencesColumnName].Value = "?"; NewRowAdded(row); NotifyDataChanged(); } else if (string.Compare(newValue, node.GetValue <string>()) != 0) { // value has changed ValueChanged(row, node.GetValue <string>(), newValue); NotifyDataChanged(); string key = (string)row.Cells[KeyColumnName].Value; ResXDataNode newNode; if (string.IsNullOrEmpty(key)) { newNode = new ResXDataNode("A", newValue); row.Status = KEY_STATUS.ERROR; } else { newNode = new ResXDataNode(key, newValue); row.Status = KEY_STATUS.OK; row.LastValidKey = key; } newNode.Comment = (string)row.Cells[CommentColumnName].Value; row.DataSourceItem = newNode; } } else if (Columns[e.ColumnIndex].Name == CommentColumnName) // comment was edited { string newComment = (string)row.Cells[CommentColumnName].Value; if (isNewRow) { row.Status = KEY_STATUS.ERROR; row.Cells[ReferencesColumnName].Value = "?"; NewRowAdded(row); NotifyDataChanged(); } else if (string.Compare(newComment, node.Comment) != 0) { CommentChanged(row, node.Comment, newComment); NotifyDataChanged(); node.Comment = newComment; } } } } catch (Exception ex) { VLOutputWindow.VisualLocalizerPane.WriteException(ex); VisualLocalizer.Library.Components.MessageBox.ShowException(ex); } finally { editorControl.ReferenceCounterThreadSuspended = false; NotifyItemsStateChanged(); } }