/* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Collections.ObjectModel; using System.ComponentModel; using System.Text.RegularExpressions; using System.Xml; namespace GreenshotLanguageEditor { /// /// Interaction logic for EntriesEditorWindow.xaml /// public partial class EntriesEditorWindow : Window, INotifyPropertyChanged { private string languagePath; ObservableDictionary languageResources = new ObservableDictionary(); IList languageFiles; public IList LanguageFiles { get {return languageFiles;} set {languageFiles = value; NotifyPropertyChanged("languageFiles");} } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } // maybe refactor this encapsulating column related info bool unsavedChangesInLanguage1 = false; bool unsavedChangesInLanguage2 = false; public LanguageFile LanguageFile1 { get; set; } public LanguageFile LanguageFile2 { get; set; } private ICollectionView view; public ICollectionView View { 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: " + "https://greenshot.svn.sourceforge.net/svnroot/greenshot/trunk/Greenshot/Languages/"; dialog.ShowNewFolderButton = false; System.Windows.Forms.DialogResult result = dialog.ShowDialog(); string languagePath; if (result == System.Windows.Forms.DialogResult.OK) { languagePath = dialog.SelectedPath; } else { this.Close(); return; } 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) { LanguageFiles = new BindingList(); foreach (LanguageFile languageFile in GreenshotLanguage.GetLanguageFiles(languagePath, "language*.xml")) { LanguageFiles.Add(languageFile); // default: first non-english file is for right column, english file for left column if(LanguageFile2 == null && !"en-US".Equals(languageFile.IETF)) { LanguageFile2 = languageFile; }else if (LanguageFile1 == null || "en-US".Equals(languageFile.IETF)) { LanguageFile1 = languageFile; } } if(LanguageFile1 != null) PopulateColumn(LanguageFile1, 1); if(LanguageFile2 != null) PopulateColumn(LanguageFile2, 2); return new List(languageResources.Values); } private void PopulateColumn(LanguageFile languageFile, int columnIndex) { ClearColumn(columnIndex); IDictionary resources = GreenshotLanguage.ReadLanguageFile(languageFile); foreach(string key in resources.Keys) { LanguageEntry entry = GetOrCreateLanguageEntry(key); if(columnIndex == 1) entry.Entry1 = resources[key]; else if (columnIndex == 2) entry.Entry2 = resources[key]; else throw new ArgumentOutOfRangeException("Argument columnIndex must be either 1 or 2"); } if(columnIndex == 1) unsavedChangesInLanguage1 = false; if(columnIndex == 2) unsavedChangesInLanguage2 = false; } private void ClearColumn(int columnIndex) { IList resKeys = new List(languageResources.Keys); //foreach(string key in resKeys) { foreach(LanguageEntry e in languageResources.Values) { 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) { LanguageEntry entry; if (languageResources.ContainsKey(key)) { entry = languageResources[key]; } else { entry = new LanguageEntry(); entry.Key = key; languageResources.Add(key, entry); } return entry; } private void saveButtonClicked(object sender, RoutedEventArgs e) { int targetColumn = GetTargetColumn((Control)sender); LanguageFile editedFile = (LanguageFile) (targetColumn == 1 ? language1ComboBox.SelectedItem : language2ComboBox.SelectedItem); CreateXML(editedFile.FilePath, targetColumn); } private void languageComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { int targetColumn = GetTargetColumn((Control)sender); LanguageFile file = (LanguageFile)((ComboBox)sender).SelectedItem; if((targetColumn == 1 && file.Equals(LanguageFile1)) || (targetColumn == 2 && file.Equals(LanguageFile2))) { // nothing changed return; } if((targetColumn == 1 && unsavedChangesInLanguage1) || (targetColumn == 2 && unsavedChangesInLanguage2)) { MessageBoxResult res = MessageBox.Show("Do you really want to switch language? Unsaved changes will be lost.", "Confirm language switch", MessageBoxButton.OKCancel, MessageBoxImage.Warning,MessageBoxResult.Cancel,MessageBoxOptions.None); if(res != MessageBoxResult.OK) { // cancelled by user ((ComboBox)sender).SelectedItem = (targetColumn == 1) ? LanguageFile1 : LanguageFile2; return; } } 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) { int targetColumn = GetTargetColumn((Control)sender); if((targetColumn == 1 && unsavedChangesInLanguage1) || (targetColumn == 2 && unsavedChangesInLanguage2)) { MessageBoxResult res = MessageBox.Show("Do you really want to reset this column? Unsaved changes will be lost.", "Confirm language reset", MessageBoxButton.OKCancel, MessageBoxImage.Warning,MessageBoxResult.Cancel,MessageBoxOptions.None); if(res == MessageBoxResult.OK) { LanguageFile file = (LanguageFile)(targetColumn == 1 ? language1ComboBox.SelectedItem : language2ComboBox.SelectedItem); PopulateColumn(file, targetColumn); } } } private void newButtonClicked(object sender, RoutedEventArgs e) { int targetColumn = GetTargetColumn((Control)sender); if((targetColumn == 1 && unsavedChangesInLanguage1) || (targetColumn == 2 && unsavedChangesInLanguage2)) { MessageBoxResult res = MessageBox.Show("Do you really want to discard this column? Unsaved changes will be lost.", "Confirm new language file creation", MessageBoxButton.OKCancel, MessageBoxImage.Warning,MessageBoxResult.Cancel,MessageBoxOptions.None); if(res != MessageBoxResult.OK) { return; } } LanguageFile newLang = new LanguageFile(); newLang.FilePath = languagePath; new MetaEditorWindow(newLang).ShowDialog(); if(newLang.FileName != null && newLang.FileName.Length > 0) { ClearColumn(targetColumn); CreateXML(newLang.FilePath,targetColumn); LanguageFiles.Add(newLang); LanguageFiles = LanguageFiles.OrderBy(f => f.FileName).ToList(); if(targetColumn == 1) { LanguageFile1 = newLang; language1ComboBox.SelectedItem = newLang; } else { LanguageFile2 = newLang; language2ComboBox.SelectedItem = newLang; } PopulateColumn(newLang, targetColumn); } } private void metaButtonClicked(object sender, RoutedEventArgs e) { int targetColumn = GetTargetColumn((Control)sender); new MetaEditorWindow(targetColumn == 1 ? LanguageFile1 : LanguageFile2).ShowDialog(); } private int GetTargetColumn(Control control) { object tag = control.Tag; if(tag == null && !tag.Equals("1") && !tag.Equals("2")) { throw new ApplicationException("Please use the control's Tag property to indicate the column to interact with (1 or 2)."); } else { return tag.Equals("1") ? 1 : 2; } } private void cellEdited(object sender, DataGridCellEditEndingEventArgs e) { if(e.Column.DisplayIndex == 1) unsavedChangesInLanguage1 = true; else if(e.Column.DisplayIndex == 2) unsavedChangesInLanguage2 = true; } public void CreateXML(string savePath, int targetColumn) { LanguageFile langfile = targetColumn == 1 ? LanguageFile1 : LanguageFile2; ICollectionView view = (ICollectionView)LanguageGrid.ItemsSource; IList entries = (IList)view.SourceCollection; using (XmlTextWriter xmlWriter = new XmlTextWriter(savePath, Encoding.UTF8)) { xmlWriter.Formatting = Formatting.Indented; xmlWriter.Indentation = 1; xmlWriter.IndentChar = '\t'; xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("language"); xmlWriter.WriteAttributeString("description", langfile.Description); xmlWriter.WriteAttributeString("ietf", langfile.IETF); xmlWriter.WriteAttributeString("version", langfile.Version); xmlWriter.WriteAttributeString("languagegroup", langfile.Languagegroup); xmlWriter.WriteStartElement("resources"); foreach(LanguageEntry entry in entries) { string entryValue = (targetColumn == 1) ? entry.Entry1 : entry.Entry2; if(!String.IsNullOrWhiteSpace(entryValue) && !String.IsNullOrWhiteSpace(entry.Key)) { xmlWriter.WriteStartElement("resource"); xmlWriter.WriteAttributeString("name", entry.Key); xmlWriter.WriteString(entryValue); xmlWriter.WriteEndElement(); } } xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); xmlWriter.WriteEndDocument(); } } } public class LanguageEntry : IEditableObject, INotifyPropertyChanged { private string key; private string entry1; private string entry2; public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } public Brush Background { get { if (String.IsNullOrEmpty(Entry1)) { return Brushes.Red; } if (String.IsNullOrEmpty(Entry2)) { return Brushes.Red; } return Brushes.White; } } public string Key { get { return key; } set { key = value; NotifyPropertyChanged("Key"); } } public string Entry1 { get { return entry1; } set { entry1 = value; NotifyPropertyChanged("Entry1"); NotifyPropertyChanged("Background"); } } public string Entry2 { get { return entry2; } set { entry2 = value; NotifyPropertyChanged("Entry2"); NotifyPropertyChanged("Background"); } } public void BeginEdit() { } public void EndEdit() { } public void CancelEdit() { } } }