PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/PSLib/CSharp/WOW Developing/LuaEditor2/QuickZip.UserControls/Components/SelectionHelper/SelectionHelper.cs

http://pslib.googlecode.com/
C# | 496 lines | 402 code | 93 blank | 1 comment | 79 complexity | 823148d7127bb18dbfc8b462eb81878e MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Documents;
  8. using System.Windows.Input;
  9. using System.Diagnostics;
  10. using System.Windows.Controls.Primitives;
  11. using System.Windows.Media;
  12. using System.ComponentModel;
  13. using System.Windows.Threading;
  14. namespace QuickZip.UserControls
  15. {
  16. public static class SelectionHelper
  17. {
  18. #region Attached Properties
  19. public static DependencyProperty EnableSelectionProperty =
  20. DependencyProperty.RegisterAttached("EnableSelection", typeof(bool), typeof(SelectionHelper),
  21. new PropertyMetadata(OnEnableSelectionpChanged));
  22. public static bool GetEnableSelection(DependencyObject target)
  23. {
  24. return (bool)target.GetValue(EnableSelectionProperty);
  25. }
  26. public static void SetEnableSelection(DependencyObject target, bool value)
  27. {
  28. target.SetValue(EnableSelectionProperty, value);
  29. }
  30. private static DependencyProperty LastScrollContentPresenterProperty =
  31. DependencyProperty.RegisterAttached("LastScrollContentPresenter", typeof(ScrollContentPresenter), typeof(SelectionHelper));
  32. public static ScrollContentPresenter GetLastScrollContentPresenter(DependencyObject target)
  33. {
  34. return (ScrollContentPresenter)target.GetValue(LastScrollContentPresenterProperty);
  35. }
  36. public static void SetLastScrollContentPresenter(DependencyObject target, ScrollContentPresenter value)
  37. {
  38. target.SetValue(LastScrollContentPresenterProperty, value);
  39. }
  40. private static DependencyProperty SelectionAdornerProperty =
  41. DependencyProperty.RegisterAttached("SelectionAdorner", typeof(SelectionAdorner), typeof(SelectionHelper));
  42. public static SelectionAdorner GetSelectionAdorner(DependencyObject target)
  43. {
  44. return (SelectionAdorner)target.GetValue(SelectionAdornerProperty);
  45. }
  46. public static void SetSelectionAdorner(DependencyObject target, SelectionAdorner value)
  47. {
  48. target.SetValue(SelectionAdornerProperty, value);
  49. }
  50. private static DependencyProperty StartScrollbarPositionProperty =
  51. DependencyProperty.RegisterAttached("StartScrollbarPosition", typeof(Point), typeof(SelectionHelper));
  52. public static Point GetStartScrollbarPosition(DependencyObject target)
  53. {
  54. return (Point)target.GetValue(StartScrollbarPositionProperty);
  55. }
  56. public static void SetStartScrollbarPosition(DependencyObject target, Point value)
  57. {
  58. target.SetValue(StartScrollbarPositionProperty, value);
  59. }
  60. private static DependencyProperty StartPositionProperty =
  61. DependencyProperty.RegisterAttached("StartPosition", typeof(Point), typeof(SelectionHelper));
  62. public static Point GetStartPosition(DependencyObject target)
  63. {
  64. return (Point)target.GetValue(StartPositionProperty);
  65. }
  66. public static void SetStartPosition(DependencyObject target, Point value)
  67. {
  68. target.SetValue(StartPositionProperty, value);
  69. }
  70. private static DependencyProperty IsDraggingProperty =
  71. DependencyProperty.RegisterAttached("IsDragging", typeof(bool), typeof(SelectionHelper), new PropertyMetadata(false));
  72. public static bool GetIsDragging(DependencyObject target)
  73. {
  74. return (bool)target.GetValue(IsDraggingProperty);
  75. }
  76. public static bool GetIsDragging(ListView sender)
  77. {
  78. ItemsPresenter ip = UITools.FindVisualChild<ItemsPresenter>(sender);
  79. ScrollContentPresenter p = UITools.FindAncestor<ScrollContentPresenter>(ip);
  80. return GetIsDragging(p);
  81. }
  82. public static void SetIsDragging(DependencyObject target, bool value)
  83. {
  84. target.SetValue(IsDraggingProperty, value);
  85. }
  86. public static void OnEnableSelectionpChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
  87. {
  88. if (s is ListView)
  89. {
  90. ListView control = s as ListView;
  91. var OnScrollChange = (RoutedEventHandler)delegate(object sender, RoutedEventArgs args)
  92. {
  93. ItemsPresenter ip = UITools.FindVisualChild<ItemsPresenter>(sender as ListView);
  94. ScrollContentPresenter p = UITools.FindAncestor<ScrollContentPresenter>(ip);
  95. if (GetIsDragging(p) && Mouse.LeftButton == MouseButtonState.Pressed)
  96. UpdatePosition(p, true);
  97. };
  98. var OnMouseDown = (RoutedEventHandler)delegate(object sender, RoutedEventArgs args)
  99. {
  100. (sender as ListView).SelectedItems.Clear();
  101. };
  102. var OnSizeChanged = (RoutedEventHandler)delegate(object sender, RoutedEventArgs args)
  103. {
  104. ItemsPresenter ip = UITools.FindVisualChild<ItemsPresenter>(sender as ListView);
  105. ScrollContentPresenter p = UITools.FindAncestor<ScrollContentPresenter>(ip);
  106. EndDragging(p);
  107. };
  108. Action unloadAdorner = () =>
  109. {
  110. ScrollContentPresenter p = GetLastScrollContentPresenter(control);
  111. if (p != null)
  112. {
  113. SelectionAdorner _adorner = GetSelectionAdorner(p);
  114. if (AdornerLayer.GetAdornerLayer(p) != null)
  115. AdornerLayer.GetAdornerLayer(p).Remove(_adorner);
  116. control.MouseUp -= new MouseButtonEventHandler(OnMouseUp);
  117. control.MouseMove -= new MouseEventHandler(OnMouseMove);
  118. _adorner.PreviewMouseDown -= new MouseButtonEventHandler(OnPreviewMouseDown);
  119. _adorner.MouseMove -= new MouseEventHandler(OnMouseMove);
  120. _adorner.MouseUp -= new MouseButtonEventHandler(OnMouseUp);
  121. control.RemoveHandler(ListView.SizeChangedEvent, OnSizeChanged);
  122. SetSelectionAdorner(p, null);
  123. }
  124. };
  125. Action attachAdorner = () =>
  126. {
  127. unloadAdorner();
  128. ItemsPresenter ip = UITools.FindVisualChild<ItemsPresenter>(control);
  129. ScrollContentPresenter p = UITools.FindAncestor<ScrollContentPresenter>(ip);
  130. if (p != null)
  131. {
  132. SelectionAdorner _adorner = new SelectionAdorner(p);
  133. SetSelectionAdorner(p, _adorner);
  134. AdornerLayer.GetAdornerLayer(p).Add(_adorner);
  135. control.PreviewMouseDown += new MouseButtonEventHandler(OnPreviewMouseDown);
  136. control.MouseUp += new MouseButtonEventHandler(OnMouseUp);
  137. control.MouseMove += new MouseEventHandler(OnMouseMove);
  138. _adorner.PreviewMouseDown += new MouseButtonEventHandler(OnPreviewMouseDown);
  139. _adorner.MouseMove += new MouseEventHandler(OnMouseMove);
  140. _adorner.MouseUp += new MouseButtonEventHandler(OnMouseUp);
  141. control.AddHandler(ListView.SizeChangedEvent, OnSizeChanged);
  142. SetLastScrollContentPresenter(control, p);
  143. }
  144. };
  145. if ((bool)e.NewValue == true)
  146. {
  147. if (control.IsLoaded)
  148. attachAdorner();
  149. else
  150. control.Loaded += delegate { attachAdorner(); };
  151. control.AddHandler(ScrollViewer.ScrollChangedEvent, OnScrollChange);
  152. control.AddHandler(ListView.MouseDownEvent, OnMouseDown);
  153. //Monitor view change, and reattach handlers.
  154. DependencyPropertyDescriptor viewDescriptor = DependencyPropertyDescriptor.FromProperty(ListView.ViewProperty, typeof(ListView));
  155. viewDescriptor.AddValueChanged
  156. (control, delegate
  157. {
  158. control.Dispatcher.BeginInvoke(DispatcherPriority.Input, attachAdorner);
  159. });
  160. }
  161. else //If EnableSelection = False
  162. {
  163. unloadAdorner();
  164. control.RemoveHandler(ScrollViewer.ScrollChangedEvent, OnScrollChange);
  165. control.RemoveHandler(ListView.MouseDownEvent, OnMouseDown);
  166. SetSelectionAdorner(control, null);
  167. }
  168. }
  169. }
  170. #endregion
  171. #region Methods
  172. static ListViewItem getSelectedItem(ScrollContentPresenter lvSender, Point position)
  173. {
  174. HitTestResult r = VisualTreeHelper.HitTest(lvSender, position);
  175. if (r == null) return null;
  176. DependencyObject obj = r.VisualHit;
  177. while (!(obj is ListView) && (obj != null))
  178. {
  179. obj = VisualTreeHelper.GetParent(obj);
  180. if (obj is ListViewItem)
  181. return obj as ListViewItem;
  182. }
  183. return null;
  184. }
  185. static Point GetScrollbarPosition(ScrollContentPresenter p)
  186. {
  187. ScrollViewer scrollViewer = UITools.FindAncestor<ScrollViewer>(p);
  188. return new Point(p.ActualWidth / scrollViewer.ViewportWidth * scrollViewer.HorizontalOffset,
  189. p.ActualHeight / scrollViewer.ViewportHeight * scrollViewer.VerticalOffset);
  190. }
  191. static void BeginDragging(ScrollContentPresenter p)
  192. {
  193. SetStartScrollbarPosition(p, GetScrollbarPosition(p));
  194. SetStartPosition(p, Mouse.GetPosition(p));
  195. SetIsDragging(p, true);
  196. }
  197. internal static object PositionCheck(DependencyObject sender, object value)
  198. {
  199. if (value is Point)
  200. {
  201. Point ptValue = (Point)value;
  202. SelectionAdorner adorner = sender as SelectionAdorner;
  203. ptValue.X = Math.Max(ptValue.X, 0);
  204. ptValue.X = Math.Min(ptValue.X, adorner.ActualWidth);
  205. ptValue.Y = Math.Max(ptValue.Y, 0);
  206. ptValue.Y = Math.Min(ptValue.Y, adorner.ActualHeight);
  207. return ptValue;
  208. }
  209. return value;
  210. }
  211. static void UpdateSelectedItems(ListView lvControl, IList<object> newList)
  212. {
  213. List<object> addList = new List<object>();
  214. List<object> removeList = new List<object>(lvControl.SelectedItems as IList<object>);
  215. foreach (object obj in newList)
  216. if (removeList.Contains(obj))
  217. removeList.Remove(obj);
  218. else addList.Add(obj);
  219. foreach (object obj in removeList)
  220. lvControl.SelectedItems.Remove(obj);
  221. foreach (object obj in addList)
  222. lvControl.SelectedItems.Add(obj);
  223. }
  224. static void HighlightItems(ListView lvControl, IList<int> newList)
  225. {
  226. for (int i = 0; i < lvControl.Items.Count; i++)
  227. {
  228. ListViewItem item = lvControl.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;
  229. if (item != null)
  230. SetIsDragging(item, newList.Contains(i));
  231. }
  232. }
  233. static void UnhighlightItems(ListView lvControl)
  234. {
  235. for (int i = 0; i < lvControl.Items.Count; i++)
  236. {
  237. ListViewItem item = lvControl.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;
  238. if (item != null)
  239. SetIsDragging(item, false);
  240. }
  241. }
  242. static void UpdateSelection(ScrollContentPresenter p, Rect selectionBounds, bool highlightOnly)
  243. {
  244. ListView lvControl = UITools.FindAncestor<ListView>(p);
  245. if (lvControl != null)
  246. {
  247. IChildInfo icInfo = UITools.FindVisualChild<Panel>(p) as IChildInfo;
  248. List<object> newList = new List<object>();
  249. List<int> newIntList = new List<int>();
  250. if (icInfo != null)
  251. {
  252. for (int i = 0; i < lvControl.Items.Count; i++)
  253. if (icInfo.GetChildRect(i).IntersectsWith(selectionBounds))
  254. {
  255. newList.Add(lvControl.Items[i]);
  256. newIntList.Add(i);
  257. }
  258. }
  259. else
  260. if (lvControl.View is GridView)
  261. {
  262. Point curPos = (Point)PositionCheck(GetSelectionAdorner(p), Mouse.GetPosition(p));
  263. if (_firstSelectedItem == null)
  264. _firstSelectedItem = getSelectedItem(p, curPos);
  265. ListViewItem curSelectedItem = getSelectedItem(p, curPos);
  266. if (_firstSelectedItem != null && curSelectedItem != null)
  267. {
  268. int startIdx = lvControl.ItemContainerGenerator.IndexFromContainer(_firstSelectedItem);
  269. int endIdx = lvControl.ItemContainerGenerator.IndexFromContainer(curSelectedItem);
  270. for (int i = Math.Min(startIdx, endIdx); i <= Math.Max(startIdx, endIdx); i++)
  271. {
  272. newList.Add(lvControl.Items[i]);
  273. newIntList.Add(i);
  274. }
  275. }
  276. }
  277. if (highlightOnly)
  278. HighlightItems(lvControl, newIntList);
  279. else
  280. {
  281. UnhighlightItems(lvControl);
  282. UpdateSelectedItems(lvControl, newList);
  283. }
  284. }
  285. }
  286. static void UpdatePosition(ScrollContentPresenter p, bool highlightOnly)
  287. {
  288. ScrollViewer scrollViewer = UITools.FindAncestor<ScrollViewer>(p);
  289. SelectionAdorner _adorner = GetSelectionAdorner(p);
  290. if (GetIsDragging(p))
  291. {
  292. Point startScrollbarPosition = GetStartScrollbarPosition(p);
  293. Point curScrollbarPosition = GetScrollbarPosition(p);
  294. Point startPosition = GetStartPosition(p);
  295. Point curPosition = Mouse.GetPosition(p);
  296. if (!_adorner.IsSelecting)
  297. {
  298. if (Math.Abs(startPosition.X - curPosition.X) > SystemParameters.MinimumHorizontalDragDistance ||
  299. Math.Abs(startPosition.Y - curPosition.Y) > SystemParameters.MinimumVerticalDragDistance)
  300. {
  301. _adorner.IsSelecting = true;
  302. Mouse.Capture(p);
  303. }
  304. }
  305. else
  306. {
  307. Vector offset = Point.Subtract(startScrollbarPosition, curScrollbarPosition);
  308. _adorner.StartPosition = Point.Add(startPosition, offset);
  309. _adorner.EndPosition = curPosition;
  310. UpdateSelection(p, new Rect(
  311. new Point(startPosition.X + startScrollbarPosition.X, startPosition.Y + startScrollbarPosition.Y),
  312. new Point(curPosition.X + curScrollbarPosition.X, curPosition.Y + curScrollbarPosition.Y)), highlightOnly);
  313. }
  314. }
  315. }
  316. static void EndDragging(ScrollContentPresenter p)
  317. {
  318. SelectionAdorner _adorner = GetSelectionAdorner(p);
  319. if (_adorner.IsSelecting)
  320. {
  321. UpdatePosition(p, false);
  322. _adorner.IsSelecting = false;
  323. SetIsDragging(p, false);
  324. }
  325. }
  326. static bool _itemAlreadySelected = false;
  327. static ListViewItem _itemUnderMouse = null;
  328. static ListViewItem _firstSelectedItem = null;
  329. static ScrollContentPresenter getScrollContentPresenter(object sender)
  330. {
  331. if (sender is ListView)
  332. {
  333. ItemsPresenter ip = UITools.FindVisualChild<ItemsPresenter>(sender as ListView);
  334. return UITools.FindAncestor<ScrollContentPresenter>(ip);
  335. }
  336. else
  337. if (sender is SelectionAdorner)
  338. return (ScrollContentPresenter)((SelectionAdorner)sender).AdornedElement;
  339. else return (ScrollContentPresenter)sender;
  340. }
  341. static void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
  342. {
  343. bool isOverScrollBar = UITools.FindAncestor<ScrollBar>(e.OriginalSource as DependencyObject) != null;
  344. bool spButtonPressed = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift) ||
  345. Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
  346. ScrollContentPresenter p = getScrollContentPresenter(sender);
  347. _itemUnderMouse = getSelectedItem(p, e.GetPosition(p));
  348. if (!spButtonPressed && !isOverScrollBar)
  349. {
  350. _firstSelectedItem = _itemUnderMouse;
  351. _itemAlreadySelected = (_itemUnderMouse != null && _itemUnderMouse.IsSelected);
  352. if (!_itemAlreadySelected && e.ClickCount == 1)
  353. {
  354. BeginDragging(p);
  355. e.Handled = true;
  356. }
  357. }
  358. else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
  359. {
  360. ListView lvSender = UITools.FindAncestor<ListView>(sender as DependencyObject);
  361. int startIdx = lvSender.SelectedIndex;
  362. int endIdx = lvSender.ItemContainerGenerator.IndexFromContainer(_itemUnderMouse);
  363. if (startIdx != -1 && endIdx != -1)
  364. {
  365. lvSender.SelectedItems.Clear();
  366. for (int i = Math.Min(startIdx, endIdx); i <= Math.Max(startIdx, endIdx); i++)
  367. lvSender.SelectedItems.Add(lvSender.Items[i]);
  368. e.Handled = true;
  369. }
  370. }
  371. }
  372. static void OnMouseMove(object sender, MouseEventArgs e)
  373. {
  374. ScrollContentPresenter p = getScrollContentPresenter(sender);
  375. if (GetIsDragging(p))
  376. if (e.LeftButton == MouseButtonState.Pressed)
  377. UpdatePosition(p, true);
  378. }
  379. static void OnMouseUp(object sender, MouseButtonEventArgs e)
  380. {
  381. ScrollContentPresenter p = getScrollContentPresenter(sender);
  382. if (GetIsDragging(p))
  383. {
  384. EndDragging(p);
  385. Mouse.Capture(null);
  386. UITools.FindAncestor<ListView>(p).Focus();
  387. ListViewItem curSelectedItem = getSelectedItem(p, Mouse.GetPosition(p));
  388. if (curSelectedItem != null && curSelectedItem.Equals(_itemUnderMouse))
  389. {
  390. UITools.FindAncestor<ListBox>(p).SelectedItems.Clear();
  391. _itemUnderMouse.IsSelected = true;
  392. }
  393. }
  394. if (_firstSelectedItem == null && GetStartPosition(p).Equals(Mouse.GetPosition(p)))
  395. UITools.FindAncestor<ListBox>(p).SelectedItems.Clear();
  396. _firstSelectedItem = null;
  397. SetIsDragging(p, false);
  398. }
  399. #endregion
  400. #region Data
  401. #endregion
  402. }
  403. }