oops
[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 using System.ComponentModel;
33 using System.Security.Permissions;
34
35 namespace System.Web.UI.WebControls {
36
37         // CAS - no inheritance demand required because the class is sealed
38         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
39         public sealed class RepeatInfo {
40
41                 // What is baseControl for ?
42                 public void RenderRepeater (HtmlTextWriter w, IRepeatInfoUser user, Style controlStyle, WebControl baseControl)
43                 {
44                         PrintValues (user);
45
46                         if (RepeatDirection == RepeatDirection.Vertical)
47                                 RenderVert (w, user, controlStyle, baseControl);
48                         else
49                                 RenderHoriz (w, user, controlStyle, baseControl);
50                 }
51
52                 void RenderBr (HtmlTextWriter w)
53                 {
54 #if NET_2_0
55                         w.Write ("<br />");
56 #else
57                         // grrr, not xhtml...
58                         w.Write ("<br>");
59 #endif
60
61                 }
62
63                 void RenderVert (HtmlTextWriter w, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) 
64                 {
65                         int itms = user.RepeatedItemCount;
66                         // total number of rows/columns in our table
67                         int cols = RepeatColumns == 0 ? 1 : RepeatColumns;
68                         // this gets ceil (itms / cols)
69                         int rows = (itms + cols - 1) / cols;
70                         bool sep = user.HasSeparators;
71                         bool oti = OuterTableImplied;
72                         int hdr_span = cols * ((sep && cols != 1) ? 2 : 1);
73
74                         bool table = RepeatLayout == RepeatLayout.Table && !oti;
75
76 #if NET_2_0
77                         bool show_empty_trailing_items = true;
78                         bool show_empty_trailing_sep = true;
79 #else
80                         bool show_empty_trailing_items = false;
81                         bool show_empty_trailing_sep = false;
82 #endif
83                         
84                         if (! oti)
85                                 RenderBeginTag (w, controlStyle, baseControl);
86
87                         if (UseAccessibleHeader) {
88                                 if (CaptionAlign != TableCaptionAlign.NotSet)
89                                         w.AddAttribute (HtmlTextWriterAttribute.Align, CaptionAlign.ToString());
90
91                                 w.RenderBeginTag (HtmlTextWriterTag.Caption);
92                                 w.Write (Caption);
93                                 w.RenderEndTag ();
94
95                         }
96
97                         // Render the header
98                         if (user.HasHeader) {
99                                 if (oti)
100                                         user.RenderItem (ListItemType.Header, -1, this, w);
101                                 else if (table) {
102                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
103                                         // Make sure the header takes up the full width. We have two
104                                         // columns per item if we are using separators, otherwise
105                                         // one per item.
106                                         if (hdr_span != 1)
107                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
108
109                                         Style s = user.GetItemStyle (ListItemType.Header, -1);
110                                         if (s != null)
111                                                 s.AddAttributesToRender (w);
112                                         
113                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
114                                         user.RenderItem (ListItemType.Header, -1, this, w);
115                                         w.RenderEndTag (); // td
116                                         w.RenderEndTag (); // tr
117                                 } else {
118                                         user.RenderItem (ListItemType.Header, -1, this, w);
119                                         RenderBr (w);
120                                 }
121                         }
122
123                         for (int r = 0; r < rows; r ++) {
124                                 if (table)
125                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
126                                 
127                                 for (int c = 0; c < cols; c ++) {
128                                         // Find the item number we are in according to the repeat
129                                         // direction.
130                                         int item = index_vert (rows, cols, r, c, itms);
131
132                                         // This item is blank because there there not enough items
133                                         // to make a full row.
134                                         if (!show_empty_trailing_items && item >= itms)
135                                                 continue;
136
137                                         if (table) {
138                                                 Style s = null;
139                                                 if (item < itms)
140                                                         s = user.GetItemStyle (ListItemType.Item, item);
141                                                 if (s != null)
142                                                         s.AddAttributesToRender (w);
143                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
144                                         }
145                                         
146                                         if (item < itms)
147                                                 user.RenderItem (ListItemType.Item, item, this, w);
148
149                                         if (table)
150                                                 w.RenderEndTag (); // td
151
152                                         if (sep && cols != 1) {
153                                                 if (table) {
154                                                         if (item < itms - 1) {
155                                                                 Style s = user.GetItemStyle (ListItemType.Separator, item);
156                                                                 if (s != null)
157                                                                         s.AddAttributesToRender (w);
158                                                         }
159                                                         if (item < itms - 1 || show_empty_trailing_sep)
160                                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
161                                                 }
162
163                                                 if (item < itms - 1)
164                                                         user.RenderItem (ListItemType.Separator, item, this, w);
165
166                                                 if (table && (item < itms - 1 || show_empty_trailing_sep))
167                                                         w.RenderEndTag (); // td
168                                         }
169                                 }
170                                 if (oti) {
171                                 } else if (table) {
172                                         w.RenderEndTag (); // tr
173                                 } else if (r != rows - 1) {
174                                         RenderBr(w);
175                                 }
176                                 
177                                 if (sep && r != rows - 1 /* no sep on last item */ && cols == 1) {
178                                         if (table) {
179                                                 w.RenderBeginTag (HtmlTextWriterTag.Tr);
180                                                 Style s = user.GetItemStyle (ListItemType.Separator, r);
181                                                 if (s != null)
182                                                         s.AddAttributesToRender (w);
183                                         
184                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
185                                         } else if (oti) {
186 #if !NET_2_0
187                                                 /* 2.0 doesn't render this <br /> */
188                                                 RenderBr (w);
189 #endif
190                                         }
191                                         
192                                         user.RenderItem (ListItemType.Separator, r, this, w);
193
194                                         if (table) {
195                                                 w.RenderEndTag (); // td
196                                                 w.RenderEndTag (); // tr
197                                         } else if (!oti) {
198                                                 RenderBr (w);
199                                         }
200                                 }
201                         }
202
203                         // Render the footer
204                         if (user.HasFooter) {
205                                 if (oti)
206                                         user.RenderItem (ListItemType.Footer, -1, this, w);
207                                 else if (table) {
208                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
209                                         if (hdr_span != 1)
210                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
211
212                                         Style s = user.GetItemStyle (ListItemType.Footer, -1);
213                                         if (s != null)
214                                                 s.AddAttributesToRender (w);
215                                         
216                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
217                                         user.RenderItem (ListItemType.Footer, -1, this, w);
218                                         w.RenderEndTag (); // td
219                                         w.RenderEndTag (); // tr
220                                 } else {
221                                         // avoid dups on 0 items
222                                         if (itms != 0)
223                                                 RenderBr (w);
224                                         user.RenderItem (ListItemType.Footer, -1, this, w);
225                                 }
226                         }
227                         if (! oti)
228                                 w.RenderEndTag (); // table/span
229                         
230                 }
231                 
232                 void RenderHoriz (HtmlTextWriter w, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) 
233                 {
234                         int itms = user.RepeatedItemCount;
235                         // total number of rows/columns in our table
236                         int cols = RepeatColumns == 0 ? itms : RepeatColumns;
237                         // this gets ceil (itms / cols)
238                         int rows = cols == 0 ? 0 : (itms + cols - 1) / cols;
239                         bool sep = user.HasSeparators;
240                         //bool oti = OuterTableImplied;
241                         int hdr_span = cols * (sep ? 2 : 1);
242
243                         bool table = RepeatLayout == RepeatLayout.Table;
244
245 #if NET_2_0
246                         bool show_empty_trailing_items = true;
247                         bool show_empty_trailing_sep = true;
248 #else
249                         bool show_empty_trailing_items = false;
250                         bool show_empty_trailing_sep = false;
251 #endif
252
253                         RenderBeginTag (w, controlStyle, baseControl);
254                         
255                         if (UseAccessibleHeader) {
256                                 if (CaptionAlign != TableCaptionAlign.NotSet)
257                                         w.AddAttribute (HtmlTextWriterAttribute.Align, CaptionAlign.ToString());
258
259                                 w.RenderBeginTag (HtmlTextWriterTag.Caption);
260                                 w.Write (Caption);
261                                 w.RenderEndTag ();
262
263                         }
264                         
265                         // Render the header
266                         if (user.HasHeader) {
267                                 if (table) {
268                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
269                                         // Make sure the header takes up the full width. We have two
270                                         // columns per item if we are using separators, otherwise
271                                         // one per item.
272                                         if (hdr_span != 1)
273                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
274
275                                         Style s = user.GetItemStyle (ListItemType.Header, -1);
276                                         if (s != null)
277                                                 s.AddAttributesToRender (w);
278                                         
279                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
280                                         user.RenderItem (ListItemType.Header, -1, this, w);
281                                         w.RenderEndTag (); // td
282                                         w.RenderEndTag (); // tr
283                                 } else {
284                                         user.RenderItem (ListItemType.Header, -1, this, w);
285                                         if (!table && RepeatColumns != 0 && itms != 0)
286                                                 RenderBr (w);
287                                 }
288                         }
289                                                 
290                         for (int r = 0; r < rows; r ++) {
291                                 if (table)
292                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
293                                 
294                                 for (int c = 0; c < cols; c ++) {
295                                         // Find the item number we are in according to the repeat
296                                         // direction.
297                                         int item = r * cols + c;
298
299                                         // This item is blank because there there not enough items
300                                         // to make a full row.
301                                         if (!show_empty_trailing_items && item >= itms)
302                                                 continue;
303
304                                         if (table) {
305                                                 Style s = null;
306                                                 if (item < itms)
307                                                         s = user.GetItemStyle (ListItemType.Item, item);
308
309                                                 if (s != null)
310                                                         s.AddAttributesToRender (w);
311                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
312                                         }
313
314                                         if (item < itms)
315                                                 user.RenderItem (ListItemType.Item, item, this, w);
316
317                                         if (table)
318                                                 w.RenderEndTag (); // td
319
320                                         if (sep) {
321                                                 if (table) {
322                                                         if (item < itms - 1) {
323                                                                 Style s = user.GetItemStyle (ListItemType.Separator, item);
324                                                                 if (s != null)
325                                                                         s.AddAttributesToRender (w);
326                                                         }
327                                                         if (item < itms - 1 || show_empty_trailing_sep)
328                                                                 w.RenderBeginTag (HtmlTextWriterTag.Td);
329                                                 }
330
331                                                 if (item < itms - 1)
332                                                         user.RenderItem (ListItemType.Separator, item, this, w);
333
334                                                 if (table && (item < itms - 1 || show_empty_trailing_sep))
335                                                         w.RenderEndTag (); // td
336                                         }
337                                 }
338
339                                 if (table) {
340                                         //      if (!oti)
341                                                 w.RenderEndTag (); // tr
342                                 } else if (!(r == rows -1 && RepeatColumns == 0))
343                                         RenderBr (w);
344                                 
345                         }
346
347                         // Render the footer
348                         if (user.HasFooter) {
349                                 if (table) {
350                                         w.RenderBeginTag (HtmlTextWriterTag.Tr);
351                                         if (hdr_span != 1)
352                                                 w.AddAttribute (HtmlTextWriterAttribute.Colspan, hdr_span.ToString ());
353
354                                         Style s = user.GetItemStyle (ListItemType.Footer, -1);
355                                         if (s != null)
356                                                 s.AddAttributesToRender (w);
357                                         
358                                         w.RenderBeginTag (HtmlTextWriterTag.Td);
359                                         user.RenderItem (ListItemType.Footer, -1, this, w);
360                                         w.RenderEndTag (); // td
361                                         w.RenderEndTag (); // tr
362                                 } else {
363                                         user.RenderItem (ListItemType.Footer, -1, this, w);
364                                 }
365                         }
366                         if (true)
367                                 w.RenderEndTag (); // table/span
368                         
369                 }
370
371                 int index_vert (int rows, int cols, int r, int c, int items)
372                 {
373                         int last = items % cols;
374
375                         if (last == 0)
376                                 last = cols;
377                         if (r == rows - 1 && c >= last)
378                                 return items;
379                         
380                         
381                         int add;
382                         int v;
383                         if (c > last){
384                                 add = last * rows + (c-last) * (rows-1);
385                                 v = add + r;
386                         } else
387                                 v = rows * c + r;
388                         
389                         return v;
390                 }
391
392                 void RenderBeginTag (HtmlTextWriter w, Style s, WebControl wc)
393                 {
394                         WebControl c;
395                         if (RepeatLayout == RepeatLayout.Table)
396                                 c = new Table ();
397                         else
398                                 c = new Label ();
399
400                         c.ID = wc.ClientID;
401                         c.CopyBaseAttributes (wc);
402                         c.ApplyStyle (s);
403                         c.Enabled = wc.Enabled;
404                         c.RenderBeginTag (w);
405                 }
406                 
407                 
408                 bool outer_table_implied;
409                 public bool OuterTableImplied {
410                         get {
411                                 return outer_table_implied;
412                         }
413                         set {
414                                 outer_table_implied = value;
415                         }
416                 }
417
418                 int repeat_cols;
419                 public int RepeatColumns {
420                         get {
421                                 return repeat_cols;
422                         }
423                         set {
424                                 repeat_cols = value;
425                         }
426                 }
427
428                 RepeatDirection dir = RepeatDirection.Vertical;
429                 public RepeatDirection RepeatDirection {
430                         get {
431                                 return dir;
432                         }
433                         set {
434                                 if (value != RepeatDirection.Horizontal &&
435                                     value != RepeatDirection.Vertical)
436                                         throw new ArgumentOutOfRangeException ();
437                                 
438                                 dir = value;
439                         }
440                 }
441
442                 RepeatLayout layout;
443                 public RepeatLayout RepeatLayout {
444                         get {
445                                 return layout;
446                         }
447                         set {
448                                 if (value != RepeatLayout.Flow &&
449                                     value != RepeatLayout.Table)
450                                         throw new ArgumentOutOfRangeException ();       
451                                 layout = value;
452                         }
453                 }
454
455                 [Conditional ("DEBUG_REPEAT_INFO")]
456                 internal void PrintValues (IRepeatInfoUser riu)
457                 {
458                         string s = String.Format ("Layout {0}; Direction {1}; Cols {2}; OuterTableImplied {3}\n" +
459                                         "User: itms {4}, hdr {5}; ftr {6}; sep {7}", RepeatLayout, RepeatDirection,
460                                         RepeatColumns, OuterTableImplied, riu.RepeatedItemCount, riu.HasSeparators, riu.HasHeader,
461                                         riu.HasFooter, riu.HasSeparators
462                                 );
463                         Console.WriteLine (s);
464                         if (HttpContext.Current != null)
465                                 HttpContext.Current.Trace.Write (s);
466                 }
467
468                 private string caption = "";
469                 private TableCaptionAlign captionAlign = TableCaptionAlign.NotSet; 
470                 private  bool useAccessibleHeader = false; 
471
472                 [WebSysDescription ("")]
473                 [WebCategory ("Accessibility")]
474                 public string Caption {
475                         get {return caption;}
476                         set { caption = value; }
477                 }
478
479                 [WebSysDescription ("")]
480                 [DefaultValue (TableCaptionAlign.NotSet)]
481                 [WebCategory ("Accessibility")]
482                 public TableCaptionAlign CaptionAlign {
483                         get {return captionAlign;}
484                         set { captionAlign = value; }
485                 }
486
487                 [WebSysDescription ("")]
488                 [DefaultValue (false)]
489                 [WebCategory ("Accessibility")]
490                 public bool UseAccessibleHeader {
491                         get {return useAccessibleHeader;}
492                         set { useAccessibleHeader = value; }            
493                 }
494
495         }
496 }