svn path=/branches/mono-1-1-9/mcs/; revision=51207
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / RepeatInfo.cs
1 //
2 // System.Web.UI.WebControls.RepeatInfo.cs
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@novell.com)
6 //
7 // (C) 2005 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 //#define DEBUG_REPEAT_INFO
30
31 using System.Diagnostics;
32
33 namespace System.Web.UI.WebControls {
34
35         public sealed class RepeatInfo {
36
37                 // What is baseControl for ?
38                 public void RenderRepeater (HtmlTextWriter w, IRepeatInfoUser user, Style controlStyle, WebControl baseControl)
39                 {
40                         PrintValues (user);
41
42                         if (RepeatDirection == RepeatDirection.Vertical)
43                                 RenderVert (w, user, controlStyle, baseControl);
44                         else
45                                 RenderHoriz (w, user, controlStyle, baseControl);
46                 }
47
48                 void RenderBr (HtmlTextWriter w)
49                 {
50 #if NET_2_0
51                         w.Write ("<br />");
52 #else
53                         // grrr, not xhtml...
54                         w.Write ("<br>");
55 #endif
56
57                 }
58
59                 void RenderVert (HtmlTextWriter w, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) 
60                 {
61                         int itms = user.RepeatedItemCount;
62                         // total number of rows/columns in our table
63                         int cols = RepeatColumns == 0 ? 1 : RepeatColumns;
64                         // this gets ceil (itms / cols)
65                         int rows = (itms + cols - 1) / cols;
66                         bool sep = user.HasSeparators;
67                         bool oti = OuterTableImplied;
68                         int hdr_span = cols * ((sep && cols != 1) ? 2 : 1);
69
70                         bool table = RepeatLayout == RepeatLayout.Table && !oti;
71
72 #if NET_2_0
73                         bool show_empty_trailing_items = true;
74                         bool show_empty_trailing_sep = true;
75 #else
76                         bool show_empty_trailing_items = false;
77                         bool show_empty_trailing_sep = false;
78 #endif
79                         
80                         if (! oti)
81                                 RenderBeginTag (w, controlStyle, baseControl);
82
83                         // Render the header
84                         if (user.HasHeader) {
85                                 if (oti)
86                                         user.RenderItem (ListItemType.Header, -1, this, w);
87                                 else if (table) {
88                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
89                                         // Make sure the header takes up the full width. We have two
90                                         // columns per item if we are using separators, otherwise
91                                         // one per item.
92                                         if (hdr_span != 1)
93                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
94
95                                         Style s = user.GetItemStyle (ListItemType.Header, -1);
96                                         if (s != null)
97                                                 s.AddAttributesToRender (w);
98                                         
99                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
100                                         user.RenderItem (ListItemType.Header, -1, this, w);
101                                         w.RenderEndTag (); // td
102                                         w.RenderEndTag (); // tr
103                                 } else {
104                                         user.RenderItem (ListItemType.Header, -1, this, w);
105                                         RenderBr (w);
106                                 }
107                         }
108
109                         for (int r = 0; r < rows; r ++) {
110                                 if (table)
111                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
112                                 
113                                 for (int c = 0; c < cols; c ++) {
114                                         // Find the item number we are in according to the repeat
115                                         // direction.
116                                         int item = index_vert (rows, cols, r, c, itms);
117
118                                         // This item is blank because there there not enough items
119                                         // to make a full row.
120                                         if (!show_empty_trailing_items && item >= itms)
121                                                 continue;
122
123                                         if (table) {
124                                                 Style s = null;
125                                                 if (item < itms)
126                                                         s = user.GetItemStyle (ListItemType.Item, item);
127                                                 if (s != null)
128                                                         s.AddAttributesToRender (w);
129                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
130                                         }
131                                         
132                                         if (item < itms)
133                                                 user.RenderItem (ListItemType.Item, item, this, w);
134
135                                         if (table)
136                                                 w.RenderEndTag (); // td
137
138                                         if (sep && cols != 1) {
139                                                 if (table) {
140                                                         if (item < itms - 1) {
141                                                                 Style s = user.GetItemStyle (ListItemType.Separator, item);
142                                                                 if (s != null)
143                                                                         s.AddAttributesToRender (w);
144                                                         }
145                                                         if (item < itms - 1 || show_empty_trailing_sep)
146                                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
147                                                 }
148
149                                                 if (item < itms - 1)
150                                                         user.RenderItem (ListItemType.Separator, item, this, w);
151
152                                                 if (table && (item < itms - 1 || show_empty_trailing_sep))
153                                                         w.RenderEndTag (); // td
154                                         }
155                                 }
156                                 if (oti) {
157                                 } else if (table) {
158                                         w.RenderEndTag (); // tr
159                                 } else if (r != rows - 1) {
160                                         RenderBr(w);
161                                 }
162                                 
163                                 if (sep && r != rows - 1 /* no sep on last item */ && cols == 1) {
164                                         if (table) {
165                                                 w.RenderBeginTag (HtmlTextWriterTag.Tr);
166                                                 Style s = user.GetItemStyle (ListItemType.Separator, r);
167                                                 if (s != null)
168                                                         s.AddAttributesToRender (w);
169                                         
170                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
171                                         } else if (oti) {
172 #if !NET_2_0
173                                                 /* 2.0 doesn't render this <br /> */
174                                                 RenderBr (w);
175 #endif
176                                         }
177                                         
178                                         user.RenderItem (ListItemType.Separator, r, this, w);
179
180                                         if (table) {
181                                                 w.RenderEndTag (); // td
182                                                 w.RenderEndTag (); // tr
183                                         } else if (!oti) {
184                                                 RenderBr (w);
185                                         }
186                                 }
187                         }
188
189                         // Render the footer
190                         if (user.HasFooter) {
191                                 if (oti)
192                                         user.RenderItem (ListItemType.Footer, -1, this, w);
193                                 else if (table) {
194                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
195                                         if (hdr_span != 1)
196                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
197
198                                         Style s = user.GetItemStyle (ListItemType.Footer, -1);
199                                         if (s != null)
200                                                 s.AddAttributesToRender (w);
201                                         
202                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
203                                         user.RenderItem (ListItemType.Footer, -1, this, w);
204                                         w.RenderEndTag (); // td
205                                         w.RenderEndTag (); // tr
206                                 } else {
207                                         // avoid dups on 0 items
208                                         if (itms != 0)
209                                                 RenderBr (w);
210                                         user.RenderItem (ListItemType.Footer, -1, this, w);
211                                 }
212                         }
213                         if (! oti)
214                                 w.RenderEndTag (); // table/span
215                         
216                 }
217                 
218                 void RenderHoriz (HtmlTextWriter w, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) 
219                 {
220                         int itms = user.RepeatedItemCount;
221                         // total number of rows/columns in our table
222                         int cols = RepeatColumns == 0 ? itms : RepeatColumns;
223                         // this gets ceil (itms / cols)
224                         int rows = cols == 0 ? 0 : (itms + cols - 1) / cols;
225                         bool sep = user.HasSeparators;
226                         //bool oti = OuterTableImplied;
227                         int hdr_span = cols * (sep ? 2 : 1);
228
229                         bool table = RepeatLayout == RepeatLayout.Table;
230
231 #if NET_2_0
232                         bool show_empty_trailing_items = true;
233                         bool show_empty_trailing_sep = true;
234 #else
235                         bool show_empty_trailing_items = false;
236                         bool show_empty_trailing_sep = false;
237 #endif
238
239                         RenderBeginTag (w, controlStyle, baseControl);
240                         
241                         // Render the header
242                         if (user.HasHeader) {
243                                 if (table) {
244                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
245                                         // Make sure the header takes up the full width. We have two
246                                         // columns per item if we are using separators, otherwise
247                                         // one per item.
248                                         if (hdr_span != 1)
249                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
250
251                                         Style s = user.GetItemStyle (ListItemType.Header, -1);
252                                         if (s != null)
253                                                 s.AddAttributesToRender (w);
254                                         
255                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
256                                         user.RenderItem (ListItemType.Header, -1, this, w);
257                                         w.RenderEndTag (); // td
258                                         w.RenderEndTag (); // tr
259                                 } else {
260                                         user.RenderItem (ListItemType.Header, -1, this, w);
261                                         if (!table && RepeatColumns != 0 && itms != 0)
262                                                 RenderBr (w);
263                                 }
264                         }
265                                                 
266                         for (int r = 0; r < rows; r ++) {
267                                 if (table)
268                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
269                                 
270                                 for (int c = 0; c < cols; c ++) {
271                                         // Find the item number we are in according to the repeat
272                                         // direction.
273                                         int item = r * cols + c;
274
275                                         // This item is blank because there there not enough items
276                                         // to make a full row.
277                                         if (!show_empty_trailing_items && item >= itms)
278                                                 continue;
279
280                                         if (table) {
281                                                 Style s = null;
282                                                 if (item < itms)
283                                                         s = user.GetItemStyle (ListItemType.Item, item);
284
285                                                 if (s != null)
286                                                         s.AddAttributesToRender (w);
287                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
288                                         }
289
290                                         if (item < itms)
291                                                 user.RenderItem (ListItemType.Item, item, this, w);
292
293                                         if (table)
294                                                 w.RenderEndTag (); // td
295
296                                         if (sep) {
297                                                 if (table) {
298                                                         if (item < itms - 1) {
299                                                                 Style s = user.GetItemStyle (ListItemType.Separator, item);
300                                                                 if (s != null)
301                                                                         s.AddAttributesToRender (w);
302                                                         }
303                                                         if (item < itms - 1 || show_empty_trailing_sep)
304                                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
305                                                 }
306
307                                                 if (item < itms - 1)
308                                                         user.RenderItem (ListItemType.Separator, item, this, w);
309
310                                                 if (table && (item < itms - 1 || show_empty_trailing_sep))
311                                                         w.RenderEndTag (); // td
312                                         }
313                                 }
314
315                                 if (table) {
316                                         //      if (!oti)
317                                                 w.RenderEndTag (); // tr
318                                 } else if (!(r == rows -1 && RepeatColumns == 0))
319                                         RenderBr (w);
320                                 
321                         }
322
323                         // Render the footer
324                         if (user.HasFooter) {
325                                 if (table) {
326                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
327                                         if (hdr_span != 1)
328                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
329
330                                         Style s = user.GetItemStyle (ListItemType.Footer, -1);
331                                         if (s != null)
332                                                 s.AddAttributesToRender (w);
333                                         
334                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
335                                         user.RenderItem (ListItemType.Footer, -1, this, w);
336                                         w.RenderEndTag (); // td
337                                         w.RenderEndTag (); // tr
338                                 } else {
339                                         user.RenderItem (ListItemType.Footer, -1, this, w);
340                                 }
341                         }
342                         if (true)
343                                 w.RenderEndTag (); // table/span
344                         
345                 }
346
347                 int index_vert (int rows, int cols, int r, int c, int items)
348                 {
349                         int last = items % cols;
350
351                         if (last == 0)
352                                 last = cols;
353                         if (r == rows - 1 && c >= last)
354                                 return items;
355                         
356                         
357                         int add;
358                         int v;
359                         if (c > last){
360                                 add = last * rows + (c-last) * (rows-1);
361                                 v = add + r;
362                         } else
363                                 v = rows * c + r;
364                         
365                         return v;
366                 }
367
368                 void RenderBeginTag (HtmlTextWriter w, Style s, WebControl wc)
369                 {
370                         WebControl c;
371                         if (RepeatLayout == RepeatLayout.Table)
372                                 c = new Table ();
373                         else
374                                 c = new Label ();
375
376                         c.ID = wc.ClientID;
377                         c.CopyBaseAttributes (wc);
378                         c.ApplyStyle (s);
379                         c.RenderBeginTag (w);
380                 }
381                 
382                 
383                 bool outer_table_implied;
384                 public bool OuterTableImplied {
385                         get {
386                                 return outer_table_implied;
387                         }
388                         set {
389                                 outer_table_implied = value;
390                         }
391                 }
392
393                 int repeat_cols;
394                 public int RepeatColumns {
395                         get {
396                                 return repeat_cols;
397                         }
398                         set {
399                                 repeat_cols = value;
400                         }
401                 }
402
403                 RepeatDirection dir = RepeatDirection.Vertical;
404                 public RepeatDirection RepeatDirection {
405                         get {
406                                 return dir;
407                         }
408                         set {
409                                 if (value != RepeatDirection.Horizontal &&
410                                     value != RepeatDirection.Vertical)
411                                         throw new ArgumentOutOfRangeException ();
412                                 
413                                 dir = value;
414                         }
415                 }
416
417                 RepeatLayout layout;
418                 public RepeatLayout RepeatLayout {
419                         get {
420                                 return layout;
421                         }
422                         set {
423                                 if (value != RepeatLayout.Flow &&
424                                     value != RepeatLayout.Table)
425                                         throw new ArgumentOutOfRangeException ();       
426                                 layout = value;
427                         }
428                 }
429
430                 [Conditional ("DEBUG_REPEAT_INFO")]
431                 internal void PrintValues (IRepeatInfoUser riu)
432                 {
433                         string s = String.Format ("Layout {0}; Direction {1}; Cols {2}; OuterTableImplied {3}\n" +
434                                         "User: itms {4}, hdr {5}; ftr {6}; sep {7}", RepeatLayout, RepeatDirection,
435                                         RepeatColumns, OuterTableImplied, riu.RepeatedItemCount, riu.HasSeparators, riu.HasHeader,
436                                         riu.HasFooter, riu.HasSeparators
437                                 );
438                         Console.WriteLine (s);
439                         if (HttpContext.Current != null)
440                                 HttpContext.Current.Trace.Write (s);
441                 }
442         }
443 }