Completed
Branch master (4dc390)
by Fabio
30:44
created

TDataList::getSelectedItemStyle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 9
rs 9.6666
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
/**
3
 * TDataList class file
4
 *
5
 * @author Qiang Xue <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2015 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
9
 * @package System.Web.UI.WebControls
10
 */
11
12
/**
13
 * Includes TBaseDataList class
14
 */
15
Prado::using('System.Web.UI.WebControls.TBaseDataList');
16
/**
17
 * Includes TRepeatInfo class
18
 */
19
Prado::using('System.Web.UI.WebControls.TRepeatInfo');
20
21
/**
22
 * TDataList class
23
 *
24
 * TDataList represents a data bound and updatable list control.
25
 *
26
 * Like {@link TRepeater}, TDataList displays its content repeatedly based on
27
 * the data fetched from {@link setDataSource DataSource}.
28
 * The repeated contents in TDataList are called items, which are controls and
29
 * can be accessed through {@link getItems Items}. When {@link dataBind()} is
30
 * invoked, TDataList creates an item for each row of data and binds the data
31
 * row to the item. Optionally, a TDataList can have a header, a footer and/or
32
 * separators between items.
33
 *
34
 * TDataList differs from {@link TRepeater} in that it supports tiling the items
35
 * in different manners and it maintains status of items to handle data update.
36
 *
37
 * The layout of the repeated contents are specified by inline templates.
38
 * TDataList items, header, footer, etc. are being instantiated with the corresponding
39
 * templates when data is being bound to the repeater.
40
 *
41
 * Since v3.1.0, the layout can also be by renderers. A renderer is a control class
42
 * that can be instantiated as datalist items, header, etc. A renderer can thus be viewed
43
 * as an external template (in fact, it can also be non-templated controls).
44
 *
45
 * A renderer can be any control class.
46
 * - If the class implements {@link IDataRenderer}, the <b>Data</b>
47
 * property will be set as the data row during databinding. Many PRADO controls
48
 * implement this interface, such as {@link TLabel}, {@link TTextBox}, etc.
49
 * - If the class implements {@link IItemDataRenderer}, the <b>ItemIndex</b> property will be set
50
 * as the zero-based index of the item in the datalist item collection, and
51
 * the <b>ItemType</b> property as the item's type (such as TListItemType::Item).
52
 * {@link TDataListItemRenderer} may be used as the convenient base class which
53
 * already implements {@link IDataItemRenderer}.
54
 *
55
 * The following properties are used to specify different types of template and renderer
56
 * for a datalist:
57
 * - {@link setItemTemplate ItemTemplate}, {@link setItemRenderer ItemRenderer}:
58
 * for each repeated row of data
59
 * - {@link setAlternatingItemTemplate AlternatingItemTemplate}, {@link setAlternatingItemRenderer AlternatingItemRenderer}:
60
 * for each alternating row of data. If not set, {@link setItemTemplate ItemTemplate} or {@link setItemRenderer ItemRenderer}
61
 * will be used instead.
62
 * - {@link setHeaderTemplate HeaderTemplate}, {@link setHeaderRenderer HeaderRenderer}:
63
 * for the datalist header.
64
 * - {@link setFooterTemplate FooterTemplate}, {@link setFooterRenderer FooterRenderer}:
65
 * for the datalist footer.
66
 * - {@link setSeparatorTemplate SeparatorTemplate}, {@link setSeparatorRenderer SeparatorRenderer}:
67
 * for content to be displayed between items.
68
 * - {@link setEmptyTemplate EmptyTemplate}, {@link setEmptyRenderer EmptyRenderer}:
69
 * used when data bound to the datalist is empty.
70
 * - {@link setEditItemTemplate EditItemTemplate}, {@link setEditItemRenderer EditItemRenderer}:
71
 * for the row being editted.
72
 * - {@link setSelectedItemTemplate SelectedItemTemplate}, {@link setSelectedItemRenderer SelectedItemRenderer}:
73
 * for the row being selected.
74
 *
75
 * If a content type is defined with both a template and a renderer, the latter takes precedence.
76
 *
77
 * When {@link dataBind()} is being called, TDataList undergoes the following lifecycles for each row of data:
78
 * - create item based on templates or renderers
79
 * - set the row of data to the item
80
 * - raise {@link onItemCreated OnItemCreated}:
81
 * - add the item as a child control
82
 * - call dataBind() of the item
83
 * - raise {@link onItemDataBound OnItemDataBound}:
84
 *
85
 * TDataList raises an {@link onItemCommand OnItemCommand} whenever a button control
86
 * within some datalist item raises a <b>OnCommand</b> event. Therefore,
87
 * you can handle all sorts of <b>OnCommand</b> event in a central place by
88
 * writing an event handler for {@link onItemCommand OnItemCommand}.
89
 *
90
 * An additional event is raised if the <b>OnCommand</b> event has one of the following
91
 * command names:
92
 * - edit: user wants to edit an item. <b>OnEditCommand</b> event will be raised.
93
 * - update: user wants to save the change to an item. <b>OnUpdateCommand</b> event will be raised.
94
 * - select: user selects an item. <b>OnSelectedIndexChanged</b> event will be raised.
95
 * - delete: user deletes an item. <b>OnDeleteCommand</b> event will be raised.
96
 * - cancel: user cancels previously editting action. <b>OnCancelCommand</b> event will be raised.
97
 *
98
 * TDataList provides a few properties to support tiling the items.
99
 * The number of columns used to display the data items is specified via
100
 * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection}
101
 * governs the order of the items being rendered.
102
 * The layout of the data items in the list is specified via {@link setRepeatLayout RepeatLayout},
103
 * which can take one of the following values:
104
 * - Table (default): items are organized using HTML table and cells.
105
 * When using this layout, one can set {@link setCellPadding CellPadding} and
106
 * {@link setCellSpacing CellSpacing} to adjust the cellpadding and cellpadding
107
 * of the table, and {@link setCaption Caption} and {@link setCaptionAlign CaptionAlign}
108
 * to add a table caption with the specified alignment.
109
 * - Flow: items are organized using HTML spans and breaks.
110
 * - Raw: TDataList does not generate any HTML tags to do the tiling.
111
 *
112
 * Items in TDataList can be in one of the three status: normal browsing,
113
 * being editted and being selected. To change the status of a particular
114
 * item, set {@link setSelectedItemIndex SelectedItemIndex} or
115
 * {@link setEditItemIndex EditItemIndex}. The former will change
116
 * the indicated item to selected mode, which will cause the item to
117
 * use {@link setSelectedItemTemplate SelectedItemTemplate} or
118
 * {@link setSelectedItemRenderer SelectedItemRenderer} for presentation.
119
 * The latter will change the indicated item to edit mode and to use corresponding
120
 * template or renderer.
121
 * Note, if an item is in edit mode, then selecting this item will have no effect.
122
 *
123
 * Different styles may be applied to items in different status. The style
124
 * application is performed in a hierarchical way: Style in higher hierarchy
125
 * will inherit from styles in lower hierarchy.
126
 * Starting from the lowest hierarchy, the item styles include
127
 * - item's own style
128
 * - {@link getItemStyle ItemStyle}
129
 * - {@link getAlternatingItemStyle AlternatingItemStyle}
130
 * - {@link getSelectedItemStyle SelectedItemStyle}
131
 * - {@link getEditItemStyle EditItemStyle}.
132
 * Therefore, if background color is set as red in {@link getItemStyle ItemStyle},
133
 * {@link getEditItemStyle EditItemStyle} will also have red background color
134
 * unless it is set to a different value explicitly.
135
 *
136
 * When a page containing a datalist is post back, the datalist will restore automatically
137
 * all its contents, including items, header, footer and separators.
138
 * However, the data row associated with each item will not be recovered and become null.
139
 * To access the data, use one of the following ways:
140
 * - Use {@link getDataKeys DataKeys} to obtain the data key associated with
141
 * the specified datalist item and use the key to fetch the corresponding data
142
 * from some persistent storage such as DB.
143
 * - Save the whole dataset in viewstate, which will restore the dataset automatically upon postback.
144
 * Be aware though, if the size of your dataset is big, your page size will become big. Some
145
 * complex data may also have serializing problem if saved in viewstate.
146
 *
147
 * @author Qiang Xue <[email protected]>
148
 * @package System.Web.UI.WebControls
149
 * @since 3.0
150
 */
151
class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUser
152
{
153
	/**
154
	 * Command name that TDataList understands. They are case-insensitive.
155
	 */
156
	const CMD_SELECT='Select';
157
	const CMD_EDIT='Edit';
158
	const CMD_UPDATE='Update';
159
	const CMD_DELETE='Delete';
160
	const CMD_CANCEL='Cancel';
161
162
	/**
163
	 * @var TDataListItemCollection item list
164
	 */
165
	private $_items=null;
166
	/**
167
	 * @var Itemplate various item templates
168
	 */
169
	private $_itemTemplate=null;
170
	private $_emptyTemplate=null;
171
	private $_alternatingItemTemplate=null;
172
	private $_selectedItemTemplate=null;
173
	private $_editItemTemplate=null;
174
	private $_headerTemplate=null;
175
	private $_footerTemplate=null;
176
	private $_separatorTemplate=null;
177
	/**
178
	 * @var TControl header item
179
	 */
180
	private $_header=null;
181
	/**
182
	 * @var TControl footer item
183
	 */
184
	private $_footer=null;
185
186
	/**
187
	 * @return TDataListItemCollection item list
188
	 */
189
	public function getItems()
190
	{
191
		if(!$this->_items)
192
			$this->_items=new TDataListItemCollection;
193
		return $this->_items;
194
	}
195
196
	/**
197
	 * @return integer number of items
198
	 */
199
	public function getItemCount()
200
	{
201
		return $this->_items?$this->_items->getCount():0;
202
	}
203
204
	/**
205
	 * @return string the class name for datalist items. Defaults to empty, meaning not set.
206
	 * @since 3.1.0
207
	 */
208
	public function getItemRenderer()
209
	{
210
		return $this->getViewState('ItemRenderer','');
211
	}
212
213
	/**
214
	 * Sets the item renderer class.
215
	 *
216
	 * If not empty, the class will be used to instantiate as datalist items.
217
	 * This property takes precedence over {@link getItemTemplate ItemTemplate}.
218
	 *
219
	 * @param string the renderer class name in namespace format.
220
	 * @see setItemTemplate
221
	 * @since 3.1.0
222
	 */
223
	public function setItemRenderer($value)
224
	{
225
		$this->setViewState('ItemRenderer',$value,'');
226
	}
227
228
	/**
229
	 * @return string the class name for alternative datalist items. Defaults to empty, meaning not set.
230
	 * @since 3.1.0
231
	 */
232
	public function getAlternatingItemRenderer()
233
	{
234
		return $this->getViewState('AlternatingItemRenderer','');
235
	}
236
237
	/**
238
	 * Sets the alternative item renderer class.
239
	 *
240
	 * If not empty, the class will be used to instantiate as alternative datalist items.
241
	 * This property takes precedence over {@link getAlternatingItemTemplate AlternatingItemTemplate}.
242
	 *
243
	 * @param string the renderer class name in namespace format.
244
	 * @see setAlternatingItemTemplate
245
	 * @since 3.1.0
246
	 */
247
	public function setAlternatingItemRenderer($value)
248
	{
249
		$this->setViewState('AlternatingItemRenderer',$value,'');
250
	}
251
252
	/**
253
	 * @return string the class name for the datalist item being editted. Defaults to empty, meaning not set.
254
	 * @since 3.1.0
255
	 */
256
	public function getEditItemRenderer()
257
	{
258
		return $this->getViewState('EditItemRenderer','');
259
	}
260
261
	/**
262
	 * Sets the renderer class for the datalist item being editted.
263
	 *
264
	 * If not empty, the class will be used to instantiate as the datalist item.
265
	 * This property takes precedence over {@link getEditItemTemplate EditItemTemplate}.
266
	 *
267
	 * @param string the renderer class name in namespace format.
268
	 * @see setEditItemTemplate
269
	 * @since 3.1.0
270
	 */
271
	public function setEditItemRenderer($value)
272
	{
273
		$this->setViewState('EditItemRenderer',$value,'');
274
	}
275
276
	/**
277
	 * @return string the class name for the datalist item being selected. Defaults to empty, meaning not set.
278
	 * @since 3.1.0
279
	 */
280
	public function getSelectedItemRenderer()
281
	{
282
		return $this->getViewState('SelectedItemRenderer','');
283
	}
284
285
	/**
286
	 * Sets the renderer class for the datalist item being selected.
287
	 *
288
	 * If not empty, the class will be used to instantiate as the datalist item.
289
	 * This property takes precedence over {@link getSelectedItemTemplate SelectedItemTemplate}.
290
	 *
291
	 * @param string the renderer class name in namespace format.
292
	 * @see setSelectedItemTemplate
293
	 * @since 3.1.0
294
	 */
295
	public function setSelectedItemRenderer($value)
296
	{
297
		$this->setViewState('SelectedItemRenderer',$value,'');
298
	}
299
300
	/**
301
	 * @return string the class name for datalist item separators. Defaults to empty, meaning not set.
302
	 * @since 3.1.0
303
	 */
304
	public function getSeparatorRenderer()
305
	{
306
		return $this->getViewState('SeparatorRenderer','');
307
	}
308
309
	/**
310
	 * Sets the datalist item separator renderer class.
311
	 *
312
	 * If not empty, the class will be used to instantiate as datalist item separators.
313
	 * This property takes precedence over {@link getSeparatorTemplate SeparatorTemplate}.
314
	 *
315
	 * @param string the renderer class name in namespace format.
316
	 * @see setSeparatorTemplate
317
	 * @since 3.1.0
318
	 */
319
	public function setSeparatorRenderer($value)
320
	{
321
		$this->setViewState('SeparatorRenderer',$value,'');
322
	}
323
324
	/**
325
	 * @return string the class name for datalist header item. Defaults to empty, meaning not set.
326
	 * @since 3.1.0
327
	 */
328
	public function getHeaderRenderer()
329
	{
330
		return $this->getViewState('HeaderRenderer','');
331
	}
332
333
	/**
334
	 * Sets the datalist header renderer class.
335
	 *
336
	 * If not empty, the class will be used to instantiate as datalist header item.
337
	 * This property takes precedence over {@link getHeaderTemplate HeaderTemplate}.
338
	 *
339
	 * @param string the renderer class name in namespace format.
340
	 * @see setHeaderTemplate
341
	 * @since 3.1.0
342
	 */
343
	public function setHeaderRenderer($value)
344
	{
345
		$this->setViewState('HeaderRenderer',$value,'');
346
	}
347
348
	/**
349
	 * @return string the class name for datalist footer item. Defaults to empty, meaning not set.
350
	 * @since 3.1.0
351
	 */
352
	public function getFooterRenderer()
353
	{
354
		return $this->getViewState('FooterRenderer','');
355
	}
356
357
	/**
358
	 * Sets the datalist footer renderer class.
359
	 *
360
	 * If not empty, the class will be used to instantiate as datalist footer item.
361
	 * This property takes precedence over {@link getFooterTemplate FooterTemplate}.
362
	 *
363
	 * @param string the renderer class name in namespace format.
364
	 * @see setFooterTemplate
365
	 * @since 3.1.0
366
	 */
367
	public function setFooterRenderer($value)
368
	{
369
		$this->setViewState('FooterRenderer',$value,'');
370
	}
371
372
	/**
373
	 * @return string the class name for empty datalist item. Defaults to empty, meaning not set.
374
	 * @since 3.1.0
375
	 */
376
	public function getEmptyRenderer()
377
	{
378
		return $this->getViewState('EmptyRenderer','');
379
	}
380
381
	/**
382
	 * Sets the datalist empty renderer class.
383
	 *
384
	 * The empty renderer is created as the child of the datalist
385
	 * if data bound to the datalist is empty.
386
	 * This property takes precedence over {@link getEmptyTemplate EmptyTemplate}.
387
	 *
388
	 * @param string the renderer class name in namespace format.
389
	 * @see setEmptyTemplate
390
	 * @since 3.1.0
391
	 */
392
	public function setEmptyRenderer($value)
393
	{
394
		$this->setViewState('EmptyRenderer',$value,'');
395
	}
396
397
	/**
398
	 * @return ITemplate the template for item
399
	 */
400
	public function getItemTemplate()
401
	{
402
		return $this->_itemTemplate;
403
	}
404
405
	/**
406
	 * @param ITemplate the template for item
407
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
408
	 */
409
	public function setItemTemplate($value)
410
	{
411
		if($value instanceof ITemplate || $value===null)
412
			$this->_itemTemplate=$value;
413
		else
414
			throw new TInvalidDataTypeException('datalist_template_required','ItemTemplate');
415
	}
416
417
	/**
418
	 * @return TTableItemStyle the style for item
419
	 */
420
	public function getItemStyle()
421
	{
422
		if(($style=$this->getViewState('ItemStyle',null))===null)
423
		{
424
			$style=new TTableItemStyle;
425
			$this->setViewState('ItemStyle',$style,null);
426
		}
427
		return $style;
428
	}
429
430
	/**
431
	 * @return ITemplate the template for each alternating item
432
	 */
433
	public function getAlternatingItemTemplate()
434
	{
435
		return $this->_alternatingItemTemplate;
436
	}
437
438
	/**
439
	 * @param ITemplate the template for each alternating item
440
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
441
	 */
442
	public function setAlternatingItemTemplate($value)
443
	{
444
		if($value instanceof ITemplate || $value===null)
445
			$this->_alternatingItemTemplate=$value;
446
		else
447
			throw new TInvalidDataTypeException('datalist_template_required','AlternatingItemType');
448
	}
449
450
	/**
451
	 * @return TTableItemStyle the style for each alternating item
452
	 */
453
	public function getAlternatingItemStyle()
454
	{
455
		if(($style=$this->getViewState('AlternatingItemStyle',null))===null)
456
		{
457
			$style=new TTableItemStyle;
458
			$this->setViewState('AlternatingItemStyle',$style,null);
459
		}
460
		return $style;
461
	}
462
463
	/**
464
	 * @return ITemplate the selected item template
465
	 */
466
	public function getSelectedItemTemplate()
467
	{
468
		return $this->_selectedItemTemplate;
469
	}
470
471
	/**
472
	 * @param ITemplate the selected item template
473
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
474
	 */
475
	public function setSelectedItemTemplate($value)
476
	{
477
		if($value instanceof ITemplate || $value===null)
478
			$this->_selectedItemTemplate=$value;
479
		else
480
			throw new TInvalidDataTypeException('datalist_template_required','SelectedItemTemplate');
481
	}
482
483
	/**
484
	 * @return TTableItemStyle the style for selected item
485
	 */
486
	public function getSelectedItemStyle()
487
	{
488
		if(($style=$this->getViewState('SelectedItemStyle',null))===null)
489
		{
490
			$style=new TTableItemStyle;
491
			$this->setViewState('SelectedItemStyle',$style,null);
492
		}
493
		return $style;
494
	}
495
496
	/**
497
	 * @return ITemplate the edit item template
498
	 */
499
	public function getEditItemTemplate()
500
	{
501
		return $this->_editItemTemplate;
502
	}
503
504
	/**
505
	 * @param ITemplate the edit item template
506
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
507
	 */
508
	public function setEditItemTemplate($value)
509
	{
510
		if($value instanceof ITemplate || $value===null)
511
			$this->_editItemTemplate=$value;
512
		else
513
			throw new TInvalidDataTypeException('datalist_template_required','EditItemTemplate');
514
	}
515
516
	/**
517
	 * @return TTableItemStyle the style for edit item
518
	 */
519
	public function getEditItemStyle()
520
	{
521
		if(($style=$this->getViewState('EditItemStyle',null))===null)
522
		{
523
			$style=new TTableItemStyle;
524
			$this->setViewState('EditItemStyle',$style,null);
525
		}
526
		return $style;
527
	}
528
529
	/**
530
	 * @return ITemplate the header template
531
	 */
532
	public function getHeaderTemplate()
533
	{
534
		return $this->_headerTemplate;
535
	}
536
537
	/**
538
	 * @param ITemplate the header template
539
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
540
	 */
541
	public function setHeaderTemplate($value)
542
	{
543
		if($value instanceof ITemplate || $value===null)
544
			$this->_headerTemplate=$value;
545
		else
546
			throw new TInvalidDataTypeException('datalist_template_required','HeaderTemplate');
547
	}
548
549
	/**
550
	 * @return TTableItemStyle the style for header
551
	 */
552
	public function getHeaderStyle()
553
	{
554
		if(($style=$this->getViewState('HeaderStyle',null))===null)
555
		{
556
			$style=new TTableItemStyle;
557
			$this->setViewState('HeaderStyle',$style,null);
558
		}
559
		return $style;
560
	}
561
562
	/**
563
	 * @return TControl the header item
564
	 */
565
	public function getHeader()
566
	{
567
		return $this->_header;
568
	}
569
570
	/**
571
	 * @return ITemplate the footer template
572
	 */
573
	public function getFooterTemplate()
574
	{
575
		return $this->_footerTemplate;
576
	}
577
578
	/**
579
	 * @param ITemplate the footer template
580
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
581
	 */
582
	public function setFooterTemplate($value)
583
	{
584
		if($value instanceof ITemplate || $value===null)
585
			$this->_footerTemplate=$value;
586
		else
587
			throw new TInvalidDataTypeException('datalist_template_required','FooterTemplate');
588
	}
589
590
	/**
591
	 * @return TTableItemStyle the style for footer
592
	 */
593
	public function getFooterStyle()
594
	{
595
		if(($style=$this->getViewState('FooterStyle',null))===null)
596
		{
597
			$style=new TTableItemStyle;
598
			$this->setViewState('FooterStyle',$style,null);
599
		}
600
		return $style;
601
	}
602
603
	/**
604
	 * @return TControl the footer item
605
	 */
606
	public function getFooter()
607
	{
608
		return $this->_footer;
609
	}
610
611
	/**
612
	 * @return ITemplate the template applied when no data is bound to the datalist
613
	 */
614
	public function getEmptyTemplate()
615
	{
616
		return $this->_emptyTemplate;
617
	}
618
619
	/**
620
	 * @param ITemplate the template applied when no data is bound to the datalist
621
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
622
	 */
623
	public function setEmptyTemplate($value)
624
	{
625
		if($value instanceof ITemplate || $value===null)
626
			$this->_emptyTemplate=$value;
627
		else
628
			throw new TInvalidDataTypeException('datalist_template_required','EmptyTemplate');
629
	}
630
631
	/**
632
	 * @return ITemplate the separator template
633
	 */
634
	public function getSeparatorTemplate()
635
	{
636
		return $this->_separatorTemplate;
637
	}
638
639
	/**
640
	 * @param ITemplate the separator template
641
	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
642
	 */
643
	public function setSeparatorTemplate($value)
644
	{
645
		if($value instanceof ITemplate || $value===null)
646
			$this->_separatorTemplate=$value;
647
		else
648
			throw new TInvalidDataTypeException('datalist_template_required','SeparatorTemplate');
649
	}
650
651
	/**
652
	 * @return TTableItemStyle the style for separator
653
	 */
654
	public function getSeparatorStyle()
655
	{
656
		if(($style=$this->getViewState('SeparatorStyle',null))===null)
657
		{
658
			$style=new TTableItemStyle;
659
			$this->setViewState('SeparatorStyle',$style,null);
660
		}
661
		return $style;
662
	}
663
664
	/**
665
	 * @return integer the zero-based index of the selected item in {@link getItems Items}.
666
	 * A value -1 means no item selected.
667
	 */
668
	public function getSelectedItemIndex()
669
	{
670
		return $this->getViewState('SelectedItemIndex',-1);
671
	}
672
673
	/**
674
	 * Selects an item by its index in {@link getItems Items}.
675
	 * Previously selected item will be un-selected.
676
	 * If the item to be selected is already in edit mode, it will remain in edit mode.
677
	 * If the index is less than 0, any existing selection will be cleared up.
678
	 * @param integer the selected item index
679
	 */
680
	public function setSelectedItemIndex($value)
681
	{
682
		if(($value=TPropertyValue::ensureInteger($value))<0)
683
			$value=-1;
684
		if(($current=$this->getSelectedItemIndex())!==$value)
685
		{
686
			$this->setViewState('SelectedItemIndex',$value,-1);
687
			$items=$this->getItems();
688
			$itemCount=$items->getCount();
689
			if($current>=0 && $current<$itemCount)
690
			{
691
				$item=$items->itemAt($current);
692
				if(($item instanceof IItemDataRenderer) && $item->getItemType()!==TListItemType::EditItem)
693
					$item->setItemType($current%2?TListItemType::AlternatingItem : TListItemType::Item);
694
			}
695
			if($value>=0 && $value<$itemCount)
696
			{
697
				$item=$items->itemAt($value);
698
				if(($item instanceof IItemDataRenderer) && $item->getItemType()!==TListItemType::EditItem)
699
					$item->setItemType(TListItemType::SelectedItem);
700
			}
701
		}
702
	}
703
704
	/**
705
	 * @return TControl the selected item, null if no item is selected.
706
	 */
707
	public function getSelectedItem()
708
	{
709
		$index=$this->getSelectedItemIndex();
710
		$items=$this->getItems();
711
		if($index>=0 && $index<$items->getCount())
712
			return $items->itemAt($index);
713
		else
714
			return null;
715
	}
716
717
	/**
718
	 * @return mixed the key value of the currently selected item
719
	 * @throws TInvalidOperationException if {@link getDataKeyField DataKeyField} is empty.
720
	 */
721
	public function getSelectedDataKey()
722
	{
723
		if($this->getDataKeyField()==='')
724
			throw new TInvalidOperationException('datalist_datakeyfield_required');
725
		$index=$this->getSelectedItemIndex();
726
		$dataKeys=$this->getDataKeys();
727
		if($index>=0 && $index<$dataKeys->getCount())
728
			return $dataKeys->itemAt($index);
729
		else
730
			return null;
731
	}
732
733
	/**
734
	 * @return integer the zero-based index of the edit item in {@link getItems Items}.
735
	 * A value -1 means no item is in edit mode.
736
	 */
737
	public function getEditItemIndex()
738
	{
739
		return $this->getViewState('EditItemIndex',-1);
740
	}
741
742
	/**
743
	 * Edits an item by its index in {@link getItems Items}.
744
	 * Previously editting item will change to normal item state.
745
	 * If the index is less than 0, any existing edit item will be cleared up.
746
	 * @param integer the edit item index
747
	 */
748
	public function setEditItemIndex($value)
749
	{
750
		if(($value=TPropertyValue::ensureInteger($value))<0)
751
			$value=-1;
752
		if(($current=$this->getEditItemIndex())!==$value)
753
		{
754
			$this->setViewState('EditItemIndex',$value,-1);
755
			$items=$this->getItems();
756
			$itemCount=$items->getCount();
757
			if($current>=0 && $current<$itemCount)
758
				$items->itemAt($current)->setItemType($current%2?TListItemType::AlternatingItem : TListItemType::Item);
759
			if($value>=0 && $value<$itemCount)
760
				$items->itemAt($value)->setItemType(TListItemType::EditItem);
761
		}
762
	}
763
764
	/**
765
	 * @return TControl the edit item
766
	 */
767
	public function getEditItem()
768
	{
769
		$index=$this->getEditItemIndex();
770
		$items=$this->getItems();
771
		if($index>=0 && $index<$items->getCount())
772
			return $items->itemAt($index);
773
		else
774
			return null;
775
	}
776
777
	/**
778
	 * @return boolean whether the header should be shown. Defaults to true.
779
	 */
780
	public function getShowHeader()
781
	{
782
		return $this->getViewState('ShowHeader',true);
783
	}
784
785
	/**
786
	 * @param boolean whether to show header
787
	 */
788
	public function setShowHeader($value)
789
	{
790
		$this->setViewState('ShowHeader',TPropertyValue::ensureBoolean($value),true);
791
	}
792
793
	/**
794
	 * @return boolean whether the footer should be shown. Defaults to true.
795
	 */
796
	public function getShowFooter()
797
	{
798
		return $this->getViewState('ShowFooter',true);
799
	}
800
801
	/**
802
	 * @param boolean whether to show footer
803
	 */
804
	public function setShowFooter($value)
805
	{
806
		$this->setViewState('ShowFooter',TPropertyValue::ensureBoolean($value),true);
807
	}
808
809
	/**
810
	 * @return TRepeatInfo repeat information (primarily used by control developers)
811
	 */
812
	protected function getRepeatInfo()
813
	{
814
		if(($repeatInfo=$this->getViewState('RepeatInfo',null))===null)
815
		{
816
			$repeatInfo=new TRepeatInfo;
817
			$this->setViewState('RepeatInfo',$repeatInfo,null);
818
		}
819
		return $repeatInfo;
820
	}
821
822
	/**
823
	 * @return string caption of the table layout
824
	 */
825
	public function getCaption()
826
	{
827
		return $this->getRepeatInfo()->getCaption();
828
	}
829
830
	/**
831
	 * @param string caption of the table layout
832
	 */
833
	public function setCaption($value)
834
	{
835
		$this->getRepeatInfo()->setCaption($value);
836
	}
837
838
	/**
839
	 * @return TTableCaptionAlign alignment of the caption of the table layout. Defaults to TTableCaptionAlign::NotSet.
840
	 */
841
	public function getCaptionAlign()
842
	{
843
		return $this->getRepeatInfo()->getCaptionAlign();
844
	}
845
846
	/**
847
	 * @return TTableCaptionAlign alignment of the caption of the table layout.
848
	 */
849
	public function setCaptionAlign($value)
850
	{
851
		$this->getRepeatInfo()->setCaptionAlign($value);
852
	}
853
854
	/**
855
	 * @return integer the number of columns that the list should be displayed with. Defaults to 0 meaning not set.
856
	 */
857
	public function getRepeatColumns()
858
	{
859
		return $this->getRepeatInfo()->getRepeatColumns();
860
	}
861
862
	/**
863
	 * @param integer the number of columns that the list should be displayed with.
864
	 */
865
	public function setRepeatColumns($value)
866
	{
867
		$this->getRepeatInfo()->setRepeatColumns($value);
868
	}
869
870
	/**
871
	 * @return TRepeatDirection the direction of traversing the list, defaults to TRepeatDirection::Vertical
872
	 */
873
	public function getRepeatDirection()
874
	{
875
		return $this->getRepeatInfo()->getRepeatDirection();
876
	}
877
878
	/**
879
	 * @param TRepeatDirection the direction of traversing the list
880
	 */
881
	public function setRepeatDirection($value)
882
	{
883
		$this->getRepeatInfo()->setRepeatDirection($value);
884
	}
885
886
	/**
887
	 * @return TRepeatLayout how the list should be displayed, using table or using line breaks. Defaults to TRepeatLayout::Table.
888
	 */
889
	public function getRepeatLayout()
890
	{
891
		return $this->getRepeatInfo()->getRepeatLayout();
892
	}
893
894
	/**
895
	 * @param TRepeatLayout how the list should be displayed, using table or using line breaks
896
	 */
897
	public function setRepeatLayout($value)
898
	{
899
		$this->getRepeatInfo()->setRepeatLayout($value);
900
	}
901
902
	/**
903
	 * This method overrides parent's implementation to handle
904
	 * {@link onItemCommand OnItemCommand} event which is bubbled from
905
	 * datalist items and their child controls.
906
	 * If the event parameter is {@link TDataListCommandEventParameter} and
907
	 * the command name is a recognized one, which includes 'select', 'edit',
908
	 * 'delete', 'update', and 'cancel' (case-insensitive), then a
909
	 * corresponding command event is also raised (such as {@link onEditCommand OnEditCommand}).
910
	 * This method should only be used by control developers.
911
	 * @param TControl the sender of the event
912
	 * @param TEventParameter event parameter
913
	 * @return boolean whether the event bubbling should stop here.
914
	 */
915
	public function bubbleEvent($sender,$param)
916
	{
917
		if($param instanceof TDataListCommandEventParameter)
918
		{
919
			$this->onItemCommand($param);
920
			$command=$param->getCommandName();
921
			if(strcasecmp($command,self::CMD_SELECT)===0)
922
			{
923
				if(($item=$param->getItem()) instanceof IItemDataRenderer)
924
					$this->setSelectedItemIndex($item->getItemIndex());
925
				$this->onSelectedIndexChanged($param);
926
				return true;
927
			}
928
			else if(strcasecmp($command,self::CMD_EDIT)===0)
929
			{
930
				$this->onEditCommand($param);
931
				return true;
932
			}
933
			else if(strcasecmp($command,self::CMD_DELETE)===0)
934
			{
935
				$this->onDeleteCommand($param);
936
				return true;
937
			}
938
			else if(strcasecmp($command,self::CMD_UPDATE)===0)
939
			{
940
				$this->onUpdateCommand($param);
941
				return true;
942
			}
943
			else if(strcasecmp($command,self::CMD_CANCEL)===0)
944
			{
945
				$this->onCancelCommand($param);
946
				return true;
947
			}
948
		}
949
		return false;
950
	}
951
952
953
	/**
954
	 * Raises <b>OnItemCreated</b> event.
955
	 * This method is invoked after a data list item is created and instantiated with
956
	 * template, but before added to the page hierarchy.
957
	 * The datalist item control responsible for the event
958
	 * can be determined from the event parameter.
959
	 * If you override this method, be sure to call parent's implementation
960
	 * so that event handlers have chance to respond to the event.
961
	 * @param TDataListItemEventParameter event parameter
962
	 */
963
	public function onItemCreated($param)
964
	{
965
		$this->raiseEvent('OnItemCreated',$this,$param);
966
	}
967
968
	/**
969
	 * Raises <b>OnItemDataBound</b> event.
970
	 * This method is invoked right after an item is data bound.
971
	 * The datalist item control responsible for the event
972
	 * can be determined from the event parameter.
973
	 * If you override this method, be sure to call parent's implementation
974
	 * so that event handlers have chance to respond to the event.
975
	 * @param TDataListItemEventParameter event parameter
976
	 */
977
	public function onItemDataBound($param)
978
	{
979
		$this->raiseEvent('OnItemDataBound',$this,$param);
980
	}
981
982
	/**
983
	 * Raises <b>OnItemCommand</b> event.
984
	 * This method is invoked when a child control of the data list
985
	 * raises an <b>OnCommand</b> event.
986
	 * @param TDataListCommandEventParameter event parameter
987
	 */
988
	public function onItemCommand($param)
989
	{
990
		$this->raiseEvent('OnItemCommand',$this,$param);
991
	}
992
993
	/**
994
	 * Raises <b>OnEditCommand</b> event.
995
	 * This method is invoked when a child control of the data list
996
	 * raises an <b>OnCommand</b> event and the command name is 'edit' (case-insensitive).
997
	 * @param TDataListCommandEventParameter event parameter
998
	 */
999
	public function onEditCommand($param)
1000
	{
1001
		$this->raiseEvent('OnEditCommand',$this,$param);
1002
	}
1003
1004
	/**
1005
	 * Raises <b>OnDeleteCommand</b> event.
1006
	 * This method is invoked when a child control of the data list
1007
	 * raises an <b>OnCommand</b> event and the command name is 'delete' (case-insensitive).
1008
	 * @param TDataListCommandEventParameter event parameter
1009
	 */
1010
	public function onDeleteCommand($param)
1011
	{
1012
		$this->raiseEvent('OnDeleteCommand',$this,$param);
1013
	}
1014
1015
	/**
1016
	 * Raises <b>OnUpdateCommand</b> event.
1017
	 * This method is invoked when a child control of the data list
1018
	 * raises an <b>OnCommand</b> event and the command name is 'update' (case-insensitive).
1019
	 * @param TDataListCommandEventParameter event parameter
1020
	 */
1021
	public function onUpdateCommand($param)
1022
	{
1023
		$this->raiseEvent('OnUpdateCommand',$this,$param);
1024
	}
1025
1026
	/**
1027
	 * Raises <b>OnCancelCommand</b> event.
1028
	 * This method is invoked when a child control of the data list
1029
	 * raises an <b>OnCommand</b> event and the command name is 'cancel' (case-insensitive).
1030
	 * @param TDataListCommandEventParameter event parameter
1031
	 */
1032
	public function onCancelCommand($param)
1033
	{
1034
		$this->raiseEvent('OnCancelCommand',$this,$param);
1035
	}
1036
1037
	/**
1038
	 * Returns a value indicating whether this control contains header item.
1039
	 * This method is required by {@link IRepeatInfoUser} interface.
1040
	 * @return boolean whether the datalist has header
1041
	 */
1042
	public function getHasHeader()
1043
	{
1044
		return ($this->getShowHeader() && ($this->_headerTemplate!==null || $this->getHeaderRenderer()!==''));
1045
	}
1046
1047
	/**
1048
	 * Returns a value indicating whether this control contains footer item.
1049
	 * This method is required by {@link IRepeatInfoUser} interface.
1050
	 * @return boolean whether the datalist has footer
1051
	 */
1052
	public function getHasFooter()
1053
	{
1054
		return ($this->getShowFooter() && ($this->_footerTemplate!==null || $this->getFooterRenderer()!==''));
1055
	}
1056
1057
	/**
1058
	 * Returns a value indicating whether this control contains separator items.
1059
	 * This method is required by {@link IRepeatInfoUser} interface.
1060
	 * @return boolean always false.
1061
	 */
1062
	public function getHasSeparators()
1063
	{
1064
		return $this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
1065
	}
1066
1067
	/**
1068
	 * Returns a style used for rendering items.
1069
	 * This method is required by {@link IRepeatInfoUser} interface.
1070
	 * @param string item type (Header,Footer,Item,AlternatingItem,SelectedItem,EditItem,Separator,Pager)
1071
	 * @param integer index of the item being rendered
1072
	 * @return TStyle item style
1073
	 */
1074
	public function generateItemStyle($itemType,$index)
1075
	{
1076
		if(($item=$this->getItem($itemType,$index))!==null && ($item instanceof IStyleable) && $item->getHasStyle())
1077
		{
1078
			$style=$item->getStyle();
1079
			$item->clearStyle();
1080
			return $style;
1081
		}
1082
		else
1083
			return null;
1084
	}
1085
1086
	/**
1087
	 * Renders an item in the list.
1088
	 * This method is required by {@link IRepeatInfoUser} interface.
1089
	 * @param THtmlWriter writer for rendering purpose
1090
	 * @param TRepeatInfo repeat information
1091
	 * @param string item type (Header,Footer,Item,AlternatingItem,SelectedItem,EditItem,Separator,Pager)
1092
	 * @param integer zero-based index of the item in the item list
1093
	 */
1094
	public function renderItem($writer,$repeatInfo,$itemType,$index)
1095
	{
1096
		$item=$this->getItem($itemType,$index);
1097
		if($repeatInfo->getRepeatLayout()===TRepeatLayout::Raw && get_class($item)==='TDataListItem')
1098
			$item->setTagName('div');
1099
		$item->renderControl($writer);
1100
	}
1101
1102
	/**
1103
	 * @param TListItemType item type
1104
	 * @param integer item index
1105
	 * @return TControl data list item with the specified item type and index
1106
	 */
1107
	private function getItem($itemType,$index)
1108
	{
1109
		switch($itemType)
1110
		{
1111
			case TListItemType::Item:
1112
			case TListItemType::AlternatingItem:
1113
			case TListItemType::SelectedItem:
1114
			case TListItemType::EditItem:
1115
				return $this->getItems()->itemAt($index);
1116
			case TListItemType::Header:
1117
				return $this->getControls()->itemAt(0);
1118
			case TListItemType::Footer:
1119
				return $this->getControls()->itemAt($this->getControls()->getCount()-1);
1120
			case TListItemType::Separator:
1121
				$i=$index+$index+1;
1122
				if($this->_headerTemplate!==null || $this->getHeaderRenderer()!=='')
1123
					$i++;
1124
				return $this->getControls()->itemAt($i);
1125
		}
1126
		return null;
1127
	}
1128
1129
	/**
1130
	 * Creates a datalist item.
1131
	 * This method invokes {@link createItem} to create a new datalist item.
1132
	 * @param integer zero-based item index.
1133
	 * @param TListItemType item type
1134
	 * @return TControl the created item, null if item is not created
1135
	 */
1136
	private function createItemInternal($itemIndex,$itemType)
1137
	{
1138
		if(($item=$this->createItem($itemIndex,$itemType))!==null)
1139
		{
1140
			$param=new TDataListItemEventParameter($item);
1141
			$this->onItemCreated($param);
1142
			$this->getControls()->add($item);
1143
			return $item;
1144
		}
1145
		else
1146
			return null;
1147
	}
1148
1149
	/**
1150
	 * Creates a datalist item and performs databinding.
1151
	 * This method invokes {@link createItem} to create a new datalist item.
1152
	 * @param integer zero-based item index.
1153
	 * @param TListItemType item type
1154
	 * @param mixed data to be associated with the item
1155
	 * @return TControl the created item, null if item is not created
1156
	 */
1157
	private function createItemWithDataInternal($itemIndex,$itemType,$dataItem)
1158
	{
1159
		if(($item=$this->createItem($itemIndex,$itemType))!==null)
1160
		{
1161
			$param=new TDataListItemEventParameter($item);
1162
			if($item instanceof IDataRenderer)
1163
				$item->setData($dataItem);
1164
			$this->onItemCreated($param);
1165
			$this->getControls()->add($item);
1166
			$item->dataBind();
1167
			$this->onItemDataBound($param);
1168
			return $item;
1169
		}
1170
		else
1171
			return null;
1172
	}
1173
1174
	private function getAlternatingItemDisplay()
1175
	{
1176
		if(($classPath=$this->getAlternatingItemRenderer())==='' && $this->_alternatingItemTemplate===null)
1177
			return array($this->getItemRenderer(),$this->_itemTemplate);
1178
		else
1179
			return array($classPath,$this->_alternatingItemTemplate);
1180
	}
1181
1182
	private function getSelectedItemDisplay($itemIndex)
1183
	{
1184
		if(($classPath=$this->getSelectedItemRenderer())==='' && $this->_selectedItemTemplate===null)
1185
		{
1186
			if($itemIndex%2===0)
1187
				return array($this->getItemRenderer(),$this->_itemTemplate);
1188
			else
1189
				return $this->getAlternatingItemDisplay();
1190
		}
1191
		else
1192
			return array($classPath,$this->_selectedItemTemplate);
1193
	}
1194
1195
	private function getEditItemDisplay($itemIndex)
1196
	{
1197
		if(($classPath=$this->getEditItemRenderer())==='' && $this->_editItemTemplate===null)
1198
			return $this->getSelectedItemDisplay($itemIndex);
1199
		else
1200
			return array($classPath,$this->_editItemTemplate);
1201
	}
1202
1203
	/**
1204
	 * Creates a datalist item instance based on the item type and index.
1205
	 * @param integer zero-based item index
1206
	 * @param TListItemType item type
1207
	 * @return TControl created datalist item
1208
	 */
1209
	protected function createItem($itemIndex,$itemType)
1210
	{
1211
		$template=null;
1212
		$classPath=null;
1213
		switch($itemType)
1214
		{
1215
			case TListItemType::Item :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1216
				$classPath=$this->getItemRenderer();
1217
				$template=$this->_itemTemplate;
1218
				break;
1219
			case TListItemType::AlternatingItem :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1220
				list($classPath,$template)=$this->getAlternatingItemDisplay();
1221
				break;
1222
			case TListItemType::SelectedItem:
1223
				list($classPath,$template)=$this->getSelectedItemDisplay($itemIndex);
1224
				break;
1225
			case TListItemType::EditItem:
1226
				list($classPath,$template)=$this->getEditItemDisplay($itemIndex);
1227
				break;
1228
			case TListItemType::Header :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1229
				$classPath=$this->getHeaderRenderer();
1230
				$template=$this->_headerTemplate;
1231
				break;
1232
			case TListItemType::Footer :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1233
				$classPath=$this->getFooterRenderer();
1234
				$template=$this->_footerTemplate;
1235
				break;
1236
			case TListItemType::Separator :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1237
				$classPath=$this->getSeparatorRenderer();
1238
				$template=$this->_separatorTemplate;
1239
				break;
1240
			default:
1241
				throw new TInvalidDataValueException('datalist_itemtype_unknown',$itemType);
1242
		}
1243
		if($classPath!=='')
1244
		{
1245
			$item=Prado::createComponent($classPath);
1246
			if($item instanceof IItemDataRenderer)
1247
			{
1248
				$item->setItemIndex($itemIndex);
1249
				$item->setItemType($itemType);
1250
			}
1251
		}
1252
		else if($template!==null)
1253
		{
1254
			$item=new TDataListItem;
1255
			$item->setItemIndex($itemIndex);
1256
			$item->setItemType($itemType);
1257
			$template->instantiateIn($item);
1258
		}
1259
		else
1260
			$item=null;
1261
1262
		return $item;
1263
	}
1264
1265
	/**
1266
	 * Creates empty datalist content.
1267
	 */
1268
	protected function createEmptyContent()
1269
	{
1270
		if(($classPath=$this->getEmptyRenderer())!=='')
1271
			$this->getControls()->add(Prado::createComponent($classPath));
1272
		else if($this->_emptyTemplate!==null)
1273
			$this->_emptyTemplate->instantiateIn($this);
1274
	}
1275
1276
	/**
1277
	 * Applies styles to items, header, footer and separators.
1278
	 * Item styles are applied in a hierarchical way. Style in higher hierarchy
1279
	 * will inherit from styles in lower hierarchy.
1280
	 * Starting from the lowest hierarchy, the item styles include
1281
	 * item's own style, {@link getItemStyle ItemStyle}, {@link getAlternatingItemStyle AlternatingItemStyle},
1282
	 * {@link getSelectedItemStyle SelectedItemStyle}, and {@link getEditItemStyle EditItemStyle}.
1283
	 * Therefore, if background color is set as red in {@link getItemStyle ItemStyle},
1284
	 * {@link getEditItemStyle EditItemStyle} will also have red background color
1285
	 * unless it is set to a different value explicitly.
1286
	 */
1287
	protected function applyItemStyles()
1288
	{
1289
		$itemStyle=$this->getViewState('ItemStyle',null);
1290
1291
		$alternatingItemStyle=$this->getViewState('AlternatingItemStyle',null);
1292
		if($itemStyle!==null)
1293
		{
1294
			if($alternatingItemStyle===null)
1295
				$alternatingItemStyle=$itemStyle;
1296
			else
1297
				$alternatingItemStyle->mergeWith($itemStyle);
1298
		}
1299
1300
		$selectedItemStyle=$this->getViewState('SelectedItemStyle',null);
1301
1302
		$editItemStyle=$this->getViewState('EditItemStyle',null);
1303
		if($selectedItemStyle!==null)
1304
		{
1305
			if($editItemStyle===null)
1306
				$editItemStyle=$selectedItemStyle;
1307
			else
1308
				$editItemStyle->mergeWith($selectedItemStyle);
1309
		}
1310
1311
		// apply header style if any
1312
		if($this->_header!==null && $this->_header instanceof IStyleable)
1313
		{
1314
			if($headerStyle=$this->getViewState('HeaderStyle',null))
1315
				$this->_header->getStyle()->mergeWith($headerStyle);
1316
		}
1317
1318
		// apply footer style if any
1319
		if($this->_footer!==null && $this->_footer instanceof IStyleable)
1320
		{
1321
			if($footerStyle=$this->getViewState('FooterStyle',null))
1322
				$this->_footer->getStyle()->mergeWith($footerStyle);
1323
		}
1324
1325
		$selectedIndex=$this->getSelectedItemIndex();
1326
		$editIndex=$this->getEditItemIndex();
1327
1328
		// apply item styles if any
1329
		foreach($this->getItems() as $index=>$item)
1330
		{
1331
			if($index===$editIndex)
1332
				$style=$editItemStyle;
1333
			else if($index===$selectedIndex)
1334
				$style=$selectedItemStyle;
1335
			else if($index%2===0)
1336
				$style=$itemStyle;
1337
			else
1338
				$style=$alternatingItemStyle;
1339
			if($style && $item instanceof IStyleable)
1340
				$item->getStyle()->mergeWith($style);
1341
		}
1342
1343
		// apply separator style if any
1344
		if(($separatorStyle=$this->getViewState('SeparatorStyle',null))!==null && $this->getHasSeparators())
1345
		{
1346
			$controls=$this->getControls();
1347
			$count=$controls->getCount();
1348
			for($i=$this->_header?2:1;$i<$count;$i+=2)
1349
			{
1350
				if(($separator=$controls->itemAt($i)) instanceof IStyleable)
1351
					$separator->getStyle()->mergeWith($separatorStyle);
1352
			}
1353
		}
1354
	}
1355
1356
	/**
1357
	 * Saves item count in viewstate.
1358
	 * This method is invoked right before control state is to be saved.
1359
	 */
1360
	public function saveState()
1361
	{
1362
		parent::saveState();
1363
		if($this->_items)
1364
			$this->setViewState('ItemCount',$this->_items->getCount(),0);
1365
		else
1366
			$this->clearViewState('ItemCount');
1367
	}
1368
1369
	/**
1370
	 * Loads item count information from viewstate.
1371
	 * This method is invoked right after control state is loaded.
1372
	 */
1373
	public function loadState()
1374
	{
1375
		parent::loadState();
1376
		if(!$this->getIsDataBound())
1377
			$this->restoreItemsFromViewState();
1378
		$this->clearViewState('ItemCount');
1379
	}
1380
1381
	/**
1382
	 * Clears up all items in the data list.
1383
	 */
1384
	public function reset()
1385
	{
1386
		$this->getControls()->clear();
1387
		$this->getItems()->clear();
1388
		$this->_header=null;
1389
		$this->_footer=null;
1390
	}
1391
1392
	/**
1393
	 * Creates data list items based on viewstate information.
1394
	 */
1395
	protected function restoreItemsFromViewState()
1396
	{
1397
		$this->reset();
1398
		if(($itemCount=$this->getViewState('ItemCount',0))>0)
1399
		{
1400
			$items=$this->getItems();
1401
			$selectedIndex=$this->getSelectedItemIndex();
1402
			$editIndex=$this->getEditItemIndex();
1403
			$hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
1404
			$this->_header=$this->createItemInternal(-1,TListItemType::Header);
1405
			for($i=0;$i<$itemCount;++$i)
1406
			{
1407
				if($hasSeparator && $i>0)
1408
					$this->createItemInternal($i-1,TListItemType::Separator);
1409
				if($i===$editIndex)
1410
					$itemType=TListItemType::EditItem;
1411
				else if($i===$selectedIndex)
1412
					$itemType=TListItemType::SelectedItem;
1413
				else
1414
					$itemType=$i%2?TListItemType::AlternatingItem : TListItemType::Item;
1415
				$items->add($this->createItemInternal($i,$itemType));
1416
			}
1417
			$this->_footer=$this->createItemInternal(-1,TListItemType::Footer);
1418
		}
1419
		else
1420
			$this->createEmptyContent();
1421
		$this->clearChildState();
1422
	}
1423
1424
	/**
1425
	 * Performs databinding to populate data list items from data source.
1426
	 * This method is invoked by dataBind().
1427
	 * You may override this function to provide your own way of data population.
1428
	 * @param Traversable the data
1429
	 */
1430
	protected function performDataBinding($data)
1431
	{
1432
		$this->reset();
1433
		$keys=$this->getDataKeys();
1434
		$keys->clear();
1435
		$keyField=$this->getDataKeyField();
1436
		$itemIndex=0;
1437
		$items=$this->getItems();
1438
		$hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
1439
		$selectedIndex=$this->getSelectedItemIndex();
1440
		$editIndex=$this->getEditItemIndex();
1441
		foreach($data as $key=>$dataItem)
1442
		{
1443
			if($keyField!=='')
1444
				$keys->add($this->getDataFieldValue($dataItem,$keyField));
1445
			else
1446
				$keys->add($key);
1447
			if($itemIndex===0)
1448
				$this->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null);
1449
			if($hasSeparator && $itemIndex>0)
1450
				$this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null);
1451
			if($itemIndex===$editIndex)
1452
				$itemType=TListItemType::EditItem;
1453
			else if($itemIndex===$selectedIndex)
1454
				$itemType=TListItemType::SelectedItem;
1455
			else
1456
				$itemType=$itemIndex%2?TListItemType::AlternatingItem : TListItemType::Item;
1457
			$items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem));
1458
			$itemIndex++;
1459
		}
1460
		if($itemIndex>0)
1461
			$this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null);
1462
		else
1463
		{
1464
			$this->createEmptyContent();
1465
			$this->dataBindChildren();
1466
		}
1467
		$this->setViewState('ItemCount',$itemIndex,0);
1468
	}
1469
1470
	/**
1471
	 * Renders the data list control.
1472
	 * This method overrides the parent implementation.
1473
	 * @param THtmlWriter writer for rendering purpose.
1474
	 */
1475
	public function render($writer)
1476
	{
1477
		if($this->getHasControls())
1478
		{
1479
			if($this->getItemCount()>0)
1480
			{
1481
				$this->applyItemStyles();
1482
				$repeatInfo=$this->getRepeatInfo();
1483
				$repeatInfo->renderRepeater($writer,$this);
1484
			}
1485
			else if($this->_emptyTemplate!==null || $this->getEmptyRenderer()!=='')
1486
				parent::render($writer);
1487
		}
1488
	}
1489
}
1490
1491
1492
/**
1493
 * TDataListItemEventParameter class
1494
 *
1495
 * TDataListItemEventParameter encapsulates the parameter data for
1496
 * {@link TDataList::onItemCreated ItemCreated} event of {@link TDataList} controls.
1497
 * The {@link getItem Item} property indicates the DataList item related with the event.
1498
 *
1499
 * @author Qiang Xue <[email protected]>
1500
 * @package System.Web.UI.WebControls
1501
 * @since 3.0
1502
 */
1503
class TDataListItemEventParameter extends TEventParameter
1504
{
1505
	/**
1506
	 * The datalist item control responsible for the event.
1507
	 * @var TControl
1508
	 */
1509
	private $_item=null;
1510
1511
	/**
1512
	 * Constructor.
1513
	 * @param TControl DataList item related with the corresponding event
1514
	 */
1515
	public function __construct($item)
1516
	{
1517
		$this->_item=$item;
1518
	}
1519
1520
	/**
1521
	 * @return TControl datalist item related with the corresponding event
1522
	 */
1523
	public function getItem()
1524
	{
1525
		return $this->_item;
1526
	}
1527
}
1528
1529
/**
1530
 * TDataListCommandEventParameter class
1531
 *
1532
 * TDataListCommandEventParameter encapsulates the parameter data for
1533
 * {@link TDataList::onItemCommand ItemCommand} event of {@link TDataList} controls.
1534
 *
1535
 * The {@link getItem Item} property indicates the DataList item related with the event.
1536
 * The {@link getCommandSource CommandSource} refers to the control that originally
1537
 * raises the Command event.
1538
 *
1539
 * @author Qiang Xue <[email protected]>
1540
 * @package System.Web.UI.WebControls
1541
 * @since 3.0
1542
 */
1543
class TDataListCommandEventParameter extends TCommandEventParameter
1544
{
1545
	/**
1546
	 * @var TControl the datalist item control responsible for the event.
1547
	 */
1548
	private $_item=null;
1549
	/**
1550
	 * @var TControl the control originally raises the <b>OnCommand</b> event.
1551
	 */
1552
	private $_source=null;
1553
1554
	/**
1555
	 * Constructor.
1556
	 * @param TControl datalist item responsible for the event
1557
	 * @param TControl original event sender
1558
	 * @param TCommandEventParameter original event parameter
1559
	 */
1560
	public function __construct($item,$source,TCommandEventParameter $param)
1561
	{
1562
		$this->_item=$item;
1563
		$this->_source=$source;
1564
		parent::__construct($param->getCommandName(),$param->getCommandParameter());
1565
	}
1566
1567
	/**
1568
	 * @return TControl the datalist item control responsible for the event.
1569
	 */
1570
	public function getItem()
1571
	{
1572
		return $this->_item;
1573
	}
1574
1575
	/**
1576
	 * @return TControl the control originally raises the <b>OnCommand</b> event.
1577
	 */
1578
	public function getCommandSource()
1579
	{
1580
		return $this->_source;
1581
	}
1582
}
1583
1584
/**
1585
 * TDataListItem class
1586
 *
1587
 * A TDataListItem control represents an item in the {@link TDataList} control,
1588
 * such as heading section, footer section, or a data item.
1589
 * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}>
1590
 * and {@link getDataItem DataItem} properties, respectively. The type of the item
1591
 * is given by {@link getItemType ItemType} property.
1592
 *
1593
 * @author Qiang Xue <[email protected]>
1594
 * @package System.Web.UI.WebControls
1595
 * @since 3.0
1596
 */
1597
class TDataListItem extends TWebControl implements INamingContainer, IItemDataRenderer
1598
{
1599
	/**
1600
	 * index of the data item in the Items collection of DataList
1601
	 */
1602
	private $_itemIndex;
1603
	/**
1604
	 * type of the TDataListItem
1605
	 * @var TListItemType
1606
	 */
1607
	private $_itemType;
1608
	/**
1609
	 * value of the data associated with this item
1610
	 * @var mixed
1611
	 */
1612
	private $_data;
1613
1614
	private $_tagName='span';
1615
1616
	/**
1617
	 * Returns the tag name used for this control.
1618
	 * @return string tag name of the control to be rendered
1619
	 */
1620
	protected function getTagName()
1621
	{
1622
		return $this->_tagName;
1623
	}
1624
1625
	/**
1626
	 * @param string tag name of the control to be rendered
1627
	 */
1628
	public function setTagName($value)
1629
	{
1630
		$this->_tagName=$value;
1631
	}
1632
1633
	/**
1634
	 * Creates a style object for the control.
1635
	 * This method creates a {@link TTableItemStyle} to be used by a datalist item.
1636
	 * @return TStyle control style to be used
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use TTableItemStyle.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
1637
	 */
1638
	protected function createStyle()
1639
	{
1640
		return new TTableItemStyle;
1641
	}
1642
1643
	/**
1644
	 * @return TListItemType item type
1645
	 */
1646
	public function getItemType()
1647
	{
1648
		return $this->_itemType;
1649
	}
1650
1651
	/**
1652
	 * @param TListItemType item type.
1653
	 */
1654
	public function setItemType($value)
1655
	{
1656
		$this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType');
0 ignored issues
show
Documentation Bug introduced by
It seems like \TPropertyValue::ensureE...value, 'TListItemType') of type string is incompatible with the declared type object<TListItemType> of property $_itemType.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1657
	}
1658
1659
	/**
1660
	 * @return integer zero-based index of the item in the item collection of datalist
1661
	 */
1662
	public function getItemIndex()
1663
	{
1664
		return $this->_itemIndex;
1665
	}
1666
1667
	/**
1668
	 * Sets the zero-based index for the item.
1669
	 * If the item is not in the item collection (e.g. it is a header item), -1 should be used.
1670
	 * @param integer zero-based index of the item.
1671
	 */
1672
	public function setItemIndex($value)
1673
	{
1674
		$this->_itemIndex=TPropertyValue::ensureInteger($value);
1675
	}
1676
1677
	/**
1678
	 * @return mixed data associated with the item
1679
	 * @since 3.1.0
1680
	 */
1681
	public function getData()
1682
	{
1683
		return $this->_data;
1684
	}
1685
1686
	/**
1687
	 * @param mixed data to be associated with the item
1688
	 * @since 3.1.0
1689
	 */
1690
	public function setData($value)
1691
	{
1692
		$this->_data=$value;
1693
	}
1694
1695
	/**
1696
	 * This property is deprecated since v3.1.0.
1697
	 * @return mixed data associated with the item
1698
	 * @deprecated deprecated since v3.1.0. Use {@link getData} instead.
1699
	 */
1700
	public function getDataItem()
1701
	{
1702
		return $this->getData();
1703
	}
1704
1705
	/**
1706
	 * This property is deprecated since v3.1.0.
1707
	 * @param mixed data to be associated with the item
1708
	 * @deprecated deprecated since version 3.1.0. Use {@link setData} instead.
1709
	 */
1710
	public function setDataItem($value)
1711
	{
1712
		return $this->setData($value);
1713
	}
1714
1715
	/**
1716
	 * This method overrides parent's implementation by wrapping event parameter
1717
	 * for <b>OnCommand</b> event with item information.
1718
	 * @param TControl the sender of the event
1719
	 * @param TEventParameter event parameter
1720
	 * @return boolean whether the event bubbling should stop here.
1721
	 */
1722
	public function bubbleEvent($sender,$param)
1723
	{
1724
		if($param instanceof TCommandEventParameter)
1725
		{
1726
			$this->raiseBubbleEvent($this,new TDataListCommandEventParameter($this,$sender,$param));
1727
			return true;
1728
		}
1729
		else
1730
			return false;
1731
	}
1732
}
1733
1734
/**
1735
 * TDataListItemCollection class.
1736
 *
1737
 * TDataListItemCollection represents a collection of data list items.
1738
 *
1739
 * @author Qiang Xue <[email protected]>
1740
 * @package System.Web.UI.WebControls
1741
 * @since 3.0
1742
 */
1743
class TDataListItemCollection extends TList
1744
{
1745
	/**
1746
	 * Inserts an item at the specified position.
1747
	 * This overrides the parent implementation by inserting only TControl descendants.
1748
	 * @param integer the speicified position.
1749
	 * @param mixed new item
1750
	 * @throws TInvalidDataTypeException if the item to be inserted is not a TControl descendant.
1751
	 */
1752
	public function insertAt($index,$item)
1753
	{
1754
		if($item instanceof TControl)
1755
			parent::insertAt($index,$item);
1756
		else
1757
			throw new TInvalidDataTypeException('datalistitemcollection_datalistitem_required');
1758
	}
1759
}
1760
1761