PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/Managed.Windows.Forms/System.Windows.Forms/CurrencyManager.cs

https://bitbucket.org/danipen/mono
C# | 452 lines | 333 code | 81 blank | 38 comment | 85 complexity | f97bc325e793fc2c4bd5b5d0517f3ca9 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (c) 2005 Novell, Inc.
  21. //
  22. // Authors:
  23. // Jackson Harper (jackson@ximian.com)
  24. // Ivan N. Zlatev (contact@i-nz.net)
  25. //
  26. using System;
  27. using System.Data;
  28. using System.Reflection;
  29. using System.Collections;
  30. using System.ComponentModel;
  31. namespace System.Windows.Forms {
  32. public class CurrencyManager : BindingManagerBase {
  33. protected int listposition;
  34. protected Type finalType;
  35. private IList list;
  36. private bool binding_suspended;
  37. private object data_source;
  38. bool editing;
  39. internal CurrencyManager ()
  40. {
  41. }
  42. internal CurrencyManager (object data_source)
  43. {
  44. SetDataSource (data_source);
  45. }
  46. public IList List {
  47. get { return list; }
  48. }
  49. public override object Current {
  50. get {
  51. if (listposition == -1 || listposition >= list.Count) {
  52. // Console.WriteLine ("throwing exception from here");
  53. // Console.WriteLine (Environment.StackTrace);
  54. throw new IndexOutOfRangeException ("list position");
  55. }
  56. return list [listposition];
  57. }
  58. }
  59. public override int Count {
  60. get { return list.Count; }
  61. }
  62. public override int Position {
  63. get {
  64. return listposition;
  65. }
  66. set {
  67. if (value < 0)
  68. value = 0;
  69. if (value >= list.Count)
  70. value = list.Count - 1;
  71. if (listposition == value)
  72. return;
  73. if (listposition != -1)
  74. EndCurrentEdit ();
  75. listposition = value;
  76. OnCurrentChanged (EventArgs.Empty);
  77. OnPositionChanged (EventArgs.Empty);
  78. }
  79. }
  80. internal void SetDataSource (object data_source)
  81. {
  82. if (this.data_source is IBindingList)
  83. ((IBindingList)this.data_source).ListChanged -= new ListChangedEventHandler (ListChangedHandler);
  84. if (data_source is IListSource)
  85. data_source = ((IListSource)data_source).GetList();
  86. this.data_source = data_source;
  87. if (data_source != null)
  88. this.finalType = data_source.GetType();
  89. listposition = -1;
  90. if (this.data_source is IBindingList)
  91. ((IBindingList)this.data_source).ListChanged += new ListChangedEventHandler (ListChangedHandler);
  92. list = (IList)data_source;
  93. // XXX this is wrong. MS invokes OnItemChanged directly, which seems to call PushData.
  94. ListChangedHandler (null, new ListChangedEventArgs (ListChangedType.Reset, -1));
  95. }
  96. public override PropertyDescriptorCollection GetItemProperties ()
  97. {
  98. return ListBindingHelper.GetListItemProperties (list);
  99. }
  100. public override void RemoveAt (int index)
  101. {
  102. list.RemoveAt (index);
  103. }
  104. public override void SuspendBinding ()
  105. {
  106. binding_suspended = true;
  107. }
  108. public override void ResumeBinding ()
  109. {
  110. binding_suspended = false;
  111. }
  112. internal override bool IsSuspended {
  113. get {
  114. // Always return true if we don't have items
  115. if (Count == 0)
  116. return true;
  117. return binding_suspended;
  118. }
  119. }
  120. internal bool AllowNew {
  121. get {
  122. if (list is IBindingList)
  123. return ((IBindingList)list).AllowNew;
  124. if (list.IsReadOnly)
  125. return false;
  126. return false;
  127. }
  128. }
  129. internal bool AllowRemove {
  130. get {
  131. if (list.IsReadOnly)
  132. return false;
  133. if (list is IBindingList)
  134. return ((IBindingList)list).AllowRemove;
  135. return false;
  136. }
  137. }
  138. internal bool AllowEdit {
  139. get {
  140. if (list is IBindingList)
  141. return ((IBindingList)list).AllowEdit;
  142. return false;
  143. }
  144. }
  145. public override void AddNew ()
  146. {
  147. IBindingList ibl = list as IBindingList;
  148. if (ibl == null)
  149. throw new NotSupportedException ();
  150. ibl.AddNew ();
  151. bool validate = (Position != (list.Count - 1));
  152. ChangeRecordState (list.Count - 1, validate, validate, true, true);
  153. }
  154. void BeginEdit ()
  155. {
  156. IEditableObject editable = Current as IEditableObject;
  157. if (editable != null) {
  158. try {
  159. editable.BeginEdit ();
  160. editing = true;
  161. }
  162. catch {
  163. /* swallow exceptions in IEditableObject.BeginEdit () */
  164. }
  165. }
  166. }
  167. public override void CancelCurrentEdit ()
  168. {
  169. if (listposition == -1)
  170. return;
  171. IEditableObject editable = Current as IEditableObject;
  172. if (editable != null) {
  173. editing = false;
  174. editable.CancelEdit ();
  175. OnItemChanged (new ItemChangedEventArgs (Position));
  176. }
  177. if (list is ICancelAddNew)
  178. ((ICancelAddNew)list).CancelNew (listposition);
  179. }
  180. public override void EndCurrentEdit ()
  181. {
  182. if (listposition == -1)
  183. return;
  184. IEditableObject editable = Current as IEditableObject;
  185. if (editable != null) {
  186. editing = false;
  187. editable.EndEdit ();
  188. }
  189. if (list is ICancelAddNew)
  190. ((ICancelAddNew)list).EndNew (listposition);
  191. }
  192. public void Refresh ()
  193. {
  194. ListChangedHandler (null, new ListChangedEventArgs (ListChangedType.Reset, -1));
  195. }
  196. protected void CheckEmpty ()
  197. {
  198. if (list == null || list.Count < 1)
  199. throw new Exception ("List is empty.");
  200. }
  201. protected internal override void OnCurrentChanged (EventArgs e)
  202. {
  203. if (onCurrentChangedHandler != null) {
  204. onCurrentChangedHandler (this, e);
  205. }
  206. // don't call OnCurrentItemChanged here, as it can be overridden
  207. if (onCurrentItemChangedHandler != null) {
  208. onCurrentItemChangedHandler (this, e);
  209. }
  210. }
  211. protected override void OnCurrentItemChanged (EventArgs e)
  212. {
  213. if (onCurrentItemChangedHandler != null) {
  214. onCurrentItemChangedHandler (this, e);
  215. }
  216. }
  217. protected virtual void OnItemChanged (ItemChangedEventArgs e)
  218. {
  219. if (ItemChanged != null)
  220. ItemChanged (this, e);
  221. transfering_data = true;
  222. PushData ();
  223. transfering_data = false;
  224. }
  225. void OnListChanged (ListChangedEventArgs args)
  226. {
  227. if (ListChanged != null)
  228. ListChanged (this, args);
  229. }
  230. protected virtual void OnPositionChanged (EventArgs e)
  231. {
  232. if (onPositionChangedHandler != null)
  233. onPositionChangedHandler (this, e);
  234. }
  235. protected internal override string GetListName (ArrayList listAccessors)
  236. {
  237. if (list is ITypedList) {
  238. PropertyDescriptor [] pds = null;
  239. if (listAccessors != null) {
  240. pds = new PropertyDescriptor [listAccessors.Count];
  241. listAccessors.CopyTo (pds, 0);
  242. }
  243. return ((ITypedList) list).GetListName (pds);
  244. }
  245. else if (finalType != null) {
  246. return finalType.Name;
  247. }
  248. return String.Empty;
  249. }
  250. protected override void UpdateIsBinding ()
  251. {
  252. UpdateItem ();
  253. foreach (Binding binding in Bindings)
  254. binding.UpdateIsBinding ();
  255. ChangeRecordState (listposition, false, false, true, false);
  256. OnItemChanged (new ItemChangedEventArgs (-1));
  257. }
  258. private void ChangeRecordState (int newPosition,
  259. bool validating,
  260. bool endCurrentEdit,
  261. bool firePositionChanged,
  262. bool pullData)
  263. {
  264. if (endCurrentEdit)
  265. EndCurrentEdit ();
  266. int old_index = listposition;
  267. listposition = newPosition;
  268. if (listposition >= list.Count)
  269. listposition = list.Count - 1;
  270. if (old_index != -1 && listposition != -1)
  271. OnCurrentChanged (EventArgs.Empty);
  272. if (firePositionChanged)
  273. OnPositionChanged (EventArgs.Empty);
  274. }
  275. private void UpdateItem ()
  276. {
  277. // Probably should be validating or something here
  278. if (!transfering_data && listposition == -1 && list.Count > 0) {
  279. listposition = 0;
  280. BeginEdit ();
  281. }
  282. }
  283. internal object this [int index] {
  284. get { return list [index]; }
  285. }
  286. private PropertyDescriptorCollection GetBrowsableProperties (Type t)
  287. {
  288. Attribute [] att = new System.Attribute [1];
  289. att [0] = new BrowsableAttribute (true);
  290. return TypeDescriptor.GetProperties (t, att);
  291. }
  292. protected void OnMetaDataChanged (EventArgs e)
  293. {
  294. if (MetaDataChanged != null)
  295. MetaDataChanged (this, e);
  296. }
  297. private void ListChangedHandler (object sender, ListChangedEventArgs e)
  298. {
  299. switch (e.ListChangedType) {
  300. case ListChangedType.PropertyDescriptorAdded:
  301. case ListChangedType.PropertyDescriptorDeleted:
  302. case ListChangedType.PropertyDescriptorChanged:
  303. OnMetaDataChanged (EventArgs.Empty);
  304. OnListChanged (e);
  305. break;
  306. case ListChangedType.ItemDeleted:
  307. if (list.Count == 0) {
  308. /* the last row was deleted */
  309. listposition = -1;
  310. UpdateIsBinding ();
  311. OnPositionChanged (EventArgs.Empty);
  312. OnCurrentChanged (EventArgs.Empty);
  313. }
  314. else if (e.NewIndex <= listposition) {
  315. /* the deleted row was either the current one, or one earlier in the list.
  316. Update the index and emit PositionChanged, CurrentChanged, and ItemChanged. */
  317. ChangeRecordState (listposition+1,
  318. false, false, e.NewIndex != listposition, false);
  319. }
  320. else {
  321. /* the deleted row was after the current one, so we don't
  322. need to update bound controls for Position/Current changed */
  323. }
  324. OnItemChanged (new ItemChangedEventArgs (-1));
  325. OnListChanged (e);
  326. break;
  327. case ListChangedType.ItemAdded:
  328. if (list.Count == 1) {
  329. /* it's the first one we've added */
  330. ChangeRecordState (e.NewIndex,
  331. false, false, true, false);
  332. OnItemChanged (new ItemChangedEventArgs (-1));
  333. OnListChanged (e);
  334. }
  335. else {
  336. if (e.NewIndex <= listposition) {
  337. ChangeRecordState (e.NewIndex,
  338. false, false, false, false);
  339. OnItemChanged (new ItemChangedEventArgs (-1));
  340. OnListChanged (e);
  341. OnPositionChanged (EventArgs.Empty);
  342. }
  343. else {
  344. OnItemChanged (new ItemChangedEventArgs (-1));
  345. OnListChanged (e);
  346. }
  347. }
  348. break;
  349. case ListChangedType.ItemChanged:
  350. if (editing) {
  351. if (e.NewIndex == listposition)
  352. OnCurrentItemChanged (EventArgs.Empty);
  353. OnItemChanged (new ItemChangedEventArgs (e.NewIndex));
  354. }
  355. OnListChanged (e);
  356. break;
  357. case ListChangedType.Reset:
  358. PushData();
  359. UpdateIsBinding();
  360. OnListChanged (e);
  361. break;
  362. default:
  363. OnListChanged (e);
  364. break;
  365. }
  366. }
  367. public event ListChangedEventHandler ListChanged;
  368. public event ItemChangedEventHandler ItemChanged;
  369. public event EventHandler MetaDataChanged;
  370. }
  371. }