From b5b6bf6e204d034475f8eb7b4a33b432417a1a9a Mon Sep 17 00:00:00 2001 From: JKlingen Date: Fri, 25 May 2012 19:38:16 +0000 Subject: [PATCH] LanguageEntries are now removed from the grid if both languageFiles contain null or empty value for it git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1903 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4 --- .../EntriesEditorWindow.xaml.cs | 47 ++-- .../GreenshotLanguageEditor.csproj | 1 + .../ObservableDictionary.cs | 257 ++++++++++++++++++ 3 files changed, 288 insertions(+), 17 deletions(-) create mode 100644 GreenshotLanguageEditor/ObservableDictionary.cs diff --git a/GreenshotLanguageEditor/EntriesEditorWindow.xaml.cs b/GreenshotLanguageEditor/EntriesEditorWindow.xaml.cs index 0ad91e3d1..ad8cb58d8 100644 --- a/GreenshotLanguageEditor/EntriesEditorWindow.xaml.cs +++ b/GreenshotLanguageEditor/EntriesEditorWindow.xaml.cs @@ -41,7 +41,7 @@ namespace GreenshotLanguageEditor { public partial class EntriesEditorWindow : Window, INotifyPropertyChanged { private string languagePath; - IDictionary languageResources = new SortedDictionary(); + ObservableDictionary languageResources = new ObservableDictionary(); IList languageFiles; public IList LanguageFiles { @@ -68,13 +68,15 @@ namespace GreenshotLanguageEditor { set; } + private ICollectionView view; public ICollectionView View { - get; - set; + get {return view;} + set {view=value; NotifyPropertyChanged("View");} } public EntriesEditorWindow() { + var dialog = new System.Windows.Forms.FolderBrowserDialog(); dialog.Description = "Select the directory containing the translation files for Greenshot. " + "Please get the latest files first: " + @@ -91,13 +93,18 @@ namespace GreenshotLanguageEditor { return; } - //languagePath = @"C:\Users\jens\Documents\Sharpdevelop Projects\Greenshot\trunk\Greenshot\Languages\"; + languagePath = @"C:\Users\jens\Documents\Sharpdevelop Projects\Greenshot\trunk\Greenshot\Languages\"; InitializeComponent(); DataContext = this; this.Activate(); View = CollectionViewSource.GetDefaultView(LoadResources(languagePath)); + languageResources.CollectionChanged += delegate { + + View = CollectionViewSource.GetDefaultView(languageResources.Values); + View.Refresh(); + }; } private IList LoadResources(string languagePath) { @@ -105,19 +112,16 @@ namespace GreenshotLanguageEditor { foreach (LanguageFile languageFile in GreenshotLanguage.GetLanguageFiles(languagePath, "language*.xml")) { LanguageFiles.Add(languageFile); - if ("en-US".Equals(languageFile.IETF)) { - // we should always start with en-US, so the grid is initialized with the probably most-complete language file as benchmark for translations - LanguageFile1 = languageFile; - PopulateColumn(languageFile, 1); - } else if(LanguageFile2 == null) { + // default: first non-english file is for right column, english file for left column + if(LanguageFile2 == null && !"en-US".Equals(languageFile.IETF)) { LanguageFile2 = languageFile; - PopulateColumn(languageFile, 2); + }else if (LanguageFile1 == null || "en-US".Equals(languageFile.IETF)) { + LanguageFile1 = languageFile; } } - if(LanguageFile1 == null) { - MessageBox.Show("language-en-US.xml does not exist in the location selected. It is needed as reference for the translation."); - this.Close(); - } + if(LanguageFile1 != null) PopulateColumn(LanguageFile1, 1); + if(LanguageFile2 != null) PopulateColumn(LanguageFile2, 2); + return new List(languageResources.Values); } @@ -132,16 +136,24 @@ namespace GreenshotLanguageEditor { } if(columnIndex == 1) unsavedChangesInLanguage1 = false; if(columnIndex == 2) unsavedChangesInLanguage2 = false; + } private void ClearColumn(int columnIndex) { - // we do not throw out LanguageEntries that do not exist in selected language, - // so that en-US (loaded at startup) is always the benchmark, even when other languages are displayed + IList resKeys = new List(languageResources.Keys); + //foreach(string key in resKeys) { foreach(LanguageEntry e in languageResources.Values) { - if (columnIndex == 1) e.Entry1 = null; + if (columnIndex == 1) e.Entry1 = null; else if (columnIndex == 2) e.Entry2 = null; else throw new ArgumentOutOfRangeException("Argument columnIndex must be either 1 or 2"); } + // remove entries with two null values + foreach(string key in resKeys) { + LanguageEntry e = languageResources[key]; + if(string.IsNullOrWhiteSpace(e.Entry1) && string.IsNullOrWhiteSpace(e.Entry2)) { + languageResources.Remove(e.Key); + } + } } private LanguageEntry GetOrCreateLanguageEntry(string key) { @@ -181,6 +193,7 @@ namespace GreenshotLanguageEditor { if(targetColumn == 1) LanguageFile1 = file; else if(targetColumn == 2) LanguageFile2 = file; PopulateColumn(file, targetColumn); + // TODO Language resources does not implement notifycollectionwhatever interface. does not work when keys are removed } private void cancelButtonClicked(object sender, RoutedEventArgs e) { diff --git a/GreenshotLanguageEditor/GreenshotLanguageEditor.csproj b/GreenshotLanguageEditor/GreenshotLanguageEditor.csproj index 8a39ac508..d937888f0 100644 --- a/GreenshotLanguageEditor/GreenshotLanguageEditor.csproj +++ b/GreenshotLanguageEditor/GreenshotLanguageEditor.csproj @@ -82,6 +82,7 @@ MetaEditorWindow.xaml Code + diff --git a/GreenshotLanguageEditor/ObservableDictionary.cs b/GreenshotLanguageEditor/ObservableDictionary.cs new file mode 100644 index 000000000..a5d9e2ccc --- /dev/null +++ b/GreenshotLanguageEditor/ObservableDictionary.cs @@ -0,0 +1,257 @@ +using System; +using System.Linq; +using System.ComponentModel; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace System.Collections.ObjectModel +{ + public class ObservableDictionary : IDictionary, INotifyCollectionChanged, INotifyPropertyChanged + { + private const string CountString = "Count"; + private const string IndexerName = "Item[]"; + private const string KeysName = "Keys"; + private const string ValuesName = "Values"; + + private IDictionary _Dictionary; + protected IDictionary Dictionary + { + get { return _Dictionary; } + } + + #region Constructors + public ObservableDictionary() + { + _Dictionary = new Dictionary(); + } + public ObservableDictionary(IDictionary dictionary) + { + _Dictionary = new Dictionary(dictionary); + } + public ObservableDictionary(IEqualityComparer comparer) + { + _Dictionary = new Dictionary(comparer); + } + public ObservableDictionary(int capacity) + { + _Dictionary = new Dictionary(capacity); + } + public ObservableDictionary(IDictionary dictionary, IEqualityComparer comparer) + { + _Dictionary = new Dictionary(dictionary, comparer); + } + public ObservableDictionary(int capacity, IEqualityComparer comparer) + { + _Dictionary = new Dictionary(capacity, comparer); + } + #endregion + + #region IDictionary Members + + public void Add(TKey key, TValue value) + { + Insert(key, value, true); + } + + public bool ContainsKey(TKey key) + { + return Dictionary.ContainsKey(key); + } + + public ICollection Keys + { + get { return Dictionary.Keys; } + } + + public bool Remove(TKey key) + { + if (key == null) throw new ArgumentNullException("key"); + + TValue value; + Dictionary.TryGetValue(key, out value); + var removed = Dictionary.Remove(key); + if (removed) + + //OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair(key, value)); + OnCollectionChanged(); + + return removed; + } + + public bool TryGetValue(TKey key, out TValue value) + { + return Dictionary.TryGetValue(key, out value); + } + + public ICollection Values + { + get { return Dictionary.Values; } + } + + public TValue this[TKey key] + { + get + { + return Dictionary[key]; + } + set + { + Insert(key, value, false); + } + } + + #endregion + + #region ICollection> Members + + public void Add(KeyValuePair item) + { + Insert(item.Key, item.Value, true); + } + + public void Clear() + { + if (Dictionary.Count > 0) + { + Dictionary.Clear(); + OnCollectionChanged(); + } + } + + public bool Contains(KeyValuePair item) + { + return Dictionary.Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + Dictionary.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return Dictionary.Count; } + } + + public bool IsReadOnly + { + get { return Dictionary.IsReadOnly; } + } + + public bool Remove(KeyValuePair item) + { + return Remove(item.Key); + } + + + #endregion + + #region IEnumerable> Members + + public IEnumerator> GetEnumerator() + { + return Dictionary.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)Dictionary).GetEnumerator(); + } + + #endregion + + #region INotifyCollectionChanged Members + + public event NotifyCollectionChangedEventHandler CollectionChanged; + + #endregion + + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + + public void AddRange(IDictionary items) + { + if (items == null) throw new ArgumentNullException("items"); + + if (items.Count > 0) + { + if (Dictionary.Count > 0) + { + if (items.Keys.Any((k) => Dictionary.ContainsKey(k))) + throw new ArgumentException("An item with the same key has already been added."); + else + foreach (var item in items) Dictionary.Add(item); + } + else + _Dictionary = new Dictionary(items); + + OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray()); + } + } + + private void Insert(TKey key, TValue value, bool add) + { + if (key == null) throw new ArgumentNullException("key"); + + TValue item; + if (Dictionary.TryGetValue(key, out item)) + { + if (add) throw new ArgumentException("An item with the same key has already been added."); + if (Equals(item, value)) return; + Dictionary[key] = value; + + OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair(key, value), new KeyValuePair(key, item)); + } + else + { + Dictionary[key] = value; + + OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair(key, value)); + } + } + + private void OnPropertyChanged() + { + OnPropertyChanged(CountString); + OnPropertyChanged(IndexerName); + OnPropertyChanged(KeysName); + OnPropertyChanged(ValuesName); + } + + protected virtual void OnPropertyChanged(string propertyName) + { + if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + + private void OnCollectionChanged() + { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair changedItem) + { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair newItem, KeyValuePair oldItem) + { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems) + { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems)); + } + } +} \ No newline at end of file