Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * TListControl class file
4
 *
5
 * @author Qiang Xue <qiang.xue@gmail.com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id: TListControl.php 2591 2008-12-19 20:31:18Z carlgmathisen $
10
 * @package System.Web.UI.WebControls
11
 */
12
 
13
/**
14
 * Includes the supporting classes
15
 */
16
Prado::using('System.Web.UI.WebControls.TDataBoundControl');
17
Prado::using('System.Web.UI.WebControls.TListItem');
18
Prado::using('System.Collections.TAttributeCollection');
19
Prado::using('System.Util.TDataFieldAccessor');
20
 
21
 
22
/**
23
 * TListControl class
24
 *
25
 * TListControl is a base class for list controls, such as {@link TListBox},
26
 * {@link TDropDownList}, {@link TCheckBoxList}, etc.
27
 * It manages the items and their status in a list control.
28
 * It also implements how the items can be populated from template and
29
 * data source.
30
 *
31
 * The property {@link getItems} returns a list of the items in the control.
32
 * To specify or determine which item is selected, use the
33
 * {@link getSelectedIndex SelectedIndex} property that indicates the zero-based
34
 * index of the selected item in the item list. You may also use
35
 * {@link getSelectedItem SelectedItem} and {@link getSelectedValue SelectedValue}
36
 * to get the selected item and its value. For multiple selection lists
37
 * (such as {@link TCheckBoxList} and {@link TListBox}), property
38
 * {@link getSelectedIndices SelectedIndices} is useful.
39
 *
40
 * TListControl implements {@link setAutoPostBack AutoPostBack} which allows
41
 * a list control to postback the page if the selections of the list items are changed.
42
 * The {@link setCausesValidation CausesValidation} and {@link setValidationGroup ValidationGroup}
43
 * properties may be used to specify that validation be performed when auto postback occurs.
44
 *
45
 * There are three ways to populate the items in a list control: from template,
46
 * using {@link setDataSource DataSource} and using {@link setDataSourceID DataSourceID}.
47
 * The latter two are covered in {@link TDataBoundControl}. To specify items via
48
 * template, using the following template syntax:
49
 * <code>
50
 * <com:TListControl>
51
 *   <com:TListItem Value="xxx" Text="yyy" >
52
 *   <com:TListItem Value="xxx" Text="yyy" Selected="true" >
53
 *   <com:TListItem Value="xxx" Text="yyy" >
54
 * </com:TListControl>
55
 * </code>
56
 *
57
 * When {@link setDataSource DataSource} or {@link setDataSourceID DataSourceID}
58
 * is used to populate list items, the {@link setDataTextField DataTextField} and
59
 * {@link setDataValueField DataValueField} properties are used to specify which
60
 * columns of the data will be used to populate the text and value of the items.
61
 * For example, if a data source is as follows,
62
 * <code>
63
 * $dataSource=array(
64
 *    array('name'=>'John', 'age'=>31),
65
 *    array('name'=>'Cary', 'age'=>28),
66
 *    array('name'=>'Rose', 'age'=>35),
67
 * );
68
 * </code>
69
 * setting {@link setDataTextField DataTextField} and {@link setDataValueField DataValueField}
70
 * to 'name' and 'age' will make the first item's text be 'John', value be 31,
71
 * the second item's text be 'Cary', value be 28, and so on.
72
 * The {@link setDataTextFormatString DataTextFormatString} property may be further
73
 * used to format how the item should be displayed. See {@link formatDataValue()}
74
 * for an explanation of the format string.
75
 *
76
 * @author Qiang Xue <qiang.xue@gmail.com>
77
 * @version $Id: TListControl.php 2591 2008-12-19 20:31:18Z carlgmathisen $
78
 * @package System.Web.UI.WebControls
79
 * @since 3.0
80
 */
81
abstract class TListControl extends TDataBoundControl implements IDataRenderer
82
{
83
	/**
84
	 * @var TListItemCollection item list
85
	 */
86
	private $_items=null;
87
	/**
88
	 * @var boolean whether items are restored from viewstate
89
	 */
90
	private $_stateLoaded=false;
91
	/**
92
	 * @var mixed the following selection variables are used
93
	 * to keep selections when Items are not available
94
	 */
95
	private $_cachedSelectedIndex=-1;
96
	private $_cachedSelectedValue=null;
97
	private $_cachedSelectedIndices=null;
98
	private $_cachedSelectedValues=null;
99
 
100
	/**
101
	 * @return string tag name of the list control
102
	 */
103
	protected function getTagName()
104
	{
105
		return 'select';
106
	}
107
 
108
	/**
109
	 * @return boolean whether to render javascript.
110
	 */
111
	public function getEnableClientScript()
112
	{
113
		return $this->getViewState('EnableClientScript',true);
114
	}
115
 
116
	/**
117
	 * @param boolean whether to render javascript.
118
	 */
119
	public function setEnableClientScript($value)
120
	{
121
		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
122
	}
123
 
124
	/**
125
	 * Adds attributes to renderer.
126
	 * @param THtmlWriter the renderer
127
	 */
128
	protected function addAttributesToRender($writer)
129
	{
130
		$page=$this->getPage();
131
		$page->ensureRenderInForm($this);
132
		if($this->getIsMultiSelect())
133
			$writer->addAttribute('multiple','multiple');
134
		if($this->getEnabled(true))
135
		{
136
			if($this->getAutoPostBack()
137
				&& $this->getEnableClientScript()
138
				&& $page->getClientSupportsJavaScript())
139
			{
140
				$this->renderClientControlScript($writer);
141
			}
142
		}
143
		else if($this->getEnabled())
144
			$writer->addAttribute('disabled','disabled');
145
		parent::addAttributesToRender($writer);
146
	}
147
 
148
	/**
149
	 * Renders the javascript for list control.
150
	 */
151
	protected function renderClientControlScript($writer)
152
	{
153
		$writer->addAttribute('id',$this->getClientID());
154
		$this->getPage()->getClientScript()->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
155
	}
156
 
157
	/**
158
	 * Gets the name of the javascript class responsible for performing postback for this control.
159
	 * Derived classes may override this method and return customized js class names.
160
	 * @return string the javascript class name
161
	 */
162
	protected function getClientClassName()
163
	{
164
		return 'Prado.WebUI.TListControl';
165
	}
166
 
167
	/**
168
	 * @return array postback options for JS postback code
169
	 */
170
	protected function getPostBackOptions()
171
	{
172
		$options['ID'] = $this->getClientID();
173
		$options['CausesValidation'] = $this->getCausesValidation();
174
		$options['ValidationGroup'] = $this->getValidationGroup();
175
		$options['EventTarget'] = $this->getUniqueID();
176
		return $options;
177
	}
178
 
179
	/**
180
	 * Adds object parsed from template to the control.
181
	 * This method adds only {@link TListItem} objects into the {@link getItems Items} collection.
182
	 * All other objects are ignored.
183
	 * @param mixed object parsed from template
184
	 */
185
	public function addParsedObject($object)
186
	{
187
		// Do not add items from template if items are loaded from viewstate
188
		if(!$this->_stateLoaded && ($object instanceof TListItem))
189
		{
190
			$index=$this->getItems()->add($object);
191
			if(($this->_cachedSelectedValue!==null && $this->_cachedSelectedValue===$object->getValue()) || ($this->_cachedSelectedIndex===$index))
192
			{
193
				$object->setSelected(true);
194
				$this->_cachedSelectedValue=null;
195
				$this->_cachedSelectedIndex=-1;
196
			}
197
		}
198
	}
199
 
200
	/**
201
	 * Performs databinding to populate list items from data source.
202
	 * This method is invoked by dataBind().
203
	 * You may override this function to provide your own way of data population.
204
	 * @param Traversable the data
205
	 */
206
	protected function performDataBinding($data)
207
	{
208
		$items=$this->getItems();
209
		if(!$this->getAppendDataBoundItems())
210
			$items->clear();
211
		$textField=$this->getDataTextField();
212
		if($textField==='')
213
			$textField=0;
214
		$valueField=$this->getDataValueField();
215
		if($valueField==='')
216
			$valueField=1;
217
		$textFormat=$this->getDataTextFormatString();
218
		$groupField=$this->getDataGroupField();
219
		foreach($data as $key=>$object)
220
		{
221
			$item=$items->createListItem();
222
			if(is_array($object) || is_object($object))
223
			{
224
				$text=TDataFieldAccessor::getDataFieldValue($object,$textField);
225
				$value=TDataFieldAccessor::getDataFieldValue($object,$valueField);
226
				$item->setValue($value);
227
				if($groupField!=='')
228
					$item->setAttribute('Group',TDataFieldAccessor::getDataFieldValue($object,$groupField));
229
			}
230
			else
231
			{
232
				$text=$object;
233
				$item->setValue("$key");
234
			}
235
			$item->setText($this->formatDataValue($textFormat,$text));
236
		}
237
		// SelectedValue or SelectedIndex may be set before databinding
238
		// so we make them be effective now
239
		if($this->_cachedSelectedValue!==null)
240
		{
241
			$this->setSelectedValue($this->_cachedSelectedValue);
242
			$this->resetCachedSelections();
243
		}
244
		else if($this->_cachedSelectedIndex!==-1)
245
		{
246
			$this->setSelectedIndex($this->_cachedSelectedIndex);
247
			$this->resetCachedSelections();
248
		}
249
		else if($this->_cachedSelectedValues!==null)
250
		{
251
			$this->setSelectedValues($this->_cachedSelectedValues);
252
			$this->resetCachedSelections();
253
		}
254
		else if($this->_cachedSelectedIndices!==null)
255
		{
256
			$this->setSelectedIndices($this->_cachedSelectedIndices);
257
			$this->resetCachedSelections();
258
		}
259
	}
260
 
261
	private function resetCachedSelections()
262
	{
263
		$this->_cachedSelectedValue=null;
264
		$this->_cachedSelectedIndex=-1;
265
		$this->_cachedSelectedValues=null;
266
		$this->_cachedSelectedIndices=null;
267
	}
268
 
269
	/**
270
	 * Creates a collection object to hold list items.
271
	 * This method may be overriden to create a customized collection.
272
	 * @return TListItemCollection the collection object
273
	 */
274
	protected function createListItemCollection()
275
	{
276
		return new TListItemCollection;
277
	}
278
 
279
	/**
280
	 * Saves items into viewstate.
281
	 * This method is invoked right before control state is to be saved.
282
	 */
283
	public function saveState()
284
	{
285
		parent::saveState();
286
		if($this->_items)
287
			$this->setViewState('Items',$this->_items->saveState(),null);
288
		else
289
			$this->clearViewState('Items');
290
	}
291
 
292
	/**
293
	 * Loads items from viewstate.
294
	 * This method is invoked right after control state is loaded.
295
	 */
296
	public function loadState()
297
	{
298
		parent::loadState();
299
		$this->_stateLoaded=true;
300
		if(!$this->getIsDataBound())
301
		{
302
			$this->_items=$this->createListItemCollection();
303
			$this->_items->loadState($this->getViewState('Items',null));
304
		}
305
		$this->clearViewState('Items');
306
	}
307
 
308
	/**
309
	 * @return boolean whether this is a multiselect control. Defaults to false.
310
	 */
311
	protected function getIsMultiSelect()
312
	{
313
		return false;
314
	}
315
 
316
	/**
317
	 * @return boolean whether performing databind should append items or clear the existing ones. Defaults to false.
318
	 */
319
	public function getAppendDataBoundItems()
320
	{
321
		return $this->getViewState('AppendDataBoundItems',false);
322
	}
323
 
324
	/**
325
	 * @param boolean whether performing databind should append items or clear the existing ones.
326
	 */
327
	public function setAppendDataBoundItems($value)
328
	{
329
		$this->setViewState('AppendDataBoundItems',TPropertyValue::ensureBoolean($value),false);
330
	}
331
 
332
	/**
333
	 * @return boolean a value indicating whether an automatic postback to the server
334
     * will occur whenever the user makes change to the list control and then tabs out of it.
335
     * Defaults to false.
336
	 */
337
	public function getAutoPostBack()
338
	{
339
		return $this->getViewState('AutoPostBack',false);
340
	}
341
 
342
	/**
343
	 * Sets the value indicating if postback automatically.
344
	 * An automatic postback to the server will occur whenever the user
345
	 * makes change to the list control and then tabs out of it.
346
	 * @param boolean the value indicating if postback automatically
347
	 */
348
	public function setAutoPostBack($value)
349
	{
350
		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false);
351
	}
352
 
353
	/**
354
	 * @return boolean whether postback event trigger by this list control will cause input validation, default is true.
355
	 */
356
	public function getCausesValidation()
357
	{
358
		return $this->getViewState('CausesValidation',true);
359
	}
360
 
361
	/**
362
	 * @param boolean whether postback event trigger by this list control will cause input validation.
363
	 */
364
	public function setCausesValidation($value)
365
	{
366
		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
367
	}
368
 
369
	/**
370
	 * @return string the field of the data source that provides the text content of the list items.
371
	 */
372
	public function getDataTextField()
373
	{
374
		return $this->getViewState('DataTextField','');
375
	}
376
 
377
	/**
378
	 * @param string the field of the data source that provides the text content of the list items.
379
	 */
380
	public function setDataTextField($value)
381
	{
382
		$this->setViewState('DataTextField',$value,'');
383
	}
384
 
385
	/**
386
	 * @return string the formatting string used to control how data bound to the list control is displayed.
387
	 */
388
	public function getDataTextFormatString()
389
	{
390
		return $this->getViewState('DataTextFormatString','');
391
	}
392
 
393
	/**
394
	 * Sets data text format string.
395
	 * The format string is used in {@link TDataValueFormatter::format()} to format the Text property value
396
	 * of each item in the list control.
397
	 * @param string the formatting string used to control how data bound to the list control is displayed.
398
	 * @see TDataValueFormatter::format()
399
	 */
400
	public function setDataTextFormatString($value)
401
	{
402
		$this->setViewState('DataTextFormatString',$value,'');
403
	}
404
 
405
	/**
406
	 * @return string the field of the data source that provides the value of each list item.
407
	 */
408
	public function getDataValueField()
409
	{
410
		return $this->getViewState('DataValueField','');
411
	}
412
 
413
	/**
414
	 * @param string the field of the data source that provides the value of each list item.
415
	 */
416
	public function setDataValueField($value)
417
	{
418
		$this->setViewState('DataValueField',$value,'');
419
	}
420
 
421
	/**
422
	 * @return string the field of the data source that provides the label of the list item groups
423
	 */
424
	public function getDataGroupField()
425
	{
426
		return $this->getViewState('DataGroupField','');
427
	}
428
 
429
	/**
430
	 * @param string the field of the data source that provides the label of the list item groups
431
	 */
432
	public function setDataGroupField($value)
433
	{
434
		$this->setViewState('DataGroupField',$value,'');
435
	}
436
 
437
	/**
438
	 * @return integer the number of items in the list control
439
	 */
440
	public function getItemCount()
441
	{
442
		return $this->_items?$this->_items->getCount():0;
443
	}
444
 
445
	/**
446
	 * @return boolean whether the list control contains any items.
447
	 */
448
	public function getHasItems()
449
	{
450
		return ($this->_items && $this->_items->getCount()>0);
451
	}
452
 
453
	/**
454
	 * @return TListItemCollection the item collection
455
	 */
456
	public function getItems()
457
	{
458
		if(!$this->_items)
459
			$this->_items=$this->createListItemCollection();
460
		return $this->_items;
461
	}
462
 
463
	/**
464
	 * @return integer the index (zero-based) of the item being selected, -1 if no item is selected.
465
	 */
466
	public function getSelectedIndex()
467
	{
468
		if($this->_items)
469
		{
470
			$n=$this->_items->getCount();
471
			for($i=0;$i<$n;++$i)
472
				if($this->_items->itemAt($i)->getSelected())
473
					return $i;
474
		}
475
		return -1;
476
	}
477
 
478
	/**
479
	 * @param integer the index (zero-based) of the item to be selected
480
	 */
481
	public function setSelectedIndex($index)
482
	{
483
		if(($index=TPropertyValue::ensureInteger($index))<0)
484
			$index=-1;
485
		if($this->_items)
486
		{
487
			$this->clearSelection();
488
			if($index>=0 && $index<$this->_items->getCount())
489
				$this->_items->itemAt($index)->setSelected(true);
490
		}
491
		$this->_cachedSelectedIndex=$index;
492
		if($this->getAdapter() instanceof IListControlAdapter)
493
			$this->getAdapter()->setSelectedIndex($index);
494
	}
495
 
496
	/**
497
	 * @return array list of index of items that are selected
498
	 */
499
	public function getSelectedIndices()
500
	{
501
		$selections=array();
502
		if($this->_items)
503
		{
504
			$n=$this->_items->getCount();
505
			for($i=0;$i<$n;++$i)
506
				if($this->_items->itemAt($i)->getSelected())
507
					$selections[]=$i;
508
		}
509
		return $selections;
510
	}
511
 
512
	/**
513
	 * @param array list of index of items to be selected
514
	 */
515
	public function setSelectedIndices($indices)
516
	{
517
		if($this->getIsMultiSelect())
518
		{
519
			if($this->_items)
520
			{
521
				$this->clearSelection();
522
				$n=$this->_items->getCount();
523
				foreach($indices as $index)
524
				{
525
					if($index>=0 && $index<$n)
526
						$this->_items->itemAt($index)->setSelected(true);
527
				}
528
			}
529
			$this->_cachedSelectedIndices=$indices;
530
		}
531
		else
532
			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this));
533
 
534
		if($this->getAdapter() instanceof IListControlAdapter)
535
			$this->getAdapter()->setSelectedIndices($indices);
536
	}
537
 
538
	/**
539
	 * @return TListItem|null the selected item with the lowest cardinal index, null if no item is selected.
540
	 */
541
	public function getSelectedItem()
542
	{
543
		if(($index=$this->getSelectedIndex())>=0)
544
			return $this->_items->itemAt($index);
545
		else
546
			return null;
547
	}
548
 
549
	/**
550
	 * Returns the value of the selected item with the lowest cardinal index.
551
	 * This method is required by {@link IDataRenderer}.
552
	 * It is the same as {@link getSelectedValue()}.
553
	 * @return string the value of the selected item with the lowest cardinal index, empty if no selection.
554
	 * @see getSelectedValue
555
	 * @since 3.1.0
556
	 */
557
	public function getData()
558
	{
559
		return $this->getSelectedValue();
560
	}
561
 
562
	/**
563
	 * Selects an item by the specified value.
564
	 * This method is required by {@link IDataRenderer}.
565
	 * It is the same as {@link setSelectedValue()}.
566
	 * @param string the value of the item to be selected.
567
	 * @see setSelectedValue
568
	 * @since 3.1.0
569
	 */
570
	public function setData($value)
571
	{
572
		$this->setSelectedValue($value);
573
	}
574
 
575
	/**
576
	 * @return string the value of the selected item with the lowest cardinal index, empty if no selection
577
	 */
578
	public function getSelectedValue()
579
	{
580
		$index=$this->getSelectedIndex();
581
		return $index>=0?$this->getItems()->itemAt($index)->getValue():'';
582
	}
583
 
584
	/**
585
	 * Sets selection by item value.
586
	 * Existing selections will be cleared if the item value is found in the item collection.
587
	 * Note, if the value is null, existing selections will also be cleared.
588
	 * @param string the value of the item to be selected.
589
	 */
590
	public function setSelectedValue($value)
591
    {
592
	    if($this->_items)
593
	    {
594
		    if($value===null)
595
		    	$this->clearSelection();
596
		    else if(($item=$this->_items->findItemByValue($value))!==null)
597
	    	{
598
		    	$this->clearSelection();
599
		    	$item->setSelected(true);
600
	    	}
601
	    	else
602
				$this->clearSelection();
603
    	}
604
    	$this->_cachedSelectedValue=$value;
605
		if($this->getAdapter() instanceof IListControlAdapter)
606
			$this->getAdapter()->setSelectedValue($value);
607
    }
608
 
609
 
610
	/**
611
	 * @return array list of the selected item values (strings)
612
	 */
613
	public function getSelectedValues()
614
	{
615
		$values=array();
616
		if($this->_items)
617
		{
618
			foreach($this->_items as $item)
619
			{
620
				if($item->getSelected())
621
					$values[]=$item->getValue();
622
			}
623
		}
624
		return $values;
625
	}
626
 
627
	/**
628
	 * @param array list of the selected item values
629
	 */
630
	public function setSelectedValues($values)
631
	{
632
		if($this->getIsMultiSelect())
633
		{
634
			if($this->_items)
635
			{
636
				$this->clearSelection();
637
				$lookup=array();
638
				foreach($this->_items as $item)
639
					$lookup[$item->getValue()]=$item;
640
				foreach($values as $value)
641
				{
642
					if(isset($lookup["$value"]))
643
						$lookup["$value"]->setSelected(true);
644
				}
645
			}
646
			$this->_cachedSelectedValues=$values;
647
		}
648
		else
649
			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this));
650
 
651
		if($this->getAdapter() instanceof IListControlAdapter)
652
			$this->getAdapter()->setSelectedValues($values);
653
	}
654
 
655
    /**
656
     * @return string selected value
657
     */
658
    public function getText()
659
    {
660
	    return $this->getSelectedValue();
661
    }
662
 
663
    /**
664
     * @param string value to be selected
665
     */
666
    public function setText($value)
667
    {
668
	    $this->setSelectedValue($value);
669
    }
670
 
671
    /**
672
     * Clears all existing selections.
673
     */
674
    public function clearSelection()
675
    {
676
	    if($this->_items)
677
	    {
678
		    foreach($this->_items as $item)
679
		    	$item->setSelected(false);
680
	    }
681
 
682
		if($this->getAdapter() instanceof IListControlAdapter)
683
			$this->getAdapter()->clearSelection();
684
    }
685
 
686
	/**
687
	 * @return string the group of validators which the list control causes validation upon postback
688
	 */
689
	public function getValidationGroup()
690
	{
691
		return $this->getViewState('ValidationGroup','');
692
	}
693
 
694
	/**
695
	 * @param string the group of validators which the list control causes validation upon postback
696
	 */
697
	public function setValidationGroup($value)
698
	{
699
		$this->setViewState('ValidationGroup',$value,'');
700
	}
701
 
702
	/**
703
	 * @return string the prompt text which is to be displayed as the first list item.
704
	 * @since 3.1.1
705
	 */
706
	public function getPromptText()
707
	{
708
		return $this->getViewState('PromptText','');
709
	}
710
 
711
	/**
712
	 * @param string the prompt text which is to be displayed as the first list item.
713
	 * @since 3.1.1
714
	 */
715
	public function setPromptText($value)
716
	{
717
		$this->setViewState('PromptText',$value,'');
718
	}
719
 
720
	/**
721
	 * @return string the prompt selection value.
722
	 * @see getPromptText
723
	 * @since 3.1.1
724
	 */
725
	public function getPromptValue()
726
	{
727
		return $this->getViewState('PromptValue','');
728
	}
729
 
730
	/**
731
	 * @param string the prompt selection value. If empty, {@link getPromptText PromptText} will be used as the value.
732
	 * @see setPromptText
733
	 * @since 3.1.1
734
	 */
735
	public function setPromptValue($value)
736
	{
737
		$this->setViewState('PromptValue',(string)$value,'');
738
	}
739
 
740
	/**
741
	 * Raises OnSelectedIndexChanged event when selection is changed.
742
	 * This method is invoked when the list control has its selection changed
743
	 * by end-users.
744
	 * @param TEventParameter event parameter
745
	 */
746
	public function onSelectedIndexChanged($param)
747
	{
748
		$this->raiseEvent('OnSelectedIndexChanged',$this,$param);
749
		$this->onTextChanged($param);
750
	}
751
 
752
	/**
753
	 * Raises OnTextChanged event when selection is changed.
754
	 * This method is invoked when the list control has its selection changed
755
	 * by end-users.
756
	 * @param TEventParameter event parameter
757
	 */
758
	public function onTextChanged($param)
759
	{
760
		$this->raiseEvent('OnTextChanged',$this,$param);
761
	}
762
 
763
	/**
764
	 * Renders the prompt text, if any.
765
	 * @param THtmlWriter writer
766
	 * @since 3.1.1
767
	 */
768
	protected function renderPrompt($writer)
769
	{
770
		$text=$this->getPromptText();
771
		$value=$this->getPromptValue();
772
		if($value==='')
773
			$value=$text;
774
		if($value!=='')
775
		{
776
			$writer->addAttribute('value',$value);
777
			$writer->renderBeginTag('option');
778
			$writer->write(THttpUtility::htmlEncode($text));
779
			$writer->renderEndTag();
780
			$writer->writeLine();
781
		}
782
	}
783
 
784
	/**
785
	 * Renders body content of the list control.
786
	 * This method renders items contained in the list control as the body content.
787
	 * @param THtmlWriter writer
788
	 */
789
	public function renderContents($writer)
790
	{
791
		$this->renderPrompt($writer);
792
 
793
		if($this->_items)
794
		{
795
			$writer->writeLine();
796
			$previousGroup=null;
797
			foreach($this->_items as $item)
798
			{
799
				if($item->getEnabled())
800
				{
801
					if($item->getHasAttributes())
802
					{
803
						$group=$item->getAttributes()->remove('Group');
804
						if($group!==$previousGroup)
805
						{
806
							if($previousGroup!==null)
807
							{
808
								$writer->renderEndTag();
809
								$writer->writeLine();
810
								$previousGroup=null;
811
							}
812
							if($group!==null)
813
							{
814
								$writer->addAttribute('label',$group);
815
								$writer->renderBeginTag('optgroup');
816
								$writer->writeLine();
817
								$previousGroup=$group;
818
							}
819
						}
820
						foreach($item->getAttributes() as $name=>$value)
821
							$writer->addAttribute($name,$value);
822
					}
823
					else if($previousGroup!==null)
824
					{
825
						$writer->renderEndTag();
826
						$writer->writeLine();
827
						$previousGroup=null;
828
					}
829
					if($item->getSelected())
830
						$writer->addAttribute('selected','selected');
831
					$writer->addAttribute('value',$item->getValue());
832
					$writer->renderBeginTag('option');
833
					$writer->write(THttpUtility::htmlEncode($item->getText()));
834
					$writer->renderEndTag();
835
					$writer->writeLine();
836
				}
837
			}
838
			if($previousGroup!==null)
839
			{
840
				$writer->renderEndTag();
841
				$writer->writeLine();
842
			}
843
		}
844
	}
845
 
846
	/**
847
	 * Formats the text value according to a format string.
848
	 * If the format string is empty, the original value is converted into
849
	 * a string and returned.
850
	 * If the format string starts with '#', the string is treated as a PHP expression
851
	 * within which the token '{0}' is translated with the data value to be formated.
852
	 * Otherwise, the format string and the data value are passed
853
	 * as the first and second parameters in {@link sprintf}.
854
	 * @param string format string
855
	 * @param mixed the data to be formatted
856
	 * @return string the formatted result
857
	 */
858
	protected function formatDataValue($formatString,$value)
859
	{
860
		if($formatString==='')
861
			return TPropertyValue::ensureString($value);
862
		else if($formatString[0]==='#')
863
		{
864
			$expression=strtr(substr($formatString,1),array('{0}'=>'$value'));
865
			try
866
			{
867
				if(eval("\$result=$expression;")===false)
868
					throw new Exception('');
869
				return $result;
870
			}
871
			catch(Exception $e)
872
			{
873
				throw new TInvalidDataValueException('listcontrol_expression_invalid',get_class($this),$expression,$e->getMessage());
874
			}
875
		}
876
		else
877
			return sprintf($formatString,$value);
878
	}
879
}
880
 
881
/**
882
 * TListItemCollection class.
883
 *
884
 * TListItemCollection maintains a list of {@link TListItem} for {@link TListControl}.
885
 *
886
 * @author Qiang Xue <qiang.xue@gmail.com>
887
 * @version $Id: TListControl.php 2591 2008-12-19 20:31:18Z carlgmathisen $
888
 * @package System.Web.UI.WebControls
889
 * @since 3.0
890
 */
891
class TListItemCollection extends TList
892
{
893
	/**
894
	 * Creates a list item object.
895
	 * This method may be overriden to provide a customized list item object.
896
	 * @param integer index where the newly created item is to be inserted at.
897
	 * If -1, the item will be appended to the end.
898
	 * @return TListItem list item object
899
	 */
900
	public function createListItem($index=-1)
901
	{
902
		$item=$this->createNewListItem();
903
		if($index<0)
904
			$this->add($item);
905
		else
906
			$this->insertAt($index,$item);
907
		return $item;
908
	}
909
 
910
	/**
911
	 * @return TListItem new item.
912
	 */
913
	protected function createNewListItem($text=null)
914
	{
915
		$item =  new TListItem;
916
		if(!is_null($text))
917
			$item->setText($text);
918
		return $item;
919
	}
920
 
921
	/**
922
	 * Inserts an item into the collection.
923
	 * @param integer the location where the item will be inserted.
924
	 * The current item at the place and the following ones will be moved backward.
925
	 * @param TListItem the item to be inserted.
926
	 * @throws TInvalidDataTypeException if the item being inserted is neither a string nor TListItem
927
	 */
928
	public function insertAt($index,$item)
929
	{
930
		if(is_string($item))
931
			$item = $this->createNewListItem($item);
932
		if(!($item instanceof TListItem))
933
			throw new TInvalidDataTypeException('listitemcollection_item_invalid',get_class($this));
934
		parent::insertAt($index,$item);
935
	}
936
 
937
	/**
938
	 * Finds the lowest cardinal index of the item whose value is the one being looked for.
939
	 * @param string the value to be looked for
940
	 * @param boolean whether to look for disabled items also
941
	 * @return integer the index of the item found, -1 if not found.
942
	 */
943
	public function findIndexByValue($value,$includeDisabled=true)
944
	{
945
		$value=TPropertyValue::ensureString($value);
946
		$index=0;
947
		foreach($this as $item)
948
		{
949
			if($item->getValue()===$value && ($includeDisabled || $item->getEnabled()))
950
				return $index;
951
			$index++;
952
		}
953
		return -1;
954
	}
955
 
956
	/**
957
	 * Finds the lowest cardinal index of the item whose text is the one being looked for.
958
	 * @param string the text to be looked for
959
	 * @param boolean whether to look for disabled items also
960
	 * @return integer the index of the item found, -1 if not found.
961
	 */
962
	public function findIndexByText($text,$includeDisabled=true)
963
	{
964
		$text=TPropertyValue::ensureString($text);
965
		$index=0;
966
		foreach($this as $item)
967
		{
968
			if($item->getText()===$text && ($includeDisabled || $item->getEnabled()))
969
				return $index;
970
			$index++;
971
		}
972
		return -1;
973
	}
974
 
975
	/**
976
	 * Finds the item whose value is the one being looked for.
977
	 * @param string the value to be looked for
978
	 * @param boolean whether to look for disabled items also
979
	 * @return TListItem the item found, null if not found.
980
	 */
981
	public function findItemByValue($value,$includeDisabled=true)
982
	{
983
		if(($index=$this->findIndexByValue($value,$includeDisabled))>=0)
984
			return $this->itemAt($index);
985
		else
986
			return null;
987
	}
988
 
989
	/**
990
	 * Finds the item whose text is the one being looked for.
991
	 * @param string the text to be looked for
992
	 * @param boolean whether to look for disabled items also
993
	 * @return TListItem the item found, null if not found.
994
	 */
995
	public function findItemByText($text,$includeDisabled=true)
996
	{
997
		if(($index=$this->findIndexByText($text,$includeDisabled))>=0)
998
			return $this->itemAt($index);
999
		else
1000
			return null;
1001
	}
1002
 
1003
	/**
1004
	 * Loads state into every item in the collection.
1005
	 * This method should only be used by framework and control developers.
1006
	 * @param array|null state to be loaded.
1007
	 */
1008
	public function loadState($state)
1009
	{
1010
		$this->clear();
1011
		if($state!==null)
1012
			$this->copyFrom($state);
1013
	}
1014
 
1015
	/**
1016
	 * Saves state of items.
1017
	 * This method should only be used by framework and control developers.
1018
	 * @return array|null the saved state
1019
	 */
1020
	public function saveState()
1021
	{
1022
		return ($this->getCount()>0) ? $this->toArray() : null;
1023
	}
1024
}
1025
 
1026
/**
1027
 * IListControlAdapter interface
1028
 *
1029
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
1030
 * @version $Revision: $  Sun Jun 25 04:53:43 EST 2006 $
1031
 * @package System.Web.UI.ActiveControls
1032
 * @since 3.0
1033
 */
1034
interface IListControlAdapter
1035
{
1036
	/**
1037
	 * Selects an item based on zero-base index on the client side.
1038
	 * @param integer the index (zero-based) of the item to be selected
1039
	 */
1040
	public function setSelectedIndex($index);
1041
	/**
1042
	 * Selects a list of item based on zero-base indices on the client side.
1043
	 * @param array list of index of items to be selected
1044
	 */
1045
	public function setSelectedIndices($indices);
1046
 
1047
	/**
1048
	 * Sets selection by item value on the client side.
1049
	 * @param string the value of the item to be selected.
1050
	 */
1051
	public function setSelectedValue($value);
1052
 
1053
	/**
1054
	 * Sets selection by a list of item values on the client side.
1055
	 * @param array list of the selected item values
1056
	 */
1057
	public function setSelectedValues($values);
1058
 
1059
    /**
1060
     * Clears all existing selections on the client side.
1061
     */
1062
    public function clearSelection();
1063
}
1064
 
1065
 
1066
?>