New test.
[mono.git] / mcs / tools / sqlsharp / gui / gtk-sharp / DataGrid.cs
1 //
2 // DataGrid - attempt at creating a DataGrid for GTK#
3 //            using a GTK# TreeView.  The goal is to have similar
4 //            functionality to a System.Windows.Forms.DataGrid
5 //            or System.Web.UI.WebControls.DataGrid.  This includes
6 //            data binding support.
7 //    
8 // Based on the sample/TreeViewDemo.cs
9 //
10 // Author: Kristian Rietveld <kris@gtk.org>
11 //         Daniel Morgan <danmorg@sc.rr.com>
12 //
13 // (c) 2002 Kristian Rietveld
14 // (c) 2002 Daniel Morgan
15 //
16
17 namespace Gtk.Controls 
18 {
19         using System;
20         using System.Collections;
21         using System.ComponentModel;
22         using System.Drawing;
23         using System.Reflection;
24         using System.Text;
25         
26         using GLib;
27         using Gtk;
28         using GtkSharp;
29
30         using System.Runtime.InteropServices;
31
32         public class DataGridColumn 
33         {
34                 private string columnName = "";
35                 private TreeViewColumn treeViewColumn = null;
36
37                 public string ColumnName {
38                         get {
39                                 return columnName;
40                         }
41                         set {
42                                 columnName = value;
43                         }
44                 }
45
46                 public TreeViewColumn TreeViewColumn {
47                         get {
48                                 return treeViewColumn;
49                         }
50                         set {
51                                 treeViewColumn = value;
52                         }
53                 }
54         }
55
56         public class DataGrid : VBox
57         {
58                 private ListStore store = null;
59                 private TreeView treeView = null;
60
61                 public DataGridColumn[] gridColumns = null;
62
63                 public DataGrid () : base(false, 4) 
64                 {               
65                         ScrolledWindow sw = new ScrolledWindow ();
66                         this.PackStart (sw, true, true, 0);
67
68                         treeView = new TreeView (store);
69                         treeView.HeadersVisible = true;
70
71                         sw.Add (treeView);
72                 }
73
74                 // FIXME: need to place in a base class
75                 //        the DataSource, DataMember, DataBind()
76                 //        public members.
77                 //        maybe we can call the base class
78                 //        BaseDataList for GTK#?
79
80                 private object dataSource = null;
81
82                 private string dataMember = "";
83
84                 public object DataSource {
85                         get {
86                                 return dataSource;
87                         }
88                         set {
89                                 dataSource = value;
90                         }
91                 }
92
93                 public string DataMember {
94                         get {
95                                 return dataMember;
96                         }
97                         set {
98                                 dataMember = value;
99                         }
100                 }
101
102                 public void DataBind () 
103                 {
104                         Clear ();
105
106                         System.Object o = null;
107                         o = GetResolvedDataSource (DataSource, DataMember);
108                         IEnumerable ie = (IEnumerable) o;
109                         ITypedList tlist = (ITypedList) o;
110
111                         // FIXME: does not belong in this base method
112                         TreeIter iter = new TreeIter ();
113                                                                         
114                         PropertyDescriptorCollection pdc = tlist.GetItemProperties (new PropertyDescriptor[0]);
115
116                         // FIXME: does not belong in this base method
117                         gridColumns = new DataGridColumn[pdc.Count];
118
119                         // FIXME: does not belong in base method
120                         // define the columns in the treeview store
121                         // based on the schema of the result
122                         uint[] theTypes = new uint[pdc.Count];
123                         for (int col = 0; col < pdc.Count; col++) {
124                                 theTypes[col] = (int) TypeFundamentals.TypeString;
125                         }
126                         store.SetColumnTypes (theTypes);
127
128                         // FIXME: does not belong in this base method
129                         int colndx = -1;
130                         foreach (PropertyDescriptor pd in pdc) {
131                                 colndx ++;
132                                 gridColumns[colndx] = new DataGridColumn ();
133                                 gridColumns[colndx].ColumnName = pd.Name;                               
134                         }
135
136                         foreach (System.Object obj in ie) {
137                                 ICustomTypeDescriptor custom = (ICustomTypeDescriptor) obj;
138                                 PropertyDescriptorCollection properties;
139                                 properties = custom.GetProperties ();
140                                 
141                                 iter = NewRow ();
142                                 int cv = 0;
143                                 foreach (PropertyDescriptor property in properties) {
144                                         object oPropValue = property.GetValue (obj);
145                                         string sPropValue = oPropValue.ToString ();
146                                         
147                                         // FIXME: does not belong in this base method
148                                         SetColumnValue (iter, cv, sPropValue);
149
150                                         cv++;
151                                 }
152                         }
153
154                         // FIXME: does not belong in this base method
155                         treeView.Model = store;
156                         AutoCreateTreeViewColumns (treeView);
157                 }
158
159                 // borrowed from Mono's System.Web implementation
160                 protected IEnumerable GetResolvedDataSource(object source, string member) 
161                 {
162                         if (source != null && source is IListSource) {
163                                 IListSource src = (IListSource) source;
164                                 IList list = src.GetList ();
165                                 if (!src.ContainsListCollection) {
166                                         return list;
167                                 }
168                                 if (list != null && list is ITypedList) {
169
170                                         ITypedList tlist = (ITypedList) list;
171                                         PropertyDescriptorCollection pdc = tlist.GetItemProperties (new PropertyDescriptor[0]);
172                                         if (pdc != null && pdc.Count > 0) {
173                                                 PropertyDescriptor pd = null;
174                                                 if (member != null && member.Length > 0) {
175                                                         pd = pdc.Find (member, true);
176                                                 } else {
177                                                         pd = pdc[0];
178                                                 }
179                                                 if (pd != null) {
180                                                         object rv = pd.GetValue (list[0]);
181                                                         if (rv != null && rv is IEnumerable) {
182                                                                 return (IEnumerable)rv;
183                                                         }
184                                                 }
185                                                 throw new Exception ("ListSource_Missing_DataMember");
186                                         }
187                                         throw new Exception ("ListSource_Without_DataMembers");
188                                 }
189                         }
190                         if (source is IEnumerable) {
191                                 return (IEnumerable)source;
192                         }
193                         return null;
194                 }
195
196                 public void Clear () 
197                 {
198                         if (store != null) {
199                                 store.Clear ();
200                                 store = null;
201                                 store = new ListStore ((int)TypeFundamentals.TypeString);
202                         }
203                         else
204                                 store = new ListStore ((int)TypeFundamentals.TypeString);       
205
206                         if (gridColumns != null) {
207                                 for (int c = 0; c < gridColumns.Length; c++) {
208                                         if (gridColumns[c] != null) {
209                                                 if (gridColumns[c].TreeViewColumn != null) {
210                                                         treeView.RemoveColumn (gridColumns[c].TreeViewColumn);
211                                                         gridColumns[c].TreeViewColumn = null;
212                                                 }
213                                                 gridColumns[c] = null;
214                                         }
215                                 }
216                                 gridColumns = null;
217                         }
218                 }
219
220                 // for DEBUG only
221                 public void AppendText (string text) 
222                 {
223                         Console.WriteLine ("DataGrid DEBUG: " + text);
224                         Console.Out.Flush ();
225                 }
226
227                 public TreeIter NewRow () 
228                 { 
229                         TreeIter rowTreeIter = new TreeIter();
230                         store.Append (out rowTreeIter);
231                         return rowTreeIter;
232                 }
233
234                 public void AddRow (object[] columnValues) 
235                 {       
236                         TreeIter iter = NewRow ();                      
237                         for(int col = 0; col < columnValues.Length; col++) {
238                                 string cellValue = columnValues[col].ToString ();
239                                 SetColumnValue (iter, col, cellValue);
240                         }
241                 }
242
243                 public void SetColumnValue (TreeIter iter, int column, string value) 
244                 {
245                         GLib.Value cell = new GLib.Value (value);
246                         store.SetValue (iter, column, cell);    
247                 }
248
249                 private void AutoCreateTreeViewColumns (TreeView theTreeView) 
250                 {
251                         for(int col = 0; col < gridColumns.Length; col++) {
252                                 // escape underscore _ because it is used
253                                 // as the underline in menus and labels
254                                 StringBuilder name = new StringBuilder ();
255                                 foreach (char ch in gridColumns[col].ColumnName) {
256                                         if (ch == '_')
257                                                 name.Append ("__");
258                                         else
259                                                 name.Append (ch);
260                                 }
261                                 TreeViewColumn tvc;
262                                 tvc = CreateColumn (theTreeView, col, 
263                                                 name.ToString ());
264                                 theTreeView.AppendColumn (tvc);
265                         }
266                 }
267
268                 // TODO: maybe need to create 
269                 // a DataGridColumnCollection of DataGridColumn
270                 // and a DataGridColumn contain a TreeViewColumn
271                 public TreeViewColumn CreateColumn (TreeView theTreeView, int col, 
272                                                 string columnName) 
273                 {
274                         TreeViewColumn NameCol = new TreeViewColumn ();          
275                         CellRenderer NameRenderer = new CellRendererText ();
276                         
277                         NameCol.Title = columnName;
278                         NameCol.PackStart (NameRenderer, true);
279                         NameCol.AddAttribute (NameRenderer, "text", col);
280
281                         gridColumns[col].TreeViewColumn = NameCol;
282                         
283                         return NameCol;
284                 }
285         }
286 }