PageRenderTime 32ms CodeModel.GetById 15ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 1ms

/Application/GUI/Controls/Details.xaml.cs

http://yet-another-music-application.googlecode.com/
C# | 492 lines | 300 code | 71 blank | 121 comment | 39 complexity | 06907485180f5c5b25de761e3dc6becd MD5 | raw file
  1/**
  2 * Details.xaml.cs
  3 * 
  4 * The details pane which shows an image, a title, a description
  5 * and a number of key-value fields.
  6 * It automatically hides fields that cannot be shown and supports
  7 * for in-place edit of certain fields.
  8 * 
  9 * * * * * * * * *
 10 * 
 11 * This code is part of the Stoffi Music Player Project.
 12 * Visit our website at: stoffiplayer.com
 13 *
 14 * This program is free software; you can redistribute it and/or
 15 * modify it under the terms of the GNU General Public License
 16 * as published by the Free Software Foundation; either version
 17 * 3 of the License, or (at your option) any later version.
 18 * 
 19 * See stoffiplayer.com/license for more information.
 20 **/
 21using System;
 22using System.Collections.Generic;
 23using System.Linq;
 24using System.Text;
 25using System.Windows;
 26using System.Windows.Controls;
 27using System.Windows.Data;
 28using System.Windows.Documents;
 29using System.Windows.Input;
 30using System.Windows.Media;
 31using System.Windows.Media.Imaging;
 32using System.Windows.Navigation;
 33using System.Windows.Shapes;
 34using System.Windows.Controls.Primitives;
 35
 36namespace Stoffi
 37{
 38	/// <summary>
 39	/// Details.xaml 的交互逻辑
 40	/// </summary>
 41	public partial class Details : StatusBar
 42	{
 43		#region Members
 44		private List<TextBlock> labels = new List<TextBlock>();
 45		private List<FrameworkElement> fields = new List<FrameworkElement>();
 46		private double cellWidth = 120;
 47		private double labelWidth = 80;
 48		private double cellHeight = 20;
 49		#endregion
 50
 51		#region Properties
 52
 53		/// <summary>
 54		/// The title of the item
 55		/// </summary>
 56		public string Title
 57		{
 58			get { return TitleBlock.Text; }
 59			set { TitleBlock.Text = value; }
 60		}
 61
 62		/// <summary>
 63		/// A short description of the item
 64		/// </summary>
 65		public string Description
 66		{
 67			get { return DescrBlock.Text; }
 68			set { DescrBlock.Text = value; }
 69		}
 70
 71		/// <summary>
 72		/// Sets the thumbnail image
 73		/// </summary>
 74		public ImageSource Image
 75		{
 76			get { return AlbumArt.Source; }
 77			set { AlbumArt.Source = value; }
 78		}
 79
 80		#endregion
 81
 82		#region Constructor
 83		/// <summary>
 84		/// Details Pane
 85		/// </summary>
 86		public Details()
 87		{
 88			U.L(LogLevel.Debug, "DETAILS", "Initialize");
 89			InitializeComponent();
 90			U.L(LogLevel.Debug, "DETAILS", "Initialized");
 91			FieldsGrid.RowDefinitions[0].Height = new GridLength(cellHeight);
 92			FieldsGrid.RowDefinitions[1].Height = new GridLength(cellHeight);
 93			FieldsGrid.ColumnDefinitions[0].Width = new GridLength(labelWidth);
 94			FieldsGrid.ColumnDefinitions[1].Width = new GridLength(cellWidth);
 95
 96			if (System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName == "")
 97				DescrBlock.Foreground = Brushes.Black;
 98			U.L(LogLevel.Debug, "DETAILS", "Created");
 99		}
100		#endregion
101
102		#region Methods
103
104		#region Public
105
106		/// <summary>
107		/// Adds a text field
108		/// </summary>
109		/// <param name="name">The name of the field</param>
110		/// <param name="value">The value of the field</param>
111		/// <param name="editable">Whether the field can be edited</param>
112		public void AddField(string name, string value, bool editable = false)
113		{
114			EditableTextBlock etb = new EditableTextBlock();
115			etb.IsEditable = editable;
116			etb.ClickToEdit = editable;
117			etb.Text = value;
118			etb.VerticalAlignment = System.Windows.VerticalAlignment.Center;
119			etb.Edited += new EditableTextBlockDelegate(Field_Edited);
120			etb.EnteredEditMode += new EventHandler(Field_EnteredEditMode);
121			AddField(name, etb);
122		}
123
124		/// <summary>
125		/// Adds a rating field
126		/// </summary>
127		/// <param name="name">The name of the field</param>
128		/// <param name="i">The rate value (0-10)</param>
129		public void AddField(string name, int i)
130		{
131			// TODO: create rate control
132		}
133
134		/// <summary>
135		/// Adds a field
136		/// </summary>
137		/// <param name="name">The name of the field</param>
138		/// <param name="e">The object representing the value</param>
139		public void AddField(string name, FrameworkElement e)
140		{
141			e.Tag = name;
142
143			int col = (int)Math.Floor((double)fields.Count + 2) / FieldsGrid.RowDefinitions.Count;
144			int row = fields.Count + 2 - col * FieldsGrid.RowDefinitions.Count;
145			col *= 2;
146
147			TextBlock label = new TextBlock();
148			label.Text = name + ':';
149			label.TextAlignment = TextAlignment.Right;
150			label.VerticalAlignment = System.Windows.VerticalAlignment.Center;
151			label.Margin = new Thickness(0, 0, 2, 0);
152			label.Padding = new Thickness(0);
153			if (System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName != "")
154				label.Foreground = new SolidColorBrush(Color.FromRgb(90, 103, 121));
155			label.Tag = name;
156			Grid.SetRow(label, row);
157			Grid.SetColumn(label, col);
158
159			e.Margin = new Thickness(2);
160			e.Tag = name;
161			Grid.SetRow(e, row);
162			Grid.SetColumn(e, col + 1);
163
164			if (col >= FieldsGrid.ColumnDefinitions.Count || row >= FieldsGrid.RowDefinitions.Count)
165			{
166				label.Visibility = System.Windows.Visibility.Collapsed;
167				e.Visibility = System.Windows.Visibility.Collapsed;
168			}
169
170			FieldsGrid.Children.Add(label);
171			labels.Add(label);
172			FieldsGrid.Children.Add(e);
173			fields.Add(e);
174			RefreshGrid();
175		}
176
177		/// <summary>
178		/// Removes a field
179		/// </summary>
180		/// <param name="name">The name of the field to remove</param>
181		public void RemoveField(string name)
182		{
183			for (int i = 0; i < fields.Count; i++)
184			{
185				FrameworkElement e = fields[i];
186				if ((string)e.Tag == name)
187				{
188					FieldsGrid.Children.Remove(e);
189					fields.RemoveAt(i);
190					i--;
191				}
192			}
193			for (int i = 0; i < labels.Count; i++)
194			{
195				FrameworkElement e = fields[i];
196				if ((string)e.Tag == name)
197				{
198					FieldsGrid.Children.Remove(e);
199					labels.RemoveAt(i);
200					i--;
201				}
202			}
203			RefreshGrid();
204		}
205
206		/// <summary>
207		/// Changes the value of a field
208		/// </summary>
209		/// <param name="name">The name of the field</param>
210		/// <param name="value">The new value of the field</param>
211		public void SetField(string name, string value)
212		{
213			foreach (FrameworkElement e in fields)
214			{
215				if (e.Tag as string == name && e is EditableTextBlock)
216					(e as EditableTextBlock).Text = value;
217				else if (e.Tag as string == name && e is TextBlock)
218					(e as TextBlock).Text = value;
219			}
220		}
221
222		/// <summary>
223		/// Removes all fields and resets control
224		/// </summary>
225		public void Clear()
226		{
227			AlbumArt.Visibility = System.Windows.Visibility.Hidden;
228
229			fields.Clear();
230			labels.Clear();
231			FieldsGrid.Children.Clear();
232
233			Title = "";
234			Description = "";
235
236			FieldsGrid.Children.Add(TitleBlock);
237			FieldsGrid.Children.Add(DescrBlock);
238
239			RefreshGrid();
240		}
241
242		#endregion
243
244		#region Private
245
246		/// <summary>
247		/// Refreshes the content inside the grid
248		/// </summary>
249		private void RefreshFields()
250		{
251			int i = 0;
252			for (int col = 0; i < fields.Count && col < FieldsGrid.ColumnDefinitions.Count; col += 2) // double increase
253			{
254			    for (int row = col == 0 ? 2 : 0; i < fields.Count && row < FieldsGrid.RowDefinitions.Count; row++, i++)
255			    {
256			        fields[i].Visibility = System.Windows.Visibility.Visible;
257			        labels[i].Visibility = System.Windows.Visibility.Visible;
258			        Grid.SetColumn(labels[i], col);
259			        Grid.SetRow(labels[i], row);
260			        Grid.SetColumn(fields[i], col + 1);
261			        Grid.SetRow(fields[i], row);
262			    }
263			}
264			while (i < fields.Count)
265			{
266			    fields[i].Visibility = System.Windows.Visibility.Collapsed;
267			    labels[i].Visibility = System.Windows.Visibility.Collapsed;
268			    i++;
269			}
270
271			AlbumArt.Visibility = fields.Count > 0 ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
272		}
273
274		/// <summary>
275		/// Refreshes the grids column and row configuration
276		/// </summary>
277		private void RefreshGrid()
278		{
279			#region Add columns
280
281			int allowed = (int)Math.Floor(RightPart.RenderSize.Width / (cellWidth + labelWidth));
282			int actual = FieldsGrid.ColumnDefinitions.Count / 2;
283
284			if (allowed > actual)
285			{
286				int add = allowed - actual;
287
288				for (int i = 0; i < add; i++)
289				{
290					FieldsGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(labelWidth) });
291					FieldsGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(cellWidth) });
292					RefreshFields();
293				}
294			}
295			#endregion
296
297			#region Remove columns
298			if (actual > allowed)
299			{
300				int remove = actual - allowed;
301				FieldsGrid.ColumnDefinitions.RemoveRange(
302					FieldsGrid.ColumnDefinitions.Count - (remove*2), remove*2);
303			}
304			#endregion
305
306			allowed = (int)Math.Floor(RightPart.RenderSize.Height / cellHeight);
307			actual = FieldsGrid.RowDefinitions.Count;
308
309			#region Add rows
310			if (allowed > actual)
311			{
312				for (int i = 0; i < allowed - actual; i++)
313				{
314					int index = actual + i;
315					double add = allowed;
316					FieldsGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(cellHeight) });
317
318					for (int j = 0; j < FieldsGrid.ColumnDefinitions.Count; j += 2)
319					{
320						TextBlock tb1 = new TextBlock()
321						{
322							Text = "Foo:",
323							Background = Brushes.Blue,
324							Margin = new Thickness(2),
325							Width = labelWidth
326						};
327
328						TextBlock tb2 = new TextBlock()
329						{
330							Text = "Bar",
331							Background = Brushes.Red,
332							Margin = new Thickness(2),
333							Width = cellWidth
334						};
335
336						Grid.SetColumn(tb1, j);
337						Grid.SetColumn(tb2, j + 1);
338
339						Grid.SetRow(tb1, FieldsGrid.RowDefinitions.Count - 1);
340						Grid.SetRow(tb2, FieldsGrid.RowDefinitions.Count - 1);
341					}
342				}
343			}
344			#endregion
345
346			#region Remove rows
347			else if (allowed < actual)
348			{
349				int remove = actual - allowed;
350				FieldsGrid.RowDefinitions.RemoveRange(
351					FieldsGrid.RowDefinitions.Count - remove, remove);
352
353				if (FieldsGrid.RowDefinitions.Count == 0)
354					FieldsGrid.Children.Clear();
355			}
356			#endregion
357
358			RefreshFields();
359		}
360
361		#endregion
362
363		#region Event handlers
364
365		/// <summary>
366		/// Invoked when the size changes.
367		/// Will add or remove rows or columns
368		/// and call Refresh().
369		/// </summary>
370		/// <param name="sender">The sender of the event</param>
371		/// <param name="e">The event data</param>
372		private void Details_SizeChanged(object sender, SizeChangedEventArgs e)
373		{
374			RefreshGrid();
375		}
376
377		/// <summary>
378		/// Invoked when a field has been edited
379		/// </summary>
380		/// <param name="sender">The sender of the event</param>
381		/// <param name="e">The event data</param>
382		private void Field_Edited(object sender, EditableTextBlockEventArgs e)
383		{
384			EditableTextBlock etb = sender as EditableTextBlock;
385			OnFieldEdited(etb.Tag as string, e.NewText);
386		}
387
388		/// <summary>
389		/// Invoked when a field enters edit mode
390		/// </summary>
391		/// <param name="sender">The sender of the event</param>
392		/// <param name="e">The event data</param>
393		private void Field_EnteredEditMode(object sender, EventArgs e)
394		{
395			OnEnteredEditMode(sender);
396		}
397
398		#endregion
399
400		#region Dispatchers
401
402		/// <summary>
403		/// Dispatches the FieldEdited event
404		/// </summary>
405		/// <param name="name">The name of the field</param>
406		/// <param name="value">The new value of the field</param>
407		private void OnFieldEdited(string name, string value)
408		{
409			if (FieldEdited != null)
410				FieldEdited(this, new FieldEditedEventArgs(name, value));
411		}
412
413		/// <summary>
414		/// Dispatches the EnteredEditMode event
415		/// </summary>
416		/// <param name="etb">The object that sent the event</param>
417		private void OnEnteredEditMode(object etb)
418		{
419			if (EnteredEditMode != null)
420				EnteredEditMode(etb, new EventArgs());
421		}
422
423		#endregion
424
425		#endregion
426
427		#region Events
428
429		/// <summary>
430		/// Occurs when a field was edited
431		/// </summary>
432		public event FieldEditedEventHandler FieldEdited;
433
434
435		/// <summary>
436		/// Occurs when the control enters edit mode
437		/// </summary>
438		public event EventHandler EnteredEditMode;
439
440		#endregion
441
442		#region Delegates
443
444		/// <summary>
445		/// Represents the method that will handle the FieldEdited event.
446		/// </summary>
447		/// <param name="sender">The sender of the event</param>
448		/// <param name="e">The event data</param>
449		public delegate void FieldEditedEventHandler(object sender, FieldEditedEventArgs e);
450
451		#endregion
452	}
453
454	#region Event arguments
455
456	/// <summary>
457	/// Provides data for the <see cref="Details.FieldEdited"/> event
458	/// </summary>
459	public class FieldEditedEventArgs : EventArgs
460	{
461		#region Properties
462
463		/// <summary>
464		/// Gets the name of the field
465		/// </summary>
466		public string Field { get; private set; }
467
468		/// <summary>
469		/// Gets the new value of the field
470		/// </summary>
471		public string Value { get; private set; }
472
473		#endregion
474
475		#region Constructor
476
477		/// <summary>
478		/// Initializes a new instance of the <see cref="FieldEditedEventArgs"/> class
479		/// </summary>
480		/// <param name="field">The name of the field</param>
481		/// <param name="value">The new value of the field</param>
482		public FieldEditedEventArgs(string field, string value)
483		{
484			Field = field;
485			Value = value;
486		}
487
488		#endregion
489	}
490
491	#endregion
492}