PageRenderTime 67ms CodeModel.GetById 16ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 0ms

/Application/GUI/Windows/PropertiesWindow.xaml.cs

http://yet-another-music-application.googlecode.com/
C# | 765 lines | 472 code | 104 blank | 189 comment | 78 complexity | 33fb5768e9d45c1d3851edd14cb236a7 MD5 | raw file
  1/**
  2 * PropertiesWindow.xaml.cs
  3 * 
  4 * The dialog showing information about one or several
  5 * tracks.
  6 * 
  7 * * * * * * * * *
  8 * 
  9 * This code is part of the Stoffi Music Player Project.
 10 * Visit our website at: stoffiplayer.com
 11 *
 12 * This program is free software; you can redistribute it and/or
 13 * modify it under the terms of the GNU General Public License
 14 * as published by the Free Software Foundation; either version
 15 * 3 of the License, or (at your option) any later version.
 16 * 
 17 * See stoffiplayer.com/license for more information.
 18 **/
 19
 20using System;
 21using System.Collections.Generic;
 22using System.Collections.ObjectModel;
 23using System.IO;
 24using System.Linq;
 25using System.Text;
 26using System.Windows;
 27using System.Windows.Controls;
 28using System.Windows.Data;
 29using System.Windows.Documents;
 30using System.Windows.Input;
 31using System.Windows.Media;
 32using System.Windows.Media.Imaging;
 33
 34namespace Stoffi
 35{
 36	/// <summary>
 37	/// Interaction logic for PropertiesWindow.xaml
 38	/// </summary>
 39	public partial class PropertiesWindow : Window
 40	{
 41		#region Members
 42
 43		/// <summary>
 44		/// Used to hold the data before writing it to file
 45		/// </summary>
 46		private TrackData tempTrack = new TrackData();
 47
 48		/// <summary>
 49		/// Holds the list of all properties inside DetailsList
 50		/// </summary>
 51		ObservableCollection<PropertyData> properties = new ObservableCollection<PropertyData>();
 52
 53		#endregion
 54
 55		#region Properties
 56
 57		/// <summary>
 58		/// Gets the tracks that are being viewed
 59		/// </summary>
 60		public List<TrackData> Tracks { get; private set; }
 61
 62		#endregion
 63
 64		#region Constructor
 65
 66		/// <summary>
 67		/// Creates an instance of the PropertiesWindow window.
 68		/// </summary>
 69		/// <param name="tracks">The tracks to load</param>
 70		public PropertiesWindow(List<TrackData> tracks)
 71		{
 72			U.L(LogLevel.Debug, "PROPERTIES", "Initialize");
 73			InitializeComponent();
 74			U.L(LogLevel.Debug, "PROPERTIES", "Initialized");
 75			int size = 16;
 76			PrevImage.Source = Utilities.GetIcoImage("pack://application:,,,/GUI/Images/Icons/LeftArrow.ico", size, size);
 77			NextImage.Source = Utilities.GetIcoImage("pack://application:,,,/GUI/Images/Icons/RightArrow.ico", size, size);
 78			PrevImage.Height = size;
 79			NextImage.Height = size;
 80			PrevImage.Width = size;
 81			NextImage.Width = size;
 82			OK.Visibility = System.Windows.Visibility.Collapsed;
 83			Apply.Visibility = System.Windows.Visibility.Collapsed;
 84			Cancel.Content = U.T("ButtonClose", "Content");
 85			Tracks = new List<TrackData>();
 86			AddTracks(tracks);
 87
 88			if (System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName != "")
 89			{
 90				Tabs.Background = Brushes.White;
 91				Background = Brushes.WhiteSmoke;
 92			}
 93		}
 94
 95		#endregion
 96
 97		#region Methods
 98
 99		#region Public
100		
101		/// <summary>
102		/// Loads a number of tracks into the window
103		/// </summary>
104		/// <param name="tracksToAdd">The tracks to load</param>
105		public void AddTracks(List<TrackData> tracksToAdd)
106		{
107			Tracks.Clear();
108			Tracks.AddRange(tracksToAdd);
109
110			if (Tracks.Count == 1)
111			{
112				// load values
113				string p = Tracks[0].Path;
114				string e = Path.GetExtension(p).Substring(1);
115				FileInfo fInfo = new FileInfo(p);
116				TagLib.File file = TagLib.File.Create(p, TagLib.ReadStyle.Average);
117
118				// set temp track
119				tempTrack.Path = p;
120
121				// set visibilities
122				LastPlayed.Visibility = System.Windows.Visibility.Visible;
123				CreatedAt.Visibility = System.Windows.Visibility.Visible;
124				ModifiedAt.Visibility = System.Windows.Visibility.Visible;
125				AccessedAt.Visibility = System.Windows.Visibility.Visible;
126				LastPlayedLabel.Visibility = System.Windows.Visibility.Visible;
127				CreatedAtLabel.Visibility = System.Windows.Visibility.Visible;
128				ModifiedAtLabel.Visibility = System.Windows.Visibility.Visible;
129				AccessedAtLabel.Visibility = System.Windows.Visibility.Visible;
130				Filename.Visibility = System.Windows.Visibility.Visible;
131				Filecount.Visibility = System.Windows.Visibility.Collapsed;
132				ArtBackgroundMultiple.Visibility = System.Windows.Visibility.Collapsed;
133				ArtBackgroundSingle.Visibility = System.Windows.Visibility.Collapsed;
134
135				// set textblocks
136				Filename.Text = Path.GetFileName(p);
137				Filetype.Text = String.Format(U.T("PropertiesGeneralTypeFormat"), e.ToUpper(), e);
138				Filepath.Text = Path.GetDirectoryName(p);
139				Filesize.Text = U.HumanSize(fInfo.Length);
140				Codec.Text = Tracks[0].Codecs;
141				Bitrate.Text = Tracks[0].Bitrate.ToString();
142				Channels.Text = Tracks[0].Channels.ToString();
143				LastPlayed.Text = Tracks[0].LastPlayed;
144				Length.Text = Tracks[0].Length;
145				PlayCount.Text = Tracks[0].PlayCount.ToString();
146				SampleRate.Text = Tracks[0].SampleRate.ToString();
147				CreatedAt.Text = fInfo.CreationTime.ToString();
148				ModifiedAt.Text = fInfo.LastWriteTime.ToString();
149				AccessedAt.Text = fInfo.LastAccessTime.ToString();
150
151				// set art
152				AlbumArt.Source = FilesystemManager.GetImageTag(Tracks[0]);
153			}
154			else if (Tracks.Count > 1)
155			{
156				Filename.Visibility = System.Windows.Visibility.Collapsed;
157				Filecount.Visibility = System.Windows.Visibility.Visible;
158
159				LastPlayed.Visibility = System.Windows.Visibility.Collapsed;
160				CreatedAt.Visibility = System.Windows.Visibility.Collapsed;
161				ModifiedAt.Visibility = System.Windows.Visibility.Collapsed;
162				AccessedAt.Visibility = System.Windows.Visibility.Collapsed;
163				LastPlayedLabel.Visibility = System.Windows.Visibility.Collapsed;
164				CreatedAtLabel.Visibility = System.Windows.Visibility.Collapsed;
165				ModifiedAtLabel.Visibility = System.Windows.Visibility.Collapsed;
166				AccessedAtLabel.Visibility = System.Windows.Visibility.Collapsed;
167
168				TrackData t = Tracks[0];
169				string e = Path.GetExtension(t.Path).Substring(1);
170				string location = Path.GetDirectoryName(t.Path);
171				long size = 0;
172				string bitrate = t.Bitrate.ToString();
173				string channels = t.Channels.ToString();
174				double length = 0;
175				uint playcount = 0;
176				string samplerate = t.SampleRate.ToString();
177				string codec = t.Codecs;
178
179
180				foreach (TrackData track in Tracks)
181				{
182					FileInfo f = new FileInfo(track.Path);
183
184					size += f.Length;
185					length += track.RawLength;
186					playcount += track.PlayCount;
187
188					if (Path.GetExtension(track.Path).Substring(1) != e)
189						e = U.T("PropertiesGeneralVariousFormats");
190
191					if (Path.GetDirectoryName(t.Path) != location)
192						location = U.T("PropertiesGeneralVariousLocations");
193
194					if (track.Bitrate.ToString() != bitrate)
195						bitrate = U.T("PropertiesGeneralVariousBitrates");
196
197					if (track.Channels.ToString() != channels)
198						channels = U.T("PropertiesGeneralVariousChannels");
199
200					if (track.SampleRate.ToString() != samplerate)
201						samplerate = U.T("PropertiesGeneralVariousSamplerates");
202
203					if (track.Codecs.ToString() != codec)
204						codec = U.T("PropertiesGeneralVariousCodecs");
205				}
206
207				if (e != U.T("PropertiesGeneralVariousFormats"))
208					Filetype.Text = String.Format(U.T("PropertiesGeneralTypeFormat"), e.ToUpper(), e);
209				else
210					Filetype.Text = e;
211
212				Filecount.Text = String.Format(U.T("PropertiesMultipleFiles"), Tracks.Count);
213				Filepath.Text = location;
214				Filesize.Text = U.HumanSize(size);
215				Codec.Text = codec;
216				Bitrate.Text = bitrate;
217				Channels.Text = channels;
218				Length.Text = U.TimeSpanToString(new TimeSpan(0, 0, Convert.ToInt32(length)));
219				PlayCount.Text = playcount.ToString();
220				SampleRate.Text = samplerate;
221
222				AlbumArt.Source = FilesystemManager.GetImageTag(Tracks[0]);
223				ArtBackgroundMultiple.Visibility = System.Windows.Visibility.Collapsed;
224				ArtBackgroundSingle.Visibility = System.Windows.Visibility.Collapsed;
225			}
226
227			FillProperties();
228		}
229
230		#endregion
231
232		#region Private
233
234		/// <summary>
235		/// Checks if two strings are equal.
236		/// An empty string and null are considered equal.
237		/// </summary>
238		/// <param name="str1">The first string</param>
239		/// <param name="str2">The second string</param>
240		/// <returns>True if the strings are equal, otherwise false</returns>
241		private bool FieldsEqual(string str1, string str2)
242		{
243			return (str1 == str2 || (str1 == "" && str2 == null) || (str2 == "" && str1 == null));
244		}
245
246		/// <summary>
247		/// Gets the value of a specific metadata tag given its name
248		/// </summary>
249		/// <param name="track">The track to retrieve the tag from</param>
250		/// <param name="tag">The name of the tag</param>
251		/// <returns>The value of the tag</returns>
252		private object GetTag(TrackData track, string tag)
253		{
254			switch (tag)
255			{
256				case "Artist":
257					return track.Artist as object;
258
259				case "Title":
260					return track.Title as object;
261
262				case "Album":
263					return track.Album as object;
264
265				case "Genre":
266					return track.Genre as object;
267
268				case "Track":
269					return track.Track as object;
270
271				case "Year":
272					if (track.Year == null)
273						return null;
274					object y = track.Year as object;
275					return track.Year as object;
276
277				default:
278					return "" as object;
279			}
280		}
281
282		/// <summary>
283		/// Gets the property given its name
284		/// </summary>
285		/// <param name="name">The name of the property</param>
286		/// <returns>The PropertyData in properties with the name <paramref name="name"/>.
287		/// null if none found.</returns>
288		private PropertyData GetProperty(string name)
289		{
290			foreach (PropertyData p in properties)
291				if (name == p.Name)
292					return p;
293			return null;
294		}
295
296		/// <summary>
297		/// Gets the property value given its name
298		/// </summary>
299		/// <param name="name">The name of the property</param>
300		/// <returns>The value of the PropertyData in properties with the name <paramref name="name"/>.
301		/// null if none found.</returns>
302		private string GetPropertyValue(string name)
303		{
304			foreach (PropertyData p in properties)
305				if (name == p.Name)
306					return p.Value;
307			return null;
308		}
309
310		/// <summary>
311		/// Checks if the tracks have the same value for a given tag
312		/// </summary>
313		/// <param name="tag">The name of the metadata tag</param>
314		/// <returns>Either the string for all tracks value of the field,
315		/// or a string describing that the values are different</returns>
316		private string CheckIfSame(string tag)
317		{
318			if (Tracks.Count < 1) return null;
319
320			bool same = true;
321			object o = GetTag(Tracks[0], tag);
322
323			foreach (TrackData t in Tracks)
324			{
325				object p = GetTag(t, tag);
326				if ((o != p && o == null) || (o.ToString() != p.ToString()))
327				{
328					same = false;
329					break;
330				}
331			}
332
333			string s = o == null ? "" : o.ToString();
334
335			return same ? s : U.T("PropertiesDetailsMultipleValues");
336		}
337
338		/// <summary>
339		/// Loads data into DetailsList
340		/// </summary>
341		private void FillProperties()
342		{
343			string title = "";
344			string artist = "";
345			string album = "";
346			string year = "";
347			string track = "";
348			string genre = "";
349			if (Tracks.Count == 1)
350			{
351				title = Tracks[0].Title;
352				artist = Tracks[0].Artist;
353				album = Tracks[0].Album;
354				year = Tracks[0].Year.ToString();
355				track = Tracks[0].Track.ToString();
356				genre = Tracks[0].Genre;
357			}
358			else
359			{
360				title = CheckIfSame("Title");
361				artist = CheckIfSame("Artist");
362				album = CheckIfSame("Album");
363				year = CheckIfSame("Year");
364				track = CheckIfSame("Track");
365				genre = CheckIfSame("Genre");
366			}
367
368			properties.Clear();
369			properties.Add(new PropertyData() { Edited = false, Name = U.T("ColumnTitle"), Value = title });
370			properties.Add(new PropertyData() { Edited = false, Name = U.T("ColumnArtist"), Value = artist });
371			properties.Add(new PropertyData() { Edited = false, Name = U.T("ColumnAlbum"), Value = album });
372			properties.Add(new PropertyData() { Edited = false, Name = U.T("ColumnYear"), Value = year as string });
373			properties.Add(new PropertyData() { Edited = false, Name = U.T("ColumnTrack"), Value = track as string });
374			properties.Add(new PropertyData() { Edited = false, Name = U.T("ColumnGenre"), Value = genre });
375			DetailsList.ItemsSource = properties;
376
377			// load into temporary holder
378			tempTrack.Title = title;
379			tempTrack.Artist = artist;
380			tempTrack.Album = album;
381			if (track != U.T("PropertiesDetailsMultipleValues") && track != "")
382				tempTrack.Track = Convert.ToUInt32(track);
383			if (year != U.T("PropertiesDetailsMultipleValues") && year != "")
384				tempTrack.Year = Convert.ToUInt32(year);
385			tempTrack.Genre = genre;
386		}
387
388		/// <summary>
389		/// Saves data from DetailsList into tempTrack
390		/// </summary>
391		private void SaveProperties()
392		{
393			foreach (PropertyData p in properties)
394			{
395				if (p.Edited)
396					switch (p.Name)
397					{
398						case "Artist":
399							tempTrack.Artist = p.Value;
400							break;
401
402						case "Title":
403							tempTrack.Title = p.Value;
404							break;
405
406						case "Album":
407							tempTrack.Album = p.Value;
408							break;
409
410						case "Genre":
411							tempTrack.Genre = p.Value;
412							break;
413
414						case "Track":
415							try
416							{
417								tempTrack.Track = Convert.ToUInt32(p.Value);
418							}
419							catch (Exception e)
420							{
421								MessageBox.Show(e.Message, "Could Not Save Value", MessageBoxButton.OK, MessageBoxImage.Error);
422							}
423							break;
424
425						case "Year":
426							try
427							{
428								tempTrack.Year = Convert.ToUInt32(p.Value);
429							}
430							catch (Exception e)
431							{
432								MessageBox.Show(e.Message, "Could Not Save Value", MessageBoxButton.OK, MessageBoxImage.Error);
433							}
434							break;
435					}
436				p.Edited = false;
437			}
438		}
439
440		/// <summary>
441		/// Saves all data of tempTrack to the tracks
442		/// </summary>
443		private void Save()
444		{
445			SaveProperties();
446
447			foreach (TrackData t in Tracks)
448			{
449				t.Title = tempTrack.Title;
450				t.Artist = tempTrack.Artist;
451				t.Album = tempTrack.Album;
452				t.Genre = tempTrack.Genre;
453				t.Track = tempTrack.Track;
454				try
455				{
456					FilesystemManager.SaveTrack(t);
457				}
458				catch (Exception e)
459				{
460					MessageBox.Show(e.Message, U.T("MessageErrorUpdating", "Title"), MessageBoxButton.OK, MessageBoxImage.Error);
461				}
462			}
463
464			if (Tracks.Count == 1)
465			{
466				string oldPath = Tracks[0].Path;
467				string newPath = Path.Combine(Path.GetDirectoryName(oldPath), Filename.Text);
468				if (oldPath != newPath)
469				{
470					try
471					{
472						File.Move(oldPath, newPath);
473						tempTrack.Path = newPath;
474					}
475					catch (Exception e)
476					{
477						MessageBox.Show(e.Message, U.T("MessageErrorRenaming", "Title"), MessageBoxButton.OK, MessageBoxImage.Error);
478					}
479				}
480			}
481
482			ToggleButtons();
483		}
484
485		/// <summary>
486		/// Will show a set of buttons depending on
487		/// whether any value has changed.
488		/// 
489		/// changed:
490		/// OK, Cancel, Apply
491		/// 
492		/// not changed:
493		/// Close
494		/// </summary>
495		private void ToggleButtons()
496		{
497			bool anyChanged = false;
498
499			// check properties
500			foreach (PropertyData p in properties)
501			{
502				if (p.Edited)
503				{
504					anyChanged = true;
505					break;
506				}
507			}
508
509			// check filename
510			string filename = Path.GetFileName(tempTrack.Path);
511			if (Tracks.Count == 1 && filename != Filename.Text)
512				anyChanged = true;
513
514			if (anyChanged)
515			{
516				OK.Visibility = System.Windows.Visibility.Visible;
517				Apply.Visibility = System.Windows.Visibility.Visible;
518				Cancel.Content = U.T("ButtonCancel", "Content");
519			}
520			else
521			{
522				OK.Visibility = System.Windows.Visibility.Collapsed;
523				Apply.Visibility = System.Windows.Visibility.Collapsed;
524				Cancel.Content = U.T("ButtonClose", "Content");
525			}
526		}
527
528		#endregion
529
530		#region Event handlers
531
532		/// <summary>
533		/// Invoked when the user clicks "Next"
534		/// </summary>
535		/// <param name="sender">The sender of the event</param>
536		/// <param name="e">The event data</param>
537		/// <remarks>Will load the next track</remarks>
538		private void Next_Click(object sender, RoutedEventArgs e)
539		{
540			OnNext();
541		}
542
543		/// <summary>
544		/// Invoked when the user clicks "Previous"
545		/// </summary>
546		/// <param name="sender">The sender of the event</param>
547		/// <param name="e">The event data</param>
548		/// <remarks>Will load the previous track</remarks>
549		private void Previous_Click(object sender, RoutedEventArgs e)
550		{
551			OnPrev();
552		}
553
554		/// <summary>
555		/// Invoked when the user clicks "OK"
556		/// </summary>
557		/// <param name="sender">The sender of the event</param>
558		/// <param name="e">The event data</param>
559		/// <remarks>Will close the window after saving</remarks>
560		private void OK_Click(object sender, RoutedEventArgs e)
561		{
562			Save();
563			Close();
564		}
565
566		/// <summary>
567		/// Invoked when the user clicks "Apply"
568		/// </summary>
569		/// <param name="sender">The sender of the event</param>
570		/// <param name="e">The event data</param>
571		/// <remarks>Will save all data</remarks>
572		private void Apply_Click(object sender, RoutedEventArgs e)
573		{
574			Save();
575		}
576
577		/// <summary>
578		/// Invoked when the user clicks "Close" or "Cancel"
579		/// </summary>
580		/// <param name="sender">The sender of the event</param>
581		/// <param name="e">The event data</param>
582		/// <remarks>Will close the window without saving</remarks>
583		private void CloseCancel_Click(object sender, RoutedEventArgs e)
584		{
585			Close();
586		}
587
588		/// <summary>
589		/// Invoked when the user edits the value of a property
590		/// </summary>
591		/// <param name="sender">The sender of the event</param>
592		/// <param name="e">The event data</param>
593		/// <remarks>Will save the text to the temporary structure</remarks>
594		private void EditableTextBlock_Edited(object sender, EditableTextBlockEventArgs e)
595		{
596			EditableTextBlock etb = sender as EditableTextBlock;
597			string prop = etb.Tag as string;
598			PropertyData p = null;
599			foreach (PropertyData pd in properties)
600			{
601				if (pd.Name == prop)
602				{
603					p = pd;
604					break;
605				}
606			}
607
608			if (p != null)
609			{
610				p.Value = e.NewText;
611				object curObj = GetTag(tempTrack, p.Name);
612				string cur = curObj as string;
613				p.Edited = curObj == null || p.Value != curObj.ToString();
614			}
615
616			ToggleButtons();
617		}
618
619		/// <summary>
620		/// Invoked when the user is typing inside the Filename box.
621		/// </summary>
622		/// <param name="sender">The sender of the event</param>
623		/// <param name="e">The event data</param>
624		/// <remarks>Will refresh the button set</remarks>
625		private void Filename_KeyUp(object sender, KeyEventArgs e)
626		{
627			ToggleButtons();
628		}
629
630		#endregion
631
632		#region Dispatchers
633
634		/// <summary>
635		/// Dispatches the NextClick event
636		/// </summary>
637		private void OnNext()
638		{
639			if (NextClick != null)
640				NextClick(this, new EventArgs());
641		}
642
643		/// <summary>
644		/// Dispatches the PreviousClick event
645		/// </summary>
646		private void OnPrev()
647		{
648			if (PreviousClick != null)
649				PreviousClick(this, new EventArgs());
650		}
651
652		#endregion
653
654		#endregion
655
656		#region Events
657
658		/// <summary>
659		/// Occurs when the user clicks Next
660		/// </summary>
661		public event EventHandler NextClick;
662
663		/// <summary>
664		/// Occurs when the user clicks Previous
665		/// </summary>
666		public event EventHandler PreviousClick;
667
668		#endregion
669	}
670
671	#region Datastructures
672
673	/// <summary>
674	/// Describes a source
675	/// </summary>
676	public class PropertyData : DependencyObject
677	{
678		#region Properties
679
680		/// <summary>
681		/// Identifies the Name dependency property
682		/// </summary>
683		public static readonly DependencyProperty NameProperty =
684			DependencyProperty.Register("Name", typeof(string),
685			typeof(PropertyData), new UIPropertyMetadata(null));
686
687		/// <summary>
688		/// Gets or sets the property name
689		/// </summary>
690		public string Name
691		{
692			get { return (string)GetValue(NameProperty); }
693			set { SetValue(NameProperty, value); }
694		}
695
696		/// <summary>
697		/// Identifies the Value dependency property
698		/// </summary>
699		public static readonly DependencyProperty ValueProperty =
700			DependencyProperty.Register("Value", typeof(string),
701			typeof(PropertyData), new UIPropertyMetadata(null));
702
703		/// <summary>
704		/// Gets or sets the property value
705		/// </summary>
706		public string Value
707		{
708			get { return (string)GetValue(ValueProperty); }
709			set { SetValue(ValueProperty, value); }
710		}
711
712		/// <summary>
713		/// Gets or sets whether the property has been edited
714		/// </summary>
715		public bool Edited { get; set; }
716
717		#endregion
718	}
719
720	#endregion
721
722	#region Converters
723
724	/// <summary>
725	/// A converter between bool and visibility (visible or hidden)
726	/// </summary>
727	public class BoolToVisibilityConverter : IValueConverter
728	{
729		/// <summary>
730		/// Converts two bool values (<paramref name="value"/> and <paramref name="parameter"/>)
731		/// to a visibility value. If the two bool values are equal it will return Visible,
732		/// if they are not it will return Hidden.
733		/// </summary>
734		/// <param name="value">The bool value</param>
735		/// <param name="targetType">The type of the target (not used)</param>
736		/// <param name="parameter">The string representation of a bool</param>
737		/// <param name="culture">The culture (not used)</param>
738		/// <returns>Visible if value and parameter are equal, otherwise Hidden</returns>
739		public object Convert(object value, Type targetType,
740			object parameter, System.Globalization.CultureInfo culture)
741		{
742			bool param = bool.Parse(parameter as string);
743			bool val = (bool)value;
744
745			return val == param ?
746			  Visibility.Visible : Visibility.Hidden;
747		}
748
749		/// <summary>
750		/// This function is not implemented and will throw an exception if used.
751		/// </summary>
752		/// <param name="value">(not used)</param>
753		/// <param name="targetType">(not used)</param>
754		/// <param name="parameter">(not used)</param>
755		/// <param name="culture">(not used)</param>
756		/// <returns>(nothing)</returns>
757		public object ConvertBack(object value, Type targetType,
758			object parameter, System.Globalization.CultureInfo culture)
759		{
760			throw new NotImplementedException();
761		}
762	}
763
764	#endregion
765}