1 //
2 // System.Web.UI.WebControls.NumericPagerField
3 //
4 // Authors:
5 //   Marek Habersack (mhabersack@novell.com)
6 //
7 // (C) 2007-2010 Novell, Inc
8 //
9 
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 using System;
31 using System.Globalization;
32 using System.Security.Permissions;
33 using System.Web;
34 using System.Web.UI;
35 
36 namespace System.Web.UI.WebControls
37 {
38 	[AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
39 	[AspNetHostingPermissionAttribute(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
40 	public class NumericPagerField : DataPagerField
41 	{
42 		const string Default_NextPageText = "...";
43 		const string Default_PreviousPageText = "...";
44 
45 		int _startRowIndex;
46 		int _maximumRows;
47 		int _totalRowCount;
48 		int _fieldIndex;
49 		bool _renderNonBreakingSpacesBetweenControls = true;
50 
NumericPagerField()51 		public NumericPagerField ()
52 		{
53 		}
54 
CopyProperties(DataPagerField newField)55 		protected override void CopyProperties (DataPagerField newField)
56 		{
57 			base.CopyProperties (newField);
58 
59 			NumericPagerField field = newField as NumericPagerField;
60 			if (field == null)
61 				return;
62 
63 			field.ButtonCount = ButtonCount;
64 			field.ButtonType = ButtonType;
65 			field.CurrentPageLabelCssClass = CurrentPageLabelCssClass;
66 			field.NextPageImageUrl = NextPageImageUrl;
67 			field.NextPageText = NextPageText;
68 			field.NextPreviousButtonCssClass = NextPreviousButtonCssClass;
69 			field.NumericButtonCssClass = NumericButtonCssClass;
70 			field.PreviousPageImageUrl = PreviousPageImageUrl;
71 			field.PreviousPageText = PreviousPageText;
72 			field.RenderNonBreakingSpacesBetweenControls = RenderNonBreakingSpacesBetweenControls;
73 		}
74 
CreateDataPagers(DataPagerFieldItem container, int startRowIndex, int maximumRows, int totalRowCount, int fieldIndex)75 		public override void CreateDataPagers (DataPagerFieldItem container, int startRowIndex, int maximumRows, int totalRowCount, int fieldIndex)
76 		{
77 			_startRowIndex = startRowIndex;
78 			_maximumRows = maximumRows;
79 			_totalRowCount = totalRowCount;
80 			_fieldIndex = fieldIndex;
81 
82 			bool setPagePropertiesNeeded = false;
83 			bool queryMode = GetQueryModeStartRowIndex (_totalRowCount, _maximumRows, ref _startRowIndex, ref setPagePropertiesNeeded);
84 			bool addNonBreakingSpace = RenderNonBreakingSpacesBetweenControls;
85 			int buttonCount = ButtonCount;
86 			int totalPages = totalRowCount / maximumRows + (totalRowCount % maximumRows > 0 ? 1 : 0);
87 			int currentPage = startRowIndex == 0 ? 1 : (startRowIndex / maximumRows) + 1;
88 			int activePage = ((startRowIndex / (maximumRows * buttonCount)) * buttonCount) + 1;
89 			int lastPage = activePage + buttonCount - 1;
90 
91 			bool showPreviousPage = activePage > buttonCount;
92 			bool showNextPage = totalPages - activePage >= buttonCount;
93 
94 			if (lastPage > totalPages)
95 				lastPage = totalPages;
96 
97 			int newPageNum;
98 			if (showPreviousPage) {
99 				newPageNum = activePage - 1;
100 				if (newPageNum < 1)
101 					newPageNum = 1;
102 
103 				CreateButton (container, DataControlCommands.PreviousPageCommandArgument, PreviousPageText, PreviousPageImageUrl,
104 					      NextPreviousButtonCssClass, newPageNum, queryMode, true, addNonBreakingSpace, false);
105 			}
106 
107 			string numericButtonCssClass = NumericButtonCssClass;
108 			bool enabled;
109 			string pageString;
110 			while (activePage <= lastPage) {
111 				enabled = activePage != currentPage;
112 				pageString = activePage.ToString (CultureInfo.InvariantCulture);
113 				CreateButton (container, pageString, pageString, String.Empty,
114 					      enabled ? numericButtonCssClass : CurrentPageLabelCssClass, activePage,
115 					      queryMode, enabled, addNonBreakingSpace, true);
116 				activePage++;
117 			}
118 			if (showNextPage && addNonBreakingSpace)
119 					container.Controls.Add (new LiteralControl ("&nbsp;"));
120 
121 			if (showNextPage)
122 				CreateButton (container, DataControlCommands.NextPageCommandArgument, NextPageText, NextPageImageUrl,
123 					      NextPreviousButtonCssClass, activePage, queryMode, true, addNonBreakingSpace, false);
124 
125 			if (setPagePropertiesNeeded)
126 				DataPager.SetPageProperties (_startRowIndex, _maximumRows, true);
127 		}
128 
CreateButton(DataPagerFieldItem container, string commandName, string text, string imageUrl, string cssClass, int pageNum, bool queryMode, bool enabled, bool addNonBreakingSpace, bool isPageNumber)129 		void CreateButton (DataPagerFieldItem container, string commandName, string text, string imageUrl, string cssClass, int pageNum,
130 				   bool queryMode, bool enabled, bool addNonBreakingSpace, bool isPageNumber)
131 		{
132 			WebControl ctl = null;
133 
134 			if (queryMode) {
135 				if (isPageNumber && !enabled) {
136 					var span = new Label ();
137 					span.Text = text;
138 					span.CssClass = cssClass;
139 					ctl = span;
140 				} else {
141 					HyperLink h = new HyperLink ();
142 					h.Text = text;
143 					h.ImageUrl = imageUrl;
144 					h.Enabled = enabled;
145 					h.NavigateUrl = GetQueryStringNavigateUrl (pageNum);
146 					h.CssClass = cssClass;
147 					ctl = h;
148 				}
149 			} else {
150 				if (!enabled) {
151 					Label l = new Label ();
152 					l.Text = text;
153 					l.CssClass = cssClass;
154 					ctl = l;
155 				} else {
156 					switch (ButtonType) {
157 						case ButtonType.Button:
158 							Button btn = new Button ();
159 							btn.CommandName = commandName;
160 							btn.CommandArgument = pageNum.ToString ();
161 							btn.Text = text;
162 							break;
163 
164 						case ButtonType.Link:
165 							LinkButton lbtn = new LinkButton ();
166 							lbtn.CommandName = commandName;
167 							lbtn.CommandArgument = pageNum.ToString ();
168 							lbtn.Text = text;
169 							ctl = lbtn;
170 							break;
171 
172 						case ButtonType.Image:
173 							ImageButton ibtn = new ImageButton ();
174 							ibtn.CommandName = commandName;
175 							ibtn.CommandArgument = pageNum.ToString ();
176 							ibtn.ImageUrl = imageUrl;
177 							ibtn.AlternateText = text;
178 							ctl = ibtn;
179 							break;
180 					}
181 
182 					if (ctl != null)
183 						ctl.CssClass = cssClass;
184 				}
185 			}
186 
187 			if (ctl != null) {
188 				container.Controls.Add (ctl);
189 				if (addNonBreakingSpace)
190 					container.Controls.Add (new LiteralControl ("&nbsp;"));
191 			}
192 		}
CreateField()193 		protected override DataPagerField CreateField ()
194 		{
195 			return new NumericPagerField ();
196 		}
197 
Equals(object o)198 		public override bool Equals (object o)
199 		{
200 			NumericPagerField field = o as NumericPagerField;
201 
202 			if (field == null)
203 				return false;
204 
205 			if (field.ButtonCount != ButtonCount)
206 				return false;
207 
208 			if (field.ButtonType != ButtonType)
209 				return false;
210 
211 			if (String.Compare (field.CurrentPageLabelCssClass, CurrentPageLabelCssClass, StringComparison.Ordinal) != 0)
212 				return false;
213 
214 			if (String.Compare (field.NextPageImageUrl, NextPageImageUrl, StringComparison.Ordinal) != 0)
215 				return false;
216 
217 			if (String.Compare (field.NextPageText, NextPageText, StringComparison.Ordinal) != 0)
218 				return false;
219 
220 			if (String.Compare (field.NextPreviousButtonCssClass, NextPreviousButtonCssClass, StringComparison.Ordinal) != 0)
221 				return false;
222 
223 			if (String.Compare (field.NumericButtonCssClass, NumericButtonCssClass, StringComparison.Ordinal) != 0)
224 				return false;
225 
226 			if (String.Compare (field.PreviousPageImageUrl, PreviousPageImageUrl, StringComparison.Ordinal) != 0)
227 				return false;
228 
229 			if (String.Compare (field.PreviousPageText, PreviousPageText, StringComparison.Ordinal) != 0)
230 				return false;
231 
232 			if (field.RenderNonBreakingSpacesBetweenControls != RenderNonBreakingSpacesBetweenControls)
233 				return false;
234 
235 			return true;
236 		}
237 
GetHashCode()238 		public override int GetHashCode ()
239 		{
240 			int ret = 0;
241 
242 			// Base the calculation on the properties that are copied in CopyProperties
243 			ret |= ButtonCount.GetHashCode ();
244 			ret |= ButtonType.GetHashCode ();
245 			ret |= CurrentPageLabelCssClass.GetHashCode ();
246 			ret |= NextPageImageUrl.GetHashCode ();
247 			ret |= NextPageText.GetHashCode ();
248 			ret |= NextPreviousButtonCssClass.GetHashCode ();
249 			ret |= NumericButtonCssClass.GetHashCode ();
250 			ret |= PreviousPageImageUrl.GetHashCode ();
251 			ret |= PreviousPageText.GetHashCode ();
252 			ret |= RenderNonBreakingSpacesBetweenControls.GetHashCode ();
253 
254 			return ret;
255 		}
256 
HandleEvent(CommandEventArgs e)257 		public override void HandleEvent (CommandEventArgs e)
258 		{
259 			string commandName = e.CommandName;
260 			int pageNum;
261 
262 			if (!Int32.TryParse (e.CommandArgument as string, out pageNum))
263 				pageNum = 0;
264 			else if (pageNum >= 1)
265 				pageNum--;
266 			else if (pageNum < 0)
267 				pageNum = 0;
268 
269 			int newStartIndex = -1;
270 			int pageSize = DataPager.PageSize;
271 			int offset = pageSize * pageNum;
272 
273 			if (String.Compare (commandName, DataControlCommands.NextPageCommandArgument, StringComparison.OrdinalIgnoreCase) == 0 ||
274 			    String.Compare (commandName, DataControlCommands.PreviousPageCommandArgument, StringComparison.OrdinalIgnoreCase) == 0) {
275 				newStartIndex = offset;
276 			} else
277 				newStartIndex = (Int32.Parse (commandName) - 1) * pageSize;
278 
279 			if (newStartIndex != -1)
280 				DataPager.SetPageProperties (newStartIndex, pageSize, true);
281 		}
282 
283 		public int ButtonCount {
284 			get {
285 				object o = ViewState ["ButtonCount"];
286 				if (o != null)
287 					return (int)o;
288 
289 				return 5;
290 			}
291 
292 			set {
293 				if (value < 1)
294 					throw new ArgumentOutOfRangeException ("value", "The ButtonCount property is set to a value less than 1.");
295 
296 				ViewState ["ButtonCount"] = value;
297 			}
298 		}
299 
300 		public ButtonType ButtonType {
301 			get {
302 				object o = ViewState ["ButtonType"];
303 				if (o != null)
304 					return (ButtonType)o;
305 
306 				return ButtonType.Link;
307 			}
308 
309 			set {
310 				if (!Enum.IsDefined (typeof (ButtonType), value))
311 					throw new ArgumentOutOfRangeException ("value", "The value for the ButtonType property is not one of the ButtonType values.");
312 
313 				ViewState ["ButtonType"] = value;
314 			}
315 		}
316 
317 		public string CurrentPageLabelCssClass {
318 			get {
319 				string s = ViewState ["CurrentPageLabelCssClass"] as string;
320 				if (s != null)
321 					return s;
322 
323 				return String.Empty;
324 			}
325 
326 			set {
327 				if (String.IsNullOrEmpty (value))
328 					return;
329 
330 				ViewState ["CurrentPageLabelCssClass"] = value;
331 			}
332 		}
333 
334 		public string NextPageImageUrl {
335 			get {
336 				string s = ViewState ["NextPageImageUrl"] as string;
337 				if (s != null)
338 					return s;
339 
340 				return String.Empty;
341 			}
342 
343 			set {
344 				if (String.IsNullOrEmpty (value))
345 					return;
346 
347 				ViewState ["NextPageImageUrl"] = value;
348 			}
349 		}
350 
351 		public string NextPageText {
352 			get {
353 				string s = ViewState ["NextPageText"] as string;
354 				if (s != null)
355 					return s;
356 
357 				return Default_NextPageText;
358 			}
359 
360 			set {
361 				if (String.IsNullOrEmpty (value) || String.Compare (Default_NextPageText, value, StringComparison.Ordinal) == 0)
362 					return;
363 
364 				ViewState ["NextPageText"] = value;
365 			}
366 		}
367 
368 		public string NextPreviousButtonCssClass {
369 			get {
370 				string s = ViewState ["NextPreviousButtonCssClass"] as string;
371 				if (s != null)
372 					return s;
373 
374 				return String.Empty;
375 			}
376 
377 			set {
378 				if (String.IsNullOrEmpty (value))
379 					return;
380 
381 				ViewState ["NextPreviousButtonCssClass"] = value;
382 			}
383 		}
384 
385 		public string NumericButtonCssClass {
386 			get {
387 				string s = ViewState ["NumericButtonCssClass"] as string;
388 				if (s != null)
389 					return s;
390 
391 				return String.Empty;
392 			}
393 
394 			set {
395 				if (String.IsNullOrEmpty (value))
396 					return;
397 
398 				ViewState ["NumericButtonCssClass"] = value;
399 			}
400 		}
401 
402 		public string PreviousPageImageUrl {
403 			get {
404 				string s = ViewState ["PreviousPageImageUrl"] as string;
405 				if (s != null)
406 					return s;
407 
408 				return String.Empty;
409 			}
410 
411 			set {
412 				if (String.IsNullOrEmpty (value))
413 					return;
414 
415 				ViewState ["PreviousPageImageUrl"] = value;
416 			}
417 		}
418 
419 		public string PreviousPageText {
420 			get {
421 				string s = ViewState ["PreviousPageText"] as string;
422 				if (s != null)
423 					return s;
424 
425 				return Default_PreviousPageText;
426 			}
427 
428 			set {
429 				if (String.IsNullOrEmpty (value) || String.Compare (Default_PreviousPageText, value, StringComparison.Ordinal) == 0)
430 					return;
431 
432 				ViewState ["PreviousPageText"] = value;
433 			}
434 		}
435 
436 		public bool RenderNonBreakingSpacesBetweenControls {
437 			get { return _renderNonBreakingSpacesBetweenControls; }
438 			set { _renderNonBreakingSpacesBetweenControls = value; }
439 		}
440 	}
441 }
442