1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.MonoRail
.Framework
.ViewComponents
18 using System
.Collections
;
21 /// Renders a table where each nested content is rendered on a cell.
23 /// For example, suppose you have a dynamic list of items and what to display
24 /// them side by side, in four columns. As the number of elements in unknown
25 /// in development time, you can use the ColumnRenderer to
26 /// create the table and cells.
31 /// The following example uses nvelocity view engine syntax.
34 /// #blockcomponent(ColumnRenderer with "items=$interests")
37 /// Custom first element
48 /// Which should render something like:
55 /// Custom first element
66 /// Content is Voleyball
75 /// The following sections are supported. Only the <c>item</c> section must be always provided. <br/>
78 /// <c>start</c>: override it in order to create the table yourself <br/>
79 /// <c>endblock</c>: override it in order to end the table <br/>
81 /// <c>startrow</c>: override it in order to start the column <br/>
82 /// <c>endrow</c>: override it in order to end the column <br/>
84 /// <c>startcolumn</c>: override it in order to start the cell <br/>
85 /// <c>endcolumn</c>: override it in order to end the cell <br/>
87 /// <c>item</c>: must be overriden in order to display the item content (unless it's something trivial like a primitive) <br/>
88 /// <c>empty</c>: section used when the <see cref="Items"/> is empty <br/>
89 /// <c>firstelement</c>: if provided, will be rendered before any cells <br/>
93 /// The number of columns defaults to three.
96 public class ColumnRenderer
: ViewComponent
99 private IEnumerable enumerable
;
100 private bool dontRenderUneededTableForEmptyLists
= false;
103 /// Gets or sets the number of columns to display.
105 /// <value>The cols.</value>
110 set { cols = value; }
114 /// Gets or sets the items to show.
116 /// <value>The items.</value>
117 [ViewComponentParam(Required
= true)]
118 public IEnumerable Items
120 get { return enumerable; }
121 set { enumerable = value; }
125 /// Gets or sets a value indicating whether the component should render a table
126 /// even if there are no elements on the <see cref="Items"/>.
129 /// <c>true</c> if it should not render; otherwise, <c>false</c>.
131 [ViewComponentParam("emptyness")]
132 public bool DontRenderUneededTableForEmptyLists
134 get { return dontRenderUneededTableForEmptyLists; }
135 set { dontRenderUneededTableForEmptyLists = value; }
139 /// Called by the framework once the component instance
142 public override void Initialize()
146 throw new ViewComponentException("ColumnRenderer: 'cols' parameter must be greater than zero");
151 /// Called by the framework so the component can
152 /// render its content
154 public override void Render()
156 if (IsEmptyAndShouldNotRenderBrokenTableTags())
163 bool hasElements
= false;
166 if (enumerable
!= null)
170 if (Context
.HasSection("firstelement"))
176 Context
.RenderSection("firstelement");
180 toFinishRow
= itemIndex
++ + cols
;
183 foreach(object item
in enumerable
)
187 bool writeRow
= itemIndex
++ % cols
== 0;
189 if (toFinishRow
== itemIndex
) EndRow();
204 toFinishRow
= itemIndex
+ cols
;
208 if (itemIndex
< toFinishRow
)
210 for(; itemIndex
< toFinishRow
- 1; itemIndex
++)
213 RenderText(" ");
229 /// Implementor should return true only if the
230 /// <c>name</c> is a known section the view component
233 /// <param name="name">section being added</param>
234 /// <returns><see langword="true"/> if section is supported</returns>
235 public override bool SupportsSection(string name
)
237 return name
== "start" || name
== "endblock" ||
238 name
== "startcolumn" || name
== "endcolumn" ||
239 name
== "startrow" || name
== "endrow" ||
240 name
== "item" || name
== "firstelement" ||
244 private bool IsEmptyAndShouldNotRenderBrokenTableTags()
246 if (dontRenderUneededTableForEmptyLists
)
248 if (enumerable
== null || !enumerable
.GetEnumerator().MoveNext())
256 private void WriteElement(object item
)
258 if (Context
.HasSection("item"))
260 PropertyBag
["item"] = item
;
261 Context
.RenderSection("item");
265 RenderText(item
.ToString());
269 private void StartColumn()
271 if (Context
.HasSection("startcolumn"))
273 Context
.RenderSection("startcolumn");
281 private void EndColumn()
283 if (Context
.HasSection("endcolumn"))
285 Context
.RenderSection("endcolumn");
293 private void StartRow()
295 if (Context
.HasSection("startrow"))
297 Context
.RenderSection("startrow");
305 private void EndRow()
307 if (Context
.HasSection("endrow"))
309 Context
.RenderSection("endrow");
317 private void StartTable()
319 if (Context
.HasSection("start"))
321 Context
.RenderSection("start");
325 RenderText("<table cellpadding='5'>");
329 private void NoElements()
331 if (Context
.HasSection("empty"))
333 Context
.RenderSection("empty");
337 if (dontRenderUneededTableForEmptyLists
)
352 private void EndTable()
354 if (Context
.HasSection("endblock"))
356 Context
.RenderSection("endblock");
360 RenderText("</table>");