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