PageRenderTime 61ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Eto.Mac/Forms/Controls/GridHandler.cs

https://github.com/dsoronda/Eto
C# | 419 lines | 358 code | 60 blank | 1 comment | 30 complexity | d1af28b37a1d866ef638139a7636bd2b MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using MonoMac.AppKit;
  3. using Eto.Forms;
  4. using System.Collections.Generic;
  5. using Eto.Mac.Forms.Menu;
  6. using System.Linq;
  7. using Eto.Drawing;
  8. using Eto.Mac.Drawing;
  9. using MonoMac.ObjCRuntime;
  10. using sd = System.Drawing;
  11. using MonoMac.Foundation;
  12. namespace Eto.Mac.Forms.Controls
  13. {
  14. public interface IGridHandler
  15. {
  16. Grid Widget { get; }
  17. NSTableView Table { get; }
  18. bool AutoSizeColumns();
  19. }
  20. class EtoGridScrollView : NSScrollView
  21. {
  22. WeakReference handler;
  23. public IGridHandler Handler { get { return (IGridHandler)handler.Target; } set { handler = new WeakReference(value); } }
  24. bool autoSized;
  25. public override void SetFrameSize(sd.SizeF newSize)
  26. {
  27. base.SetFrameSize(newSize);
  28. if (!autoSized)
  29. {
  30. autoSized = Handler.AutoSizeColumns();
  31. }
  32. }
  33. }
  34. class EtoTableHeaderView : NSTableHeaderView
  35. {
  36. WeakReference handler;
  37. public IGridHandler Handler { get { return (IGridHandler)handler.Target; } set { handler = new WeakReference(value); } }
  38. static readonly Selector selConvertPointFromBacking = new Selector("convertPointFromBacking:");
  39. public override void MouseDown(NSEvent theEvent)
  40. {
  41. var point = theEvent.LocationInWindow;
  42. if (RespondsToSelector(selConvertPointFromBacking))
  43. point = ConvertPointFromBacking(point);
  44. else
  45. point = ConvertPointFromBase(point);
  46. var col = GetColumn(point);
  47. if (col >= 0)
  48. {
  49. var column = Handler.Widget.Columns[col];
  50. if (!column.Sortable)
  51. return;
  52. }
  53. base.MouseDown(theEvent);
  54. }
  55. }
  56. class MacCellFormatArgs : GridCellFormatEventArgs
  57. {
  58. Font font;
  59. public ICellHandler CellHandler { get { return Column.DataCell.Handler as ICellHandler; } }
  60. public NSCell Cell { get; private set; }
  61. public MacCellFormatArgs(GridColumn column, object item, int row, NSCell cell)
  62. : base(column, item, row)
  63. {
  64. this.Cell = cell;
  65. }
  66. public override Font Font
  67. {
  68. get
  69. {
  70. return font ?? (font = new Font(new FontHandler(Cell.Font)));
  71. }
  72. set
  73. {
  74. font = value;
  75. Cell.Font = font != null ? ((FontHandler)font.Handler).Control : null;
  76. }
  77. }
  78. public override Color BackgroundColor
  79. {
  80. get { return CellHandler.GetBackgroundColor(Cell); }
  81. set { CellHandler.SetBackgroundColor(Cell, value); }
  82. }
  83. public override Color ForegroundColor
  84. {
  85. get { return CellHandler.GetForegroundColor(Cell); }
  86. set { CellHandler.SetForegroundColor(Cell, value); }
  87. }
  88. }
  89. public abstract class GridHandler<TControl, TWidget, TCallback> : MacControl<TControl, TWidget, TCallback>, Grid.IHandler, IDataViewHandler, IGridHandler
  90. where TControl: NSTableView
  91. where TWidget: Grid
  92. where TCallback: Grid.ICallback
  93. {
  94. ColumnCollection columns;
  95. ContextMenu contextMenu;
  96. protected int SuppressSelectionChanged { get; set; }
  97. protected bool IsAutoSizingColumns { get; private set; }
  98. public NSTableView Table
  99. {
  100. get { return Control; }
  101. }
  102. public NSScrollView ScrollView { get; private set; }
  103. public override NSView ContainerControl { get { return ScrollView; } }
  104. protected virtual void PreUpdateColumn(int index)
  105. {
  106. }
  107. protected virtual void UpdateColumns()
  108. {
  109. }
  110. public GridColumnHandler GetColumn(NSTableColumn tableColumn)
  111. {
  112. var str = tableColumn.Identifier;
  113. if (!string.IsNullOrEmpty(str))
  114. {
  115. int col;
  116. if (int.TryParse(str, out col))
  117. {
  118. return GetColumn(col);
  119. }
  120. }
  121. return null;
  122. }
  123. public GridColumnHandler GetColumn(int column)
  124. {
  125. return Widget.Columns[column].Handler as GridColumnHandler;
  126. //return Widget.Columns.Select (r => r.Handler as GridColumnHandler).First (r => r.Column == column);
  127. }
  128. class ColumnCollection : EnumerableChangedHandler<GridColumn, GridColumnCollection>
  129. {
  130. public GridHandler<TControl,TWidget,TCallback> Handler { get; set; }
  131. public override void AddItem(GridColumn item)
  132. {
  133. var colhandler = (GridColumnHandler)item.Handler;
  134. Handler.Control.AddColumn(colhandler.Control);
  135. colhandler.Setup(Handler.Control.ColumnCount - 1);
  136. Handler.UpdateColumns();
  137. }
  138. public override void InsertItem(int index, GridColumn item)
  139. {
  140. var outline = Handler.Control;
  141. var columns = new List<NSTableColumn>(outline.TableColumns());
  142. Handler.PreUpdateColumn(index);
  143. for (int i = index; i < columns.Count; i++)
  144. {
  145. outline.RemoveColumn(columns[i]);
  146. }
  147. var colhandler = (GridColumnHandler)item.Handler;
  148. columns.Insert(index, colhandler.Control);
  149. outline.AddColumn(colhandler.Control);
  150. colhandler.Setup(index);
  151. for (int i = index + 1; i < columns.Count; i++)
  152. {
  153. var col = columns[i];
  154. var colHandler = Handler.GetColumn(i);
  155. colHandler.Setup(i);
  156. outline.AddColumn(col);
  157. }
  158. Handler.UpdateColumns();
  159. }
  160. public override void RemoveItem(int index)
  161. {
  162. var outline = Handler.Control;
  163. var columns = new List<NSTableColumn>(outline.TableColumns());
  164. Handler.PreUpdateColumn(index);
  165. for (int i = index; i < columns.Count; i++)
  166. {
  167. outline.RemoveColumn(columns[i]);
  168. }
  169. columns.RemoveAt(index);
  170. for (int i = index; i < columns.Count; i++)
  171. {
  172. var col = columns[i];
  173. var colHandler = Handler.GetColumn(i);
  174. colHandler.Setup(i);
  175. outline.AddColumn(col);
  176. }
  177. Handler.UpdateColumns();
  178. }
  179. public override void RemoveAllItems()
  180. {
  181. Handler.PreUpdateColumn(0);
  182. foreach (var col in Handler.Control.TableColumns ())
  183. Handler.Control.RemoveColumn(col);
  184. Handler.UpdateColumns();
  185. }
  186. }
  187. protected GridHandler()
  188. {
  189. ScrollView = new EtoGridScrollView
  190. {
  191. Handler = this,
  192. HasVerticalScroller = true,
  193. HasHorizontalScroller = true,
  194. AutohidesScrollers = true,
  195. BorderType = NSBorderType.BezelBorder,
  196. };
  197. ScrollView.ContentView.PostsBoundsChangedNotifications = true;
  198. this.AddObserver(NSView.BoundsChangedNotification, HandleScrolled, ScrollView.ContentView);
  199. }
  200. static void HandleScrolled(ObserverActionEventArgs e)
  201. {
  202. var handler = (GridHandler<TControl,TWidget,TCallback>)e.Handler;
  203. handler.AutoSizeColumns();
  204. }
  205. public override void AttachEvent(string id)
  206. {
  207. switch (id)
  208. {
  209. default:
  210. base.AttachEvent(id);
  211. break;
  212. }
  213. }
  214. protected override void Initialize()
  215. {
  216. base.Initialize();
  217. columns = new ColumnCollection { Handler = this };
  218. columns.Register(Widget.Columns);
  219. Control.HeaderView = new EtoTableHeaderView { Handler = this };
  220. ScrollView.DocumentView = Control;
  221. }
  222. public override void OnLoadComplete(EventArgs e)
  223. {
  224. base.OnLoadComplete(e);
  225. int i = 0;
  226. IsAutoSizingColumns = true;
  227. foreach (var col in Widget.Columns.Select(r => r.Handler).OfType<IDataColumnHandler>())
  228. {
  229. col.Loaded(this, i++);
  230. col.Resize(true);
  231. }
  232. IsAutoSizingColumns = false;
  233. }
  234. public bool AutoSizeColumns()
  235. {
  236. if (Widget.Loaded)
  237. {
  238. var rect = Table.VisibleRect();
  239. if (!rect.IsEmpty)
  240. {
  241. IsAutoSizingColumns = true;
  242. foreach (var col in Widget.Columns.Select(r => r.Handler).OfType<IDataColumnHandler>())
  243. {
  244. col.Resize();
  245. }
  246. IsAutoSizingColumns = false;
  247. return true;
  248. }
  249. }
  250. return false;
  251. }
  252. public bool ShowHeader
  253. {
  254. get
  255. {
  256. return Control.HeaderView != null;
  257. }
  258. set
  259. {
  260. if (value && Control.HeaderView == null)
  261. {
  262. Control.HeaderView = new EtoTableHeaderView { Handler = this };
  263. }
  264. else if (!value && Control.HeaderView != null)
  265. {
  266. Control.HeaderView = null;
  267. }
  268. }
  269. }
  270. public bool AllowColumnReordering
  271. {
  272. get { return Control.AllowsColumnReordering; }
  273. set { Control.AllowsColumnReordering = value; }
  274. }
  275. public ContextMenu ContextMenu
  276. {
  277. get { return contextMenu; }
  278. set
  279. {
  280. contextMenu = value;
  281. Control.Menu = contextMenu != null ? ((ContextMenuHandler)contextMenu.Handler).Control : null;
  282. }
  283. }
  284. public bool AllowMultipleSelection
  285. {
  286. get { return Control.AllowsMultipleSelection; }
  287. set { Control.AllowsMultipleSelection = value; }
  288. }
  289. public IEnumerable<int> SelectedRows
  290. {
  291. get
  292. {
  293. var rows = Control.SelectedRows;
  294. if (rows != null && rows.Count > 0)
  295. return rows.Select(r => (int)r);
  296. return Enumerable.Empty<int>();
  297. }
  298. set
  299. {
  300. SuppressSelectionChanged++;
  301. UnselectAll();
  302. var indexes = NSIndexSet.FromArray(value.ToArray());
  303. Control.SelectRows(indexes, AllowMultipleSelection);
  304. SuppressSelectionChanged--;
  305. if (SuppressSelectionChanged == 0)
  306. Callback.OnSelectionChanged(Widget, EventArgs.Empty);
  307. }
  308. }
  309. public void SelectAll()
  310. {
  311. Control.SelectAll(Control);
  312. }
  313. public void SelectRow(int row)
  314. {
  315. Control.SelectRow(row, AllowMultipleSelection);
  316. }
  317. public void UnselectRow(int row)
  318. {
  319. Control.DeselectRow(row);
  320. }
  321. public void UnselectAll()
  322. {
  323. Control.DeselectAll(Control);
  324. }
  325. public int RowHeight
  326. {
  327. get { return (int)Control.RowHeight; }
  328. set { Control.RowHeight = value; }
  329. }
  330. public abstract object GetItem(int row);
  331. public virtual int RowCount
  332. {
  333. get { return Control.RowCount; }
  334. }
  335. Grid IGridHandler.Widget
  336. {
  337. get { return Widget; }
  338. }
  339. public sd.RectangleF GetVisibleRect()
  340. {
  341. var rect = ScrollView.VisibleRect();
  342. var loc = ScrollView.ContentView.Bounds.Location;
  343. rect.Offset(loc);
  344. return rect;
  345. }
  346. protected override SizeF GetNaturalSize(SizeF availableSize)
  347. {
  348. var width = Widget.Columns.Sum(r => r.Width);
  349. if (width == 0)
  350. width = 100;
  351. var height = RowHeight * 4;
  352. return new Size(width, height);
  353. }
  354. public void OnCellFormatting(GridColumn column, object item, int row, NSCell cell)
  355. {
  356. Callback.OnCellFormatting(Widget, new MacCellFormatArgs(column, item, row, cell));
  357. }
  358. }
  359. }