merge from trunk revisions 58933, 58935, 58936
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / PagedDataSource.cs
1 // System.Web.UI.WebControls.PagedDataSource.cs
2 //
3 // Author: Duncan Mak (duncan@novell.com)
4 //         Jackson Harper  (jackson@ximian.com) 
5 //
6 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 // 
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 // 
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 //
27
28 using System.Collections;
29 using System.ComponentModel;
30 using System.Security.Permissions;
31
32 namespace System.Web.UI.WebControls {
33
34         // CAS - no inheritance demand required because the class is sealed
35         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
36         public sealed class PagedDataSource : ICollection, IEnumerable, ITypedList
37         {
38                 int page_size, current_page_index, virtual_count;
39                 bool allow_paging, allow_custom_paging;
40                 IEnumerable source;
41                 
42                 public PagedDataSource ()
43                 {
44                         page_size = 10;
45                 }
46
47                 public bool AllowCustomPaging {
48                         get { return allow_custom_paging; }
49                         set { allow_custom_paging = value; }
50                 }
51
52                 public bool AllowPaging {
53                         get { return allow_paging; }
54                         set { allow_paging = value; }
55                 }
56
57                 public int Count {
58                         get {
59                                 if (source == null)
60                                         return 0;
61                                 
62                                 if (IsPagingEnabled) {
63                                         if (IsCustomPagingEnabled || !IsLastPage)
64                                                 return page_size;
65                                         return DataSourceCount - FirstIndexInPage;
66                                 }
67
68                                 return DataSourceCount;
69                         }
70                 }                                               
71
72                 public int CurrentPageIndex {
73                         get { return current_page_index; }
74                         set { current_page_index = value; }
75                 }
76
77                 public IEnumerable DataSource {
78                         get { return source; }
79                         set { source = value; }
80                 }
81
82                 public int DataSourceCount {
83                         get {
84                                 if (source == null)
85                                         return 0;
86                                 
87                                 if (IsCustomPagingEnabled)
88                                         return virtual_count;
89
90                                 if (source is ICollection)
91                                         return ((ICollection) source).Count;
92
93                                 throw new HttpException ("The data source must implement ICollection");
94                         }
95                 }
96
97                 public int FirstIndexInPage {
98                         get {
99                                 if (!IsPagingEnabled || IsCustomPagingEnabled || source == null)
100                                         return 0;
101                                 
102                                 return current_page_index * page_size;
103                         }
104                 }
105
106                 public bool IsCustomPagingEnabled {
107                         get { return IsPagingEnabled && allow_custom_paging; }
108                 }
109
110                 public bool IsFirstPage {
111                         get { 
112                                 if (!allow_paging)
113                                         return true;
114                                 
115                                 return current_page_index == 0; 
116                         }
117                 }
118
119                 public bool IsLastPage {
120                         get {
121                                 if (!allow_paging || page_size == 0)
122                                         return true;
123
124                                 return  (current_page_index == (PageCount - 1));
125                         }
126                 }
127
128                 public bool IsPagingEnabled {
129                         get { return (allow_paging && page_size != 0); }
130                 }
131
132                 public bool IsReadOnly {
133                         get { return false; } // as documented
134                 }
135
136                 public bool IsSynchronized {
137                         get { return false; } // as documented
138                 }
139
140                 public int PageCount {
141                         get {
142                                 if (source == null)
143                                         return 0;
144
145                                 if (!IsPagingEnabled || DataSourceCount == 0 || page_size == 0)
146                                         return 1;
147
148                                 return (DataSourceCount + page_size - 1) / page_size;
149                         }
150                 }
151                 
152                 public int PageSize {
153                         get { return page_size; }
154                         set { page_size = value; }
155                 }
156
157                 public object SyncRoot {
158                         get { return this; }
159                 }
160
161                 public int VirtualCount {
162                         get { return virtual_count; }
163                         set { virtual_count = value; }
164                 }
165 #if NET_2_0
166                 [MonoTODO]
167                 public bool AllowServerPaging {
168                         get {
169                                 throw new NotImplementedException ();
170                         }
171                         set {
172                                 throw new NotImplementedException ();
173                         }
174                 }
175
176                 [MonoTODO]
177                 public DataSourceSelectArguments DataSourceSelectArguments {
178                         get {
179                                 throw new NotImplementedException ();
180                         }
181                         set {
182                                 throw new NotImplementedException ();
183                         }
184                 }
185                 [MonoTODO]
186                 public DataSourceView DataSourceView {
187                         get {
188                                 throw new NotImplementedException ();
189                         }
190                         set {
191                                 throw new NotImplementedException ();
192                         }
193                 }
194
195                 [MonoTODO]
196                 public void SetItemCountFromPageIndex (int highestPageIndex)
197                 {
198                         throw new NotImplementedException ();
199                 }
200 #endif
201
202                 public void CopyTo (Array array, int index)
203                 {
204                         foreach (object o in source)
205                                 array.SetValue (o, index++);
206                 }
207
208                 public IEnumerator GetEnumerator ()
209                 {
210                         // IList goes first, as it implements ICollection
211                         IList list = source as IList;
212                         int first = 0;
213                         int count;
214                         int limit;
215                         if (list != null) {
216                                 first = FirstIndexInPage;
217                                 count = ((ICollection) source).Count;
218                                 limit = ((first + page_size) > count) ? (count - first) : page_size;
219                                 return GetListEnum (list, first, first + limit);
220                         }
221
222                         ICollection col = source as ICollection;
223                         if (col != null) {
224                                 first = FirstIndexInPage;
225                                 count = col.Count;
226                                 limit = ((first + page_size) > count) ? (count - first) : page_size;
227                                 return GetEnumeratorEnum (col.GetEnumerator (), first, first + page_size);
228                         }
229
230                         return source.GetEnumerator ();
231                 }
232
233                 public PropertyDescriptorCollection GetItemProperties (PropertyDescriptor [] list_accessors)
234                 {
235                         ITypedList typed = source as ITypedList;
236                         if (typed == null)
237                                 return null;
238                         return typed.GetItemProperties (list_accessors);
239                 }
240
241                 public string GetListName (PropertyDescriptor [] list_accessors)
242                 {
243                         return String.Empty; // as documented
244                 }
245
246                 private IEnumerator GetListEnum (IList list, int start, int end)
247                 {
248                         if (!allow_paging)
249                                 end = list.Count;
250                         else if (start >= list.Count)
251                                 yield break;
252                         
253                         for (int i = start; i < end; i++)
254                                 yield return list [i];
255                 }
256
257                 private IEnumerator GetEnumeratorEnum (IEnumerator e, int start, int end)
258                 {
259                         for (int i = 0; i < start; i++)
260                                 e.MoveNext ();
261                         for (int i = start; (!allow_paging || i < end) && e.MoveNext (); i++)
262                                 yield return e.Current;
263                 }
264         }
265 }
266