Added non-generic registration interface to IKernel and IWindsor to accommodate dynam...
[castle.git] / MonoRail / Castle.MonoRail.Framework / ViewComponents / DiggStylePagination.cs
blob7d5608f2ce3acfdba53c3d62fdece37a73dc846e
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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
17 using System;
18 using System.Collections;
19 using System.IO;
20 using Castle.MonoRail.Framework.Helpers;
22 /// <summary>
23 /// Creates a digg style pagination.
24 /// <para>
25 /// Based on Alex Henderson work. See
26 /// (Monorail Pagination with Base4.Net)
27 /// http://blog.bittercoder.com/PermaLink,guid,579711a8-0b16-481b-b52b-ebdfa1a7e225.aspx
28 /// </para>
29 /// </summary>
30 ///
31 /// <remarks>
32 /// <para>
33 /// Parameters: <br/>
34 /// <c>adjacents</c>: number of links to show around the current page <br/>
35 /// <c>page</c> (required): <see cref="IPaginatedPage"/> instance (<see cref="PaginationHelper"/>) <br/>
36 /// <c>url</c>: url to link to<br/>
37 /// <c>useInlineStyle</c>: defines if the outputted content will use inline style or css classnames (defaults to true)<br/>
38 /// <c>renderIfOnlyOnePage</c>: should the pagination render if there's only one page (defaults to true)<br/>
39 /// <c>paginatefunction</c>: a javascript function name to invoke on the page links (instead of a URL)<br/>
40 /// </para>
41 ///
42 /// <para>
43 /// Supported sections: <br/>
44 /// <c>startblock</c>: invoked with <c>page</c> <br/>
45 /// <c>endblock</c>: invoked with <c>page</c> <br/>
46 /// <c>link</c>: invoked with <c>pageIndex</c>, <c>url</c> and <c>text</c>
47 /// so you can build a custom link <br/>
48 /// <c>prev</c>: text displayed instead of "&lt;%lt;prev" <br/>
49 /// <c>next</c>: text displayed instead of "next&gt;%gt;" <br/>
50 /// </para>
51 ///
52 /// </remarks>
53 [ViewComponentDetails("DiggStylePagination", Sections = "startblock,endblock,next,prev,link")]
54 public class DiggStylePagination : AbstractPaginationViewComponent
56 private const string LinkSection = "link";
57 private const string NextSection = "next";
58 private const string PrevSection = "prev";
60 private int adjacents = 2;
61 private bool renderIfOnlyOnePage = true;
63 /// <summary>
64 /// Gets or sets the adjacents (number of links to show).
65 /// </summary>
66 /// <value>The adjacents.</value>
67 [ViewComponentParam]
68 public int Adjacents
70 get { return adjacents; }
71 set { adjacents = value; }
74 /// <summary>
75 /// Gets or sets a value indicating whether the component should render links even if there is only one page.
76 /// </summary>
77 /// <value>
78 /// <c>true</c> if it should render; otherwise, <c>false</c>.
79 /// </value>
80 [ViewComponentParam]
81 public bool RenderIfOnlyOnePage
83 get { return renderIfOnlyOnePage; }
84 set { renderIfOnlyOnePage = value; }
87 /// <summary>
88 /// Called by the framework so the component can
89 /// render its content
90 /// </summary>
91 public override void Render()
93 if (renderIfOnlyOnePage || Page.LastIndex > 1)
95 StringWriter writer = new StringWriter();
97 StartBlock(writer);
98 WritePrev(writer);
100 if (Page.LastIndex < (4 + (adjacents * 2))) // not enough links to make it worth breaking up
102 WriteNumberedLinks(writer, 1, Page.LastIndex);
104 else
106 if ((Page.LastIndex - (adjacents * 2) > Page.CurrentIndex) && // in the middle
107 (Page.CurrentIndex > (adjacents * 2)))
109 WriteNumberedLinks(writer, 1, 2);
110 WriteElipsis(writer);
111 WriteNumberedLinks(writer, Page.CurrentIndex - adjacents, Page.CurrentIndex + adjacents);
112 WriteElipsis(writer);
113 WriteNumberedLinks(writer, Page.LastIndex - 1, Page.LastIndex);
115 else if (Page.CurrentIndex < (Page.LastIndex / 2))
117 WriteNumberedLinks(writer, 1, 2 + (adjacents * 2));
118 WriteElipsis(writer);
119 WriteNumberedLinks(writer, Page.LastIndex - 1, Page.LastIndex);
121 else // at the end
123 WriteNumberedLinks(writer, 1, 2);
124 WriteElipsis(writer);
125 WriteNumberedLinks(writer, Page.LastIndex - (2 + (adjacents * 2)), Page.LastIndex);
129 WriteNext(writer);
130 EndBlock(writer);
131 RenderText(writer.ToString());
135 private void WritePrev(StringWriter writer)
137 string caption = "&laquo; prev";
138 if (Context.HasSection(PrevSection))
140 TextWriter capWriter = new StringWriter();
141 Context.RenderSection(PrevSection, capWriter);
142 caption = capWriter.ToString().Trim();
144 WriteLink(writer, Page.PreviousIndex, caption, !Page.HasPrevious);
147 private void WriteNext(StringWriter writer)
149 string caption = "next &raquo;";
150 if (Context.HasSection(NextSection))
152 TextWriter capWriter = new StringWriter();
153 Context.RenderSection(NextSection, capWriter);
154 caption = capWriter.ToString().Trim();
156 WriteLink(writer, Page.NextIndex, caption, !Page.HasNext);
159 private void WriteElipsis(TextWriter writer)
161 writer.Write("&#8230;");
164 private void WriteNumberedLinks(TextWriter writer, int startIndex, int endIndex)
166 for (int i = startIndex; i <= endIndex; i++)
168 WriteNumberedLink(writer, i);
172 private void WriteLink(TextWriter writer, int index, string text, bool disabled)
174 if (disabled)
176 if (UseInlineStyle)
178 writer.Write(String.Format("<span style=\"color: #DDD; padding: 2px 5px 2px 5px; margin: 2px; border: 1px solid #EEE;\">{0}</span>", text));
180 else
182 writer.Write(String.Format("<span class=\"disabled\">{0}</span>", text));
185 else
187 WritePageLink(writer, index, text, null);
191 private void WriteNumberedLink(TextWriter writer, int index)
193 if (index == Page.CurrentIndex)
195 if (UseInlineStyle)
197 writer.Write(String.Format("\r\n<span class=\"font-weight: bold; background-color: #000099; color: #FFF; padding: 2px 5px 2px 5px; margin: 2px; border: 1px solid #000099;\">{0}</span>\r\n", index));
199 else
201 writer.Write(String.Format("\r\n<span class=\"current\">{0}</span>\r\n", index));
204 else
206 WritePageLink(writer, index, index.ToString(), null);
210 /// <summary>
211 /// Writes the Page link.
212 /// </summary>
213 /// <param name="writer">The writer.</param>
214 /// <param name="pageIndex">Index of the page.</param>
215 /// <param name="text">The text.</param>
216 /// <param name="htmlAttributes">The HTML attributes.</param>
217 protected void WritePageLink(TextWriter writer, int pageIndex, String text, IDictionary htmlAttributes)
219 string url = CreateUrlForPage(pageIndex);
221 if (Context.HasSection(LinkSection))
223 PropertyBag["pageIndex"] = pageIndex;
224 PropertyBag["text"] = text;
225 PropertyBag["url"] = url;
227 Context.RenderSection(LinkSection, writer);
229 else
231 String href;
233 if (PaginateFunction != null)
235 href = "javascript:" + PaginateFunction + "(" + pageIndex + ");void(0);";
237 else
239 href = url;
242 if (UseInlineStyle)
244 writer.Write(String.Format("<a style=\"color: #000099;text-decoration: none;padding: 2px 5px 2px 5px;margin: 2px;border: 1px solid #AAAFEE;\" href=\"{0}\">{1}</a>\r\n", href, text));
246 else
248 writer.Write(String.Format("<a href=\"{0}\">{1}</a>\r\n", href, text));