<?php /** * IRepeatInfoUser, TRepeatInfo class file * * @author Qiang Xue <qiang.xue@gmail.com> * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2014 PradoSoft * @license http://www.pradosoft.com/license/ * @package System.Web.UI.WebControls */ Prado::using('System.Web.UI.WebControls.TTable'); /** * IRepeatInfoUser interface. * This interface must be implemented by classes who want to use {@link TRepeatInfo}. * * @author Qiang Xue <qiang.xue@gmail.com> * @package System.Web.UI.WebControls * @since 3.0 */ interface IRepeatInfoUser { /** * @return boolean whether the repeat user contains footer */ public function getHasFooter(); /** * @return boolean whether the repeat user contains header */ public function getHasHeader(); /** * @return boolean whether the repeat user contains separators */ public function getHasSeparators(); /** * @return integer number of items to be rendered (excluding header, footer and separators) */ public function getItemCount(); /** * @param string item type (Header,Footer,Item,AlternatingItem,SelectedItem,EditItem,Separator,Pager) * @param integer zero-based index of the current rendering item. * @return TStyle CSS style used for rendering items (including header, footer and separators) */ public function generateItemStyle($itemType,$index); /** * Renders an item. * @param THtmlWriter writer for the rendering purpose * @param TRepeatInfo repeat information * @param string item type * @param integer zero-based index of the item being rendered */ public function renderItem($writer,$repeatInfo,$itemType,$index); } /** * TRepeatInfo class. * TRepeatInfo represents repeat information for controls like {@link TCheckBoxList}. * The layout of the repeated items is specified via {@link setRepeatLayout RepeatLayout}, * which can be either Table (default), Flow or Raw. * A table layout uses HTML table cells to organize the items while * a flow layout uses line breaks to organize the items. * The number of columns used to display the items is specified via * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection} * governs the order of the items being rendered. * * Note, the Raw layout does not contain any formatting tags and thus ignores * the column and repeat direction settings. * * @author Qiang Xue <qiang.xue@gmail.com> * @package System.Web.UI.WebControls * @since 3.0 */ class TRepeatInfo extends TComponent { /** * @var string caption of the table used to organize the repeated items */ private $_caption=''; /** * @var TTableCaptionAlign alignment of the caption of the table used to organize the repeated items */ private $_captionAlign=TTableCaptionAlign::NotSet; /** * @var integer number of columns that the items should be arranged in */ private $_repeatColumns=0; /** * @var TRepeatDirection direction of the repetition */ private $_repeatDirection=TRepeatDirection::Vertical; /** * @var TRepeatLayout layout of the repeated items */ private $_repeatLayout=TRepeatLayout::Table; /** * @return string caption of the table layout */ public function getCaption() { return $this->_caption; } /** * @param string caption of the table layout */ public function setCaption($value) { $this->_caption=$value; } /** * @return TTableCaptionAlign alignment of the caption of the table layout. Defaults to TTableCaptionAlign::NotSet. */ public function getCaptionAlign() { return $this->_captionAlign; } /** * @return TTableCaptionAlign alignment of the caption of the table layout. */ public function setCaptionAlign($value) { $this->_captionAlign=TPropertyValue::ensureEnum($value,'TTableCaptionAlign'); } /** * @return integer the number of columns that the repeated items should be displayed in. Defaults to 0, meaning not set. */ public function getRepeatColumns() { return $this->_repeatColumns; } /** * @param integer the number of columns that the repeated items should be displayed in. */ public function setRepeatColumns($value) { if(($value=TPropertyValue::ensureInteger($value))<0) throw new TInvalidDataValueException('repeatinfo_repeatcolumns_invalid'); $this->_repeatColumns=$value; } /** * @return TRepeatDirection the direction of traversing the repeated items, defaults to TRepeatDirection::Vertical */ public function getRepeatDirection() { return $this->_repeatDirection; } /** * @param TRepeatDirection the direction of traversing the repeated items */ public function setRepeatDirection($value) { $this->_repeatDirection=TPropertyValue::ensureEnum($value,'TRepeatDirection'); } /** * @return TRepeatLayout how the repeated items should be displayed, using table or using line breaks. Defaults to TRepeatLayout::Table. */ public function getRepeatLayout() { return $this->_repeatLayout; } /** * @param TRepeatLayout how the repeated items should be displayed, using table or using line breaks. */ public function setRepeatLayout($value) { $this->_repeatLayout=TPropertyValue::ensureEnum($value,'TRepeatLayout'); } /** * Renders the repeated items. * @param THtmlWriter writer for the rendering purpose * @param IRepeatInfoUser repeat information user */ public function renderRepeater($writer, IRepeatInfoUser $user) { if($this->_repeatLayout===TRepeatLayout::Table) { $control=new TTable; if($this->_caption!=='') { $control->setCaption($this->_caption); $control->setCaptionAlign($this->_captionAlign); } } else if($this->_repeatLayout===TRepeatLayout::Raw) { $this->renderRawContents($writer,$user); return; } else $control=new TWebControl; $control->setID($user->getClientID()); $control->copyBaseAttributes($user); if($user->getHasStyle()) $control->getStyle()->copyFrom($user->getStyle()); $control->renderBeginTag($writer); $writer->writeLine(); if($this->_repeatDirection===TRepeatDirection::Vertical) $this->renderVerticalContents($writer,$user); else $this->renderHorizontalContents($writer,$user); $control->renderEndTag($writer); } /** * Renders contents in raw format. * @param THtmlWriter writer for the rendering purpose * @param IRepeatInfoUser repeat information user */ protected function renderRawContents($writer,$user) { if($user->getHasHeader()) $user->renderItem($writer,$this,'Header',-1); // render items $hasSeparators=$user->getHasSeparators(); $itemCount=$user->getItemCount(); for($i=0;$i<$itemCount;++$i) { $user->renderItem($writer,$this,'Item',$i); if($hasSeparators && $i!=$itemCount-1) $user->renderItem($writer,$this,'Separator',$i); } if($user->getHasFooter()) $user->renderItem($writer,$this,'Footer',-1); } /** * Renders contents in horizontal repeat direction. * @param THtmlWriter writer for the rendering purpose * @param IRepeatInfoUser repeat information user */ protected function renderHorizontalContents($writer,$user) { $tableLayout=($this->_repeatLayout===TRepeatLayout::Table); $hasSeparators=$user->getHasSeparators(); $itemCount=$user->getItemCount(); $columns=$this->_repeatColumns===0?$itemCount:$this->_repeatColumns; $totalColumns=$hasSeparators?$columns+$columns:$columns; $needBreak=$columns<$itemCount; if($user->getHasHeader()) $this->renderHeader($writer,$user,$tableLayout,$totalColumns,$needBreak); // render items if($tableLayout) { $writer->renderBeginTag('tbody'); $column=0; for($i=0;$i<$itemCount;++$i) { if($column==0) $writer->renderBeginTag('tr'); if(($style=$user->generateItemStyle('Item',$i))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Item',$i); $writer->renderEndTag(); $writer->writeLine(); if($hasSeparators && $i!=$itemCount-1) { if(($style=$user->generateItemStyle('Separator',$i))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Separator',$i); $writer->renderEndTag(); $writer->writeLine(); } $column++; if($i==$itemCount-1) { $restColumns=$columns-$column; if($hasSeparators) $restColumns=$restColumns?$restColumns+$restColumns+1:1; for($j=0;$j<$restColumns;++$j) $writer->write("<td></td>\n"); } if($column==$columns || $i==$itemCount-1) { $writer->renderEndTag(); $writer->writeLine(); $column=0; } } $writer->renderEndTag(); } else { $column=0; for($i=0;$i<$itemCount;++$i) { $user->renderItem($writer,$this,'Item',$i); if($hasSeparators && $i!=$itemCount-1) $user->renderItem($writer,$this,'Separator',$i); $column++; if($column==$columns || $i==$itemCount-1) { if($needBreak) $writer->writeBreak(); $column=0; } $writer->writeLine(); } } if($user->getHasFooter()) $this->renderFooter($writer,$user,$tableLayout,$totalColumns,$needBreak); } /** * Renders contents in veritcal repeat direction. * @param THtmlWriter writer for the rendering purpose * @param IRepeatInfoUser repeat information user */ protected function renderVerticalContents($writer,$user) { $tableLayout=($this->_repeatLayout===TRepeatLayout::Table); $hasSeparators=$user->getHasSeparators(); $itemCount=$user->getItemCount(); if($this->_repeatColumns<=1) { $rows=$itemCount; $columns=1; $lastColumns=1; } else { $columns=$this->_repeatColumns; $rows=(int)(($itemCount+$columns-1)/$columns); if($rows==0 && $itemCount>0) $rows=1; if(($lastColumns=$itemCount%$columns)==0) $lastColumns=$columns; } $totalColumns=$hasSeparators?$columns+$columns:$columns; if($user->getHasHeader()) $this->renderHeader($writer,$user,$tableLayout,$totalColumns,false); if($tableLayout) { $writer->renderBeginTag('tbody'); $renderedItems=0; for($row=0;$row<$rows;++$row) { $index=$row; $writer->renderBeginTag('tr'); for($col=0;$col<$columns;++$col) { if($renderedItems>=$itemCount) break; if($col>0) { $index+=$rows; if($col-1>=$lastColumns) $index--; } if($index>=$itemCount) continue; $renderedItems++; if(($style=$user->generateItemStyle('Item',$index))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Item',$index); $writer->renderEndTag(); $writer->writeLine(); if(!$hasSeparators) continue; if($renderedItems<$itemCount-1) { if($columns==1) { $writer->renderEndTag(); $writer->renderBeginTag('tr'); } if(($style=$user->generateItemStyle('Separator',$index))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Separator',$index); $writer->renderEndTag(); $writer->writeLine(); } else if($columns>1) $writer->write("<td></td>\n"); } if($row==$rows-1) { $restColumns=$columns-$lastColumns; if($hasSeparators) $restColumns+=$restColumns; for($col=0;$col<$restColumns;++$col) $writer->write("<td></td>\n"); } $writer->renderEndTag(); $writer->writeLine(); } $writer->renderEndTag(); } else { $renderedItems=0; for($row=0;$row<$rows;++$row) { $index=$row; for($col=0;$col<$columns;++$col) { if($renderedItems>=$itemCount) break; if($col>0) { $index+=$rows; if($col-1>=$lastColumns) $index--; } if($index>=$itemCount) continue; $renderedItems++; $user->renderItem($writer,$this,'Item',$index); $writer->writeLine(); if(!$hasSeparators) continue; if($renderedItems<$itemCount-1) { if($columns==1) $writer->writeBreak(); $user->renderItem($writer,$this,'Separator',$index); } $writer->writeLine(); } if($row<$rows-1 || $user->getHasFooter()) $writer->writeBreak(); } } if($user->getHasFooter()) $this->renderFooter($writer,$user,$tableLayout,$totalColumns,false); } /** * Renders header. * @param THtmlWriter writer for the rendering purpose * @param IRepeatInfoUser repeat information user * @param boolean whether to render using table layout * @param integer number of columns to be rendered * @param boolean if a line break is needed at the end */ protected function renderHeader($writer,$user,$tableLayout,$columns,$needBreak) { if($tableLayout) { $writer->renderBeginTag('thead'); $writer->renderBeginTag('tr'); if($columns>1) $writer->addAttribute('colspan',"$columns"); $writer->addAttribute('scope','col'); if(($style=$user->generateItemStyle('Header',-1))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('th'); $user->renderItem($writer,$this,'Header',-1); $writer->renderEndTag(); $writer->renderEndTag(); $writer->renderEndTag(); } else { $user->renderItem($writer,$this,'Header',-1); if($needBreak) $writer->writeBreak(); } $writer->writeLine(); } /** * Renders footer. * @param THtmlWriter writer for the rendering purpose * @param IRepeatInfoUser repeat information user * @param boolean whether to render using table layout * @param integer number of columns to be rendered */ protected function renderFooter($writer,$user,$tableLayout,$columns) { if($tableLayout) { $writer->renderBeginTag('tfoot'); $writer->renderBeginTag('tr'); if($columns>1) $writer->addAttribute('colspan',"$columns"); if(($style=$user->generateItemStyle('Footer',-1))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Footer',-1); $writer->renderEndTag(); $writer->renderEndTag(); $writer->renderEndTag(); } else $user->renderItem($writer,$this,'Footer',-1); $writer->writeLine(); } } /** * TRepeatDirection class. * TRepeatDirection defines the enumerable type for the possible directions * that repeated contents can repeat along * * The following enumerable values are defined: * - Vertical * - Horizontal * * @author Qiang Xue <qiang.xue@gmail.com> * @package System.Web.UI.WebControls * @since 3.0.4 */ class TRepeatDirection extends TEnumerable { const Vertical='Vertical'; const Horizontal='Horizontal'; } /** * TRepeatLayout class. * TRepeatLayout defines the enumerable type for the possible layouts * that repeated contents can take. * * The following enumerable values are defined: * - Table: the repeated contents are organized using an HTML table * - Flow: the repeated contents are organized using HTML spans and breaks * - Raw: the repeated contents are stacked together without any additional decorations * * @author Qiang Xue <qiang.xue@gmail.com> * @package System.Web.UI.WebControls * @since 3.0.4 */ class TRepeatLayout extends TEnumerable { const Table='Table'; const Flow='Flow'; const Raw='Raw'; }