PageRenderTime 55ms CodeModel.GetById 39ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/Application/GUI/Controls/SearchBox.xaml.cs

http://yet-another-music-application.googlecode.com/
C# | 700 lines | 360 code | 106 blank | 234 comment | 31 complexity | e35be7dc32010aaa0ae2f5fdca883c44 MD5 | raw file
  1/**
  2 * SearchBox.xaml.cs
  3 * 
  4 * The search box.
  5 * 
  6 * * * * * * * * *
  7 * 
  8 * This code is part of the Stoffi Music Player Project.
  9 * Visit our website at: stoffiplayer.com
 10 *
 11 * This program is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU General Public License
 13 * as published by the Free Software Foundation; either version
 14 * 3 of the License, or (at your option) any later version.
 15 * 
 16 * See stoffiplayer.com/license for more information.
 17 **/
 18
 19using System;
 20using System.Collections.Generic;
 21using System.Linq;
 22using System.Text;
 23using System.Windows;
 24using System.Windows.Controls;
 25using System.Windows.Data;
 26using System.Windows.Documents;
 27using System.Windows.Input;
 28using System.Windows.Media;
 29using System.Windows.Media.Imaging;
 30using System.Windows.Navigation;
 31using System.Windows.Shapes;
 32using System.Windows.Threading;
 33
 34namespace Stoffi
 35{
 36	/// <summary>
 37	/// A Windows Explorer styled search box
 38	/// </summary>
 39	public partial class SearchBox : UserControl
 40	{
 41		#region Members
 42
 43		private bool isActive = false;
 44		private bool changingActiveStatus = false;
 45		private DispatcherTimer delay = new DispatcherTimer();
 46
 47		#endregion
 48
 49		#region Properties
 50
 51		/// <summary>
 52		/// Gets or sets the current state of the search box
 53		/// </summary>
 54		public bool IsActive
 55		{
 56			get { return isActive; }
 57			set
 58			{
 59				changingActiveStatus = true;
 60				if (value)
 61				{
 62					Box.Text = "";
 63					Box.FontStyle = System.Windows.FontStyles.Normal;
 64					Box.Foreground = System.Windows.Media.Brushes.Black;
 65					SearchBackground.Background = System.Windows.Media.Brushes.White;
 66					Button.Style = (Style)FindResource("SearchClearButtonStyle");
 67					Box.Focus();
 68				}
 69				else
 70				{
 71					Box.Text = U.T("PlaybackSearch", "Text");
 72					Box.FontStyle = System.Windows.FontStyles.Italic;
 73					Box.Foreground = new SolidColorBrush(Color.FromRgb(0x79, 0x7a, 0x7a));
 74					SearchBackground.Background = new SolidColorBrush(Color.FromArgb(0xC0, 0xFF, 0xFF, 0xFF));
 75					Button.Style = (Style)FindResource("SearchButtonStyle");
 76				}
 77				changingActiveStatus = false;
 78				isActive = value;
 79				DispatchActiveStateChangedEvent(value, Text);
 80			}
 81		}
 82
 83		/// <summary>
 84		/// Get or sets the search text.
 85		/// An empty string if the search box is not active.
 86		/// </summary>
 87		public String Text
 88		{
 89			get
 90			{
 91				if (IsActive)
 92					return Box.Text;
 93				else
 94					return "";
 95			}
 96			set { Box.Text = value; }
 97		}
 98
 99		/// <summary>
100		/// Gets or sets the position of the cursor in the text box.
101		/// </summary>
102		public int Position
103		{
104			get { return Box.SelectionStart; }
105			set { Box.SelectionStart = value; }
106		}
107
108		#endregion
109
110		#region Constructor
111
112		/// <summary>
113		/// Create a search box
114		/// </summary>
115		public SearchBox()
116		{
117			U.L(LogLevel.Debug, "SEARCH BOX", "Initialize");
118			InitializeComponent();
119			U.L(LogLevel.Debug, "SEARCH BOX", "Initialized");
120			delay.Interval = new TimeSpan(0, 0, 0, 0, 500);
121			delay.Tick += new EventHandler(Delay_Tick);
122		}
123
124		#endregion
125
126		#region Methods
127
128		#region Public
129
130		/// <summary>
131		/// Add a new playlist to the search box's context menu
132		/// </summary>
133		/// <param name="playlist">The playlist to be added</param>
134		public void AddPlaylist(PlaylistData playlist)
135		{
136			// create the menu item in "Add to Playlist" in list
137			MenuItem ListAddMenu = new MenuItem();
138			ListAddMenu.Header = playlist.Name;
139			ListAddMenu.Click += AddToPlaylist_Clicked;
140			Menu_Add.Items.Insert(Menu_Add.Items.Count - 1, ListAddMenu);
141
142			// create the menu item in "Remove from Playlist" in list
143			MenuItem ListDelMenu = new MenuItem();
144			ListDelMenu.Header = playlist.Name;
145			ListDelMenu.Click += RemoveFromPlaylist_Clicked;
146			Menu_Remove.Items.Insert(Menu_Remove.Items.Count, ListDelMenu);
147
148			Menu_Remove.IsEnabled = true;
149		}
150
151		/// <summary>
152		/// Remove a playlist from the search box's context menu
153		/// </summary>
154		/// <param name="playlist">The playlist to be removed</param>
155		public void RemovePlaylist(PlaylistData playlist)
156		{
157			// remove from "add to playlist" menu in list
158			List<MenuItem> menu_items_to_remove = new List<MenuItem>();
159			foreach (MenuItem item in Menu_Add.Items)
160			{
161				if (item.Header.ToString() == playlist.Name)
162					menu_items_to_remove.Add(item);
163			}
164			foreach (MenuItem item in menu_items_to_remove)
165				Menu_Add.Items.Remove(item);
166
167			// remove from "remove from playlist" menu in list
168			menu_items_to_remove.Clear();
169			foreach (MenuItem item in Menu_Remove.Items)
170			{
171				if (item.Header.ToString() == playlist.Name)
172					menu_items_to_remove.Add(item);
173			}
174			foreach (MenuItem item in menu_items_to_remove)
175				Menu_Remove.Items.Remove(item);
176
177
178			if (SettingsManager.Playlists.Count <= 0)
179				Menu_Remove.IsEnabled = false;
180		}
181
182		/// <summary>
183		/// Rename a playlist in the search box's context menu
184		/// </summary>
185		/// <param name="oldName">The old name of the playlist</param>
186		/// <param name="newName">The new name of the playlist</param>
187		public void RenamePlaylist(String oldName, String newName)
188		{
189			foreach (MenuItem item in Menu_Add.Items)
190				if (item.Header.ToString() == oldName)
191					item.Header = newName;
192
193			foreach (MenuItem item in Menu_Remove.Items)
194				if (item.Header.ToString() == oldName)
195					item.Header = newName;
196		}
197
198		/// <summary>
199		/// 
200		/// </summary>
201		public void Clear()
202		{
203			Box.Text = "";
204			IsActive = false;
205			Box.Text = U.T("PlaybackSearch", "Text");
206			Box.FontStyle = System.Windows.FontStyles.Italic;
207			Box.Foreground = new SolidColorBrush(Color.FromRgb(0x79, 0x7a, 0x7a));
208			SearchBackground.Background = new SolidColorBrush(Color.FromArgb(0xC0, 0xFF, 0xFF, 0xFF));
209			Box.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
210			Button.Style = (Style)FindResource("SearchButtonStyle");
211			DispatchClearedEvent();
212		}
213
214		#endregion
215
216		#region Event handlers
217
218		/// <summary>
219		/// 
220		/// </summary>
221		/// <param name="sender"></param>
222		/// <param name="e"></param>
223		private void Button_Clicked(object sender, RoutedEventArgs e)
224		{
225			Clear();
226		}
227
228		/// <summary>
229		/// 
230		/// </summary>
231		/// <param name="sender"></param>
232		/// <param name="e"></param>
233		private void AddToNew_Clicked(object sender, RoutedEventArgs e)
234		{
235			DispatchAddToNewClickedEvent();
236		}
237
238		/// <summary>
239		/// 
240		/// </summary>
241		/// <param name="sender"></param>
242		/// <param name="e"></param>
243		private void AddToPlaylist_Clicked(object sender, RoutedEventArgs e)
244		{
245			if (sender is MenuItem)
246			{
247				MenuItem item = sender as MenuItem;
248				String name = item.Header.ToString();
249				DispatchAddToPlaylistClickedEvent(name);
250			}
251		}
252
253		/// <summary>
254		/// 
255		/// </summary>
256		/// <param name="sender"></param>
257		/// <param name="e"></param>
258		private void RemoveFromPlaylist_Clicked(object sender, RoutedEventArgs e)
259		{
260			if (sender is MenuItem)
261			{
262				MenuItem item = sender as MenuItem;
263				String name = item.Header.ToString();
264				DispatchRemoveFromPlaylistClickedEvent(name);
265			}
266		}
267
268		/// <summary>
269		/// 
270		/// </summary>
271		/// <param name="sender"></param>
272		/// <param name="e"></param>
273		private void Box_GotFocus(object sender, RoutedEventArgs e)
274		{
275			U.ListenForShortcut = false;
276			if (Box.Text == U.T("PlaybackSearch", "Text"))
277				IsActive = true;
278			else
279				Box.SelectAll();
280		}
281
282		/// <summary>
283		/// 
284		/// </summary>
285		/// <param name="sender"></param>
286		/// <param name="e"></param>
287		private void Box_LostFocus(object sender, RoutedEventArgs e)
288		{
289			U.ListenForShortcut = true;
290			if (Box.Text == "")
291				IsActive = false;
292		}
293
294		/// <summary>
295		/// 
296		/// </summary>
297		/// <param name="sender"></param>
298		/// <param name="e"></param>
299		private void Box_TextChanged(object sender, TextChangedEventArgs e)
300		{
301			if (IsActive && !changingActiveStatus)
302			{
303				delay.Stop();
304				delay.Start();
305			}
306		}
307
308		/// <summary>
309		/// Called after a search has been performed.
310		/// </summary>
311		/// <param name="sender">The sender of the event</param>
312		/// <param name="e">The event arguments</param>
313		private void Delay_Tick(object sender, EventArgs e)
314		{
315			delay.Stop();
316			DispatchTextChangedEvent(IsActive, Text);
317		}
318		
319		#endregion
320
321		#endregion
322
323		#region Events
324
325		/// <summary>
326		/// Invoked when the active status of the search box changes
327		/// For example when it receives focus
328		/// </summary>
329		public event SearchBoxDelegate ActiveStateChanged;
330
331		/// <summary>
332		/// TODO
333		/// </summary>
334		public event SearchBoxClearedDelegate Cleared;
335
336		/// <summary>
337		/// TODO
338		/// </summary>
339		public event SearchBoxAddToNewDelegate AddToNewClicked;
340
341		/// <summary>
342		/// TODO
343		/// </summary>
344		public event SearchBoxAddDelegate AddClicked;
345
346		/// <summary>
347		/// TODO
348		/// </summary>
349		public event SearchBoxRemoveDelegate RemoveClicked;
350
351		/// <summary>
352		/// TODO
353		/// </summary>
354		public event SearchBoxDelegate TextChanged;
355
356		/// <summary>
357		/// 
358		/// </summary>
359		/// <param name="eventHandler"></param>
360		public void SubscribeActiveStateChanged(SearchBoxDelegate eventHandler)
361		{
362			ActiveStateChanged += eventHandler;
363		}
364
365		/// <summary>
366		/// 
367		/// </summary>
368		/// <param name="eventHandler"></param>
369		public void SubscribeTextChanged(SearchBoxDelegate eventHandler)
370		{
371			TextChanged += eventHandler;
372		}
373
374		/// <summary>
375		/// 
376		/// </summary>
377		/// <param name="eventHandler"></param>
378		public void SubscribeClearClicked(SearchBoxClearedDelegate eventHandler)
379		{
380			Cleared += eventHandler;
381		}
382
383		/// <summary>
384		/// 
385		/// </summary>
386		/// <param name="eventHandler"></param>
387		public void SubscribeAddToNewClicked(SearchBoxAddToNewDelegate eventHandler)
388		{
389			AddToNewClicked += eventHandler;
390		}
391
392		/// <summary>
393		/// 
394		/// </summary>
395		/// <param name="eventHandler"></param>
396		public void SubscribeAddClicked(SearchBoxAddDelegate eventHandler)
397		{
398			AddClicked += eventHandler;
399		}
400
401		/// <summary>
402		/// 
403		/// </summary>
404		/// <param name="eventHandler"></param>
405		public void SubscribeRemoveClicked(SearchBoxRemoveDelegate eventHandler)
406		{
407			RemoveClicked += eventHandler;
408		}
409
410		/// <summary>
411		/// 
412		/// </summary>
413		/// <param name="eventHandler"></param>
414		public void UnsubsribeActiveStateChanged(SearchBoxDelegate eventHandler)
415		{
416			ActiveStateChanged -= eventHandler;
417		}
418
419		/// <summary>
420		/// 
421		/// </summary>
422		/// <param name="eventHandler"></param>
423		public void UnsubscribeTextChanged(SearchBoxDelegate eventHandler)
424		{
425			TextChanged -= eventHandler;
426		}
427
428		/// <summary>
429		/// 
430		/// </summary>
431		/// <param name="eventHandler"></param>
432		public void UnsubscribeClearClicked(SearchBoxClearedDelegate eventHandler)
433		{
434			Cleared -= eventHandler;
435		}
436
437		/// <summary>
438		/// 
439		/// </summary>
440		/// <param name="eventHandler"></param>
441		public void UnsubscribeAddToNewClicked(SearchBoxAddToNewDelegate eventHandler)
442		{
443			AddToNewClicked -= eventHandler;
444		}
445
446		/// <summary>
447		/// 
448		/// </summary>
449		/// <param name="eventHandler"></param>
450		public void UnsubscribeAddClicked(SearchBoxAddDelegate eventHandler)
451		{
452			AddClicked -= eventHandler;
453		}
454
455		/// <summary>
456		/// 
457		/// </summary>
458		/// <param name="eventHandler"></param>
459		public void UnsubscribeRemoveClicked(SearchBoxRemoveDelegate eventHandler)
460		{
461			RemoveClicked -= eventHandler;
462		}
463
464		/// <summary>
465		/// 
466		/// </summary>
467		/// <param name="active"></param>
468		/// <param name="text"></param>
469		public void DispatchActiveStateChangedEvent(bool active, string text)
470		{
471			if (ActiveStateChanged != null)
472			{
473				ActiveStateChanged(new SearchBoxEventArgs(active, text));
474			}
475		}
476
477		/// <summary>
478		/// 
479		/// </summary>
480		public void DispatchClearedEvent()
481		{
482			if (Cleared != null)
483			{
484				Cleared();
485			}
486		}
487
488		/// <summary>
489		/// 
490		/// </summary>
491		public void DispatchAddToNewClickedEvent()
492		{
493			if (AddToNewClicked != null)
494			{
495				AddToNewClicked(new SearchBoxAddToNewEventArgs());
496			}
497		}
498
499		/// <summary>
500		/// 
501		/// </summary>
502		/// <param name="name"></param>
503		public void DispatchAddToPlaylistClickedEvent(string name)
504		{
505			if (AddClicked != null)
506			{
507				AddClicked(new SearchBoxAddEventArgs(name));
508			}
509		}
510
511		/// <summary>
512		/// 
513		/// </summary>
514		/// <param name="name"></param>
515		public void DispatchRemoveFromPlaylistClickedEvent(string name)
516		{
517			if (RemoveClicked != null)
518			{
519				RemoveClicked(new SearchBoxRemoveEventArgs(name));
520			}
521		}
522
523		/// <summary>
524		/// 
525		/// </summary>
526		/// <param name="active"></param>
527		/// <param name="text"></param>
528		public void DispatchTextChangedEvent(bool active, string text)
529		{
530			if (TextChanged != null)
531			{
532				TextChanged(new SearchBoxEventArgs(active, text));
533			}
534		}
535
536		#endregion
537	}
538
539	/// <summary>
540	/// Provides data for a search box event
541	/// </summary>
542	public class SearchBoxEventArgs : EventArgs
543	{
544		#region Members
545
546		private bool isActive;
547		private string text;
548
549		#endregion
550
551		#region Properties
552
553		/// <summary>
554		/// 
555		/// </summary>
556		public bool IsActive { get { return isActive; } }
557
558		/// <summary>
559		/// 
560		/// </summary>
561		public string Text { get { return text; } }
562
563		#endregion
564
565		#region Methods
566
567		#region Public
568
569		public SearchBoxEventArgs(bool active, string txt)
570		{
571			isActive = active;
572			text = txt;
573		}
574
575		#endregion
576
577		#endregion
578	}
579
580	/// <summary>
581	/// Provides data for the <see cref="SearchBox.AddClicked"/> event
582	/// </summary>
583	public class SearchBoxAddEventArgs : EventArgs
584	{
585		#region Members
586
587		private string playlistName;
588
589		#endregion
590
591		#region Properties
592
593		/// <summary>
594		/// 
595		/// </summary>
596		public string PlaylistName { get { return playlistName; } }
597
598		#endregion
599
600		#region Methods
601
602		#region Public
603
604		/// <summary>
605		/// 
606		/// </summary>
607		/// <param name="name"></param>
608		public SearchBoxAddEventArgs(string name)
609		{
610			playlistName = name;
611		}
612
613		#endregion
614
615		#endregion
616	}
617
618	/// <summary>
619	/// Provides data for the <see cref="SearchBox.RemoveClicked"/> event
620	/// </summary>
621	public class SearchBoxRemoveEventArgs : EventArgs
622	{
623		#region Members
624
625		private string playlistName;
626
627		#endregion
628
629		#region Properties
630
631		/// <summary>
632		/// 
633		/// </summary>
634		public string PlaylistName { get { return playlistName; } }
635
636		#endregion
637
638		#region Methods
639
640		#region Public
641
642		public SearchBoxRemoveEventArgs(string name)
643		{
644			playlistName = name;
645		}
646
647		#endregion
648
649		#endregion
650	}
651
652	/// <summary>
653	/// Provides data for the <see cref="SearchBox.AddToNewClicked"/> event
654	/// </summary>
655	public class SearchBoxAddToNewEventArgs : EventArgs
656	{
657		#region Constructor
658
659		/// <summary>
660		/// 
661		/// </summary>
662		public SearchBoxAddToNewEventArgs()
663		{ }
664
665		#endregion
666	}
667
668	#region Delegates
669
670	/// <summary>
671	/// 
672	/// </summary>
673	/// <param name="e"></param>
674	public delegate void SearchBoxDelegate(SearchBoxEventArgs e);
675
676	/// <summary>
677	/// 
678	/// </summary>
679	/// <param name="e"></param>
680	public delegate void SearchBoxAddDelegate(SearchBoxAddEventArgs e);
681
682	/// <summary>
683	/// 
684	/// </summary>
685	/// <param name="e"></param>
686	public delegate void SearchBoxRemoveDelegate(SearchBoxRemoveEventArgs e);
687
688	/// <summary>
689	/// 
690	/// </summary>
691	/// <param name="e"></param>
692	public delegate void SearchBoxAddToNewDelegate(SearchBoxAddToNewEventArgs e);
693
694	/// <summary>
695	/// 
696	/// </summary>
697	public delegate void SearchBoxClearedDelegate();
698
699	#endregion
700}