From 5c0a31f2407037665e8640e486c36d6c71c5ca90 Mon Sep 17 00:00:00 2001
From: "ctrlaltca@gmail.com" <>
Date: Wed, 1 Jun 2011 09:39:26 +0000
Subject: backported active data controls + some other goodies from trunk/ ;
updated docs
---
.gitattributes | 7 +
HISTORY | 5 +
.../protected/pages/ActiveControls/Home.page | 83 ++-
.../Web/UI/ActiveControls/TActiveDataGrid.php | 753 +++++++++++++++++++++
.../Web/UI/ActiveControls/TActiveDataList.php | 117 ++++
framework/Web/UI/ActiveControls/TActiveLabel.php | 178 ++---
.../Web/UI/ActiveControls/TActiveMultiView.php | 110 +++
.../Web/UI/ActiveControls/TActiveRepeater.php | 113 ++++
.../Web/UI/ActiveControls/TActiveTableCell.php | 244 +++++++
.../Web/UI/ActiveControls/TActiveTableRow.php | 262 +++++++
framework/Web/UI/TTemplateControlInheritable.php | 116 ++++
11 files changed, 1871 insertions(+), 117 deletions(-)
create mode 100644 framework/Web/UI/ActiveControls/TActiveDataGrid.php
create mode 100644 framework/Web/UI/ActiveControls/TActiveDataList.php
create mode 100644 framework/Web/UI/ActiveControls/TActiveMultiView.php
create mode 100644 framework/Web/UI/ActiveControls/TActiveRepeater.php
create mode 100644 framework/Web/UI/ActiveControls/TActiveTableCell.php
create mode 100644 framework/Web/UI/ActiveControls/TActiveTableRow.php
create mode 100644 framework/Web/UI/TTemplateControlInheritable.php
diff --git a/.gitattributes b/.gitattributes
index f8c1d508..bc0ce443 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2594,12 +2594,18 @@ framework/Web/TUrlMapping.php -text
framework/Web/UI/ActiveControls/TActiveButton.php -text
framework/Web/UI/ActiveControls/TActiveControlAdapter.php -text
framework/Web/UI/ActiveControls/TActiveCustomValidator.php -text
+framework/Web/UI/ActiveControls/TActiveDataGrid.php -text
+framework/Web/UI/ActiveControls/TActiveDataList.php -text
framework/Web/UI/ActiveControls/TActiveHiddenField.php -text
framework/Web/UI/ActiveControls/TActiveLabel.php -text
+framework/Web/UI/ActiveControls/TActiveMultiView.php -text
framework/Web/UI/ActiveControls/TActivePageAdapter.php -text
framework/Web/UI/ActiveControls/TActivePager.php -text
framework/Web/UI/ActiveControls/TActivePanel.php -text
framework/Web/UI/ActiveControls/TActiveRatingList.php -text
+framework/Web/UI/ActiveControls/TActiveRepeater.php -text
+framework/Web/UI/ActiveControls/TActiveTableCell.php -text
+framework/Web/UI/ActiveControls/TActiveTableRow.php -text
framework/Web/UI/ActiveControls/TActiveTextBox.php -text
framework/Web/UI/ActiveControls/TAutoComplete.php -text
framework/Web/UI/ActiveControls/TBaseActiveControl.php -text
@@ -2623,6 +2629,7 @@ framework/Web/UI/TPage.php -text
framework/Web/UI/TPageStatePersister.php -text
framework/Web/UI/TSessionPageStatePersister.php -text
framework/Web/UI/TTemplateControl.php -text
+framework/Web/UI/TTemplateControlInheritable.php -text
framework/Web/UI/TTemplateManager.php -text
framework/Web/UI/TThemeManager.php -text
framework/Web/UI/WebControls/TBaseDataList.php -text
diff --git a/HISTORY b/HISTORY
index 806f33d6..4db51a4b 100644
--- a/HISTORY
+++ b/HISTORY
@@ -3,6 +3,11 @@ Version 3.1.9 Xxx XX, 201X
BUG: Issue#311 - TDataList : FooterStyle not used (ctrlaltca)
BUG: Issue#326 - Translation don't work with Prado 3.1.8 (ctrlaltca)
BUG: Issue#327 - TDbCache with PostgreSQL throw a TDbException (ctrlaltca)
+NEW: Added TTemplateControlInheritable control
+NEW: Added TActiveDataGrid control
+NEW: Added TActiveDataList control
+NEW: Added TActiveMultiView control
+NEW: Added TActiveRepeater control
Version 3.1.8 May 29, 2011
diff --git a/demos/quickstart/protected/pages/ActiveControls/Home.page b/demos/quickstart/protected/pages/ActiveControls/Home.page
index 49855980..a42bd111 100644
--- a/demos/quickstart/protected/pages/ActiveControls/Home.page
+++ b/demos/quickstart/protected/pages/ActiveControls/Home.page
@@ -64,18 +64,24 @@ TActiveButton control. See also the later part of the TActiveMultiView
+ represents a container for a group of TView controls, each of which is container for other controls.
+ At any time, at most one TView is visible. It's the active counterpart of TMultiView.
+
+
* TActivePanel
represents a container for other controls on a Web page. In HTML,
it is displayed as a <div> element. The panel's contents
can be replaced during a callback request.
-
-
- TActivePager
- generates UI that allows users to interactively specify which page of
- data to be displayed in a data-bound control.
-
+
+
+ TActivePager
+ generates UI that allows users to interactively specify which page of
+ data to be displayed in a data-bound control.
+
* TActiveRadioButton
@@ -103,7 +109,7 @@ TActiveButton control. See also the later part of the TActiveCheckBoxList
displays a list of checkboxes on a Web page and each checkbox
- can trigger a callback request.
+ can trigger a callback request.
@@ -127,6 +133,27 @@ TActiveButton control. See also the later part of the
+
+ * TActiveDataList
+ is used to display or modify a list of data items. It is the
+ active counterpart to the original TDataList control.
+
+
+
+ * TActiveDataGrid
+ displays data in a tabular format with rows and columns. It is the
+ active counterpart to the original TDataGrid control.
+
+
+
+ * TActiveRepeater
+ displays its content defined in templates repeatedly based on the given data.
+ It is the active counterpart to the original TRepeater control.
+
+
+
Extended Active Controls
@@ -160,12 +187,12 @@ TActiveButton control. See also the later part of the TValueTriggeredCallback
monitors (using a timer) an attribute of an HTML element and triggers a callback request
when the attribute value changes.
-
-
-
- TDropContainer & TDraggable represents drag and drop containers.
- The former will make its child controls "draggable" while the latter will raise a callback when a draggable
- control is dropped on it.
+
+
+
+ TDropContainer & TDraggable represents drag and drop containers.
+ The former will make its child controls "draggable" while the latter will raise a callback when a draggable
+ control is dropped on it.
@@ -316,20 +343,20 @@ if Javascript was disabled on the client's browser.
TValueTriggeredCallback
Yes | No |
-
-
-
- TDropContainer
- |
- Yes | No |
-
-
-
- TDraggable
- |
- No | No |
-
-
+
+
+
+ TDropContainer
+ |
+ Yes | No |
+
+
+
+ TDraggable
+ |
+ No | No |
+
+
@@ -377,4 +404,4 @@ realize the active controls.
-$Id$
+$Id$
diff --git a/framework/Web/UI/ActiveControls/TActiveDataGrid.php b/framework/Web/UI/ActiveControls/TActiveDataGrid.php
new file mode 100644
index 00000000..358bd414
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TActiveDataGrid.php
@@ -0,0 +1,753 @@
+
+ * @link http://www.landwehr-software.de/
+ * @copyright Copyright © 2009 LANDWEHR Computer und Software GmbH
+ * @license http://www.pradosoft.com/license/
+ * @package System.Web.UI.ActiveControls
+ */
+
+/**
+ * Includes the following used classes
+ */
+Prado::using('System.Web.UI.ActiveControls.TActiveControlAdapter');
+Prado::using('System.Web.UI.ActiveControls.TActiveLinkButton');
+Prado::using('System.Web.UI.ActiveControls.TActiveImageButton');
+Prado::using('System.Web.UI.ActiveControls.TActiveButton');
+Prado::using('System.Web.UI.ActiveControls.TActiveImage');
+Prado::using('System.Web.UI.ActiveControls.TActiveCheckBox');
+Prado::using('System.Web.UI.WebControls.TDataGrid');
+Prado::using('System.Web.UI.WebControls.TBoundColumn');
+Prado::using('System.Web.UI.WebControls.TEditCommandColumn');
+Prado::using('System.Web.UI.WebControls.TButtonColumn');
+Prado::using('System.Web.UI.WebControls.THyperLinkColumn');
+Prado::using('System.Web.UI.WebControls.TCheckBoxColumn');
+
+/**
+ * TActiveDataGrid class
+ *
+ * TActiveDataGrid represents a data bound and updatable grid control which is the
+ * active counterpart to the original {@link TDataGrid} control.
+ *
+ * This component can be used in the same way as the regular datagrid, the only
+ * difference is that the active datagrid uses callbacks instead of postbacks
+ * for interaction.
+ *
+ * There are also active datagrid columns to work with the TActiveDataGrid, which are
+ * - {@link TActiveBoundColumn}, the active counterpart to {@link TBoundColumn}.
+ * - {@link TActiveEditCommandColumn}, the active counterpart to {@link TEditCommandColumn}.
+ * - {@link TActiveButtonColumn}, the active counterpart to {@link TButtonColumn}.
+ *
+ * Please refer to the original documentation of the regular counterparts for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveDataGrid extends TDataGrid implements IActiveControl, ISurroundable {
+/**
+ * Creates a new callback control, sets the adapter to
+ * TActiveControlAdapter.
+ */
+ public function __construct() {
+ parent::__construct();
+ $this->setAdapter(new TActiveControlAdapter($this));
+ }
+
+ /**
+ * @return TBaseActiveControl standard active control options.
+ */
+ public function getActiveControl() {
+ return $this->getAdapter()->getBaseActiveControl();
+ }
+
+ /**
+ * Sets the data source object associated with the datagrid control.
+ * In addition, the render method of all connected pagers is called so they
+ * get updated when the data source is changed. Also the datagrid registers
+ * itself for rendering in order to get it's content replaced on client side.
+ * @param Traversable|array|string data source object
+ */
+ public function setDataSource($value) {
+ parent::setDataSource($value);
+ if($this->getActiveControl()->canUpdateClientSide()) {
+ $this->renderPager();
+ $this->getPage()->getAdapter()->registerControlToRender($this,$this->getResponse()->createHtmlWriter());
+ }
+ }
+
+ /**
+ * Returns the id of the surrounding container (span).
+ * @return string container id
+ */
+ public function getSurroundingTagId() {
+ return $this->ClientID.'_Container';
+ }
+
+ /**
+ * Creates a pager button.
+ * Depending on the button type, a TActiveLinkButton or a TActiveButton may be created.
+ * If it is enabled (clickable), its command name and parameter will also be set.
+ * It overrides the datagrid's original method to create active controls instead, thus
+ * the pager will do callbacks instead of the regular postbacks.
+ * @param string button type, either LinkButton or PushButton
+ * @param boolean whether the button should be enabled
+ * @param string caption of the button
+ * @param string CommandName corresponding to the OnCommand event of the button
+ * @param string CommandParameter corresponding to the OnCommand event of the button
+ * @return mixed the button instance
+ */
+ protected function createPagerButton($buttonType,$enabled,$text,$commandName,$commandParameter) {
+ if($buttonType===TDataGridPagerButtonType::LinkButton) {
+ if($enabled)
+ $button=new TActiveLinkButton;
+ else {
+ $button=new TLabel;
+ $button->setText($text);
+ return $button;
+ }
+ }
+ else {
+ $button=new TActiveButton;
+ if(!$enabled)
+ $button->setEnabled(false);
+ }
+ $button->setText($text);
+ $button->setCommandName($commandName);
+ $button->setCommandParameter($commandParameter);
+ $button->setCausesValidation(false);
+ return $button;
+ }
+
+ /**
+ * Renders the datagrid.
+ * If the datagrid did not pass the prerender phase yet, it will register itself for rendering later.
+ * Else it will call the {@link renderDataGrid()} method which will do the rendering of the datagrid.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ public function render($writer) {
+ if($this->getHasPreRendered()) {
+ $this->renderDataGrid($writer);
+ if($this->getActiveControl()->canUpdateClientSide()) $this->getPage()->getCallbackClient()->replaceContent($this->getSurroundingTagId(),$writer);
+ }
+ else {
+ $this->getPage()->getAdapter()->registerControlToRender($this,$writer);
+ }
+ }
+
+ /**
+ * Loops through all {@link TActivePager} on the page and registers the ones which are set to paginate
+ * the datagrid for rendering. This is to ensure that the connected pagers are also rendered if the
+ * data source changed.
+ */
+ private function renderPager() {
+ $pager=$this->getPage()->findControlsByType('TActivePager', false);
+ foreach($pager as $item) {
+ if($item->ControlToPaginate==$this->ID) {
+ $writer=$this->getResponse()->createHtmlWriter();
+ $this->getPage()->getAdapter()->registerControlToRender($item,$writer);
+ }
+ }
+ }
+
+ /**
+ * Renders the datagrid by writing a span tag with the container id obtained from {@link getSurroundingTagId()}
+ * which will be called by the replacement method of the client script to update it's content.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ private function renderDataGrid($writer) {
+ $writer->write('');
+ parent::render($writer);
+ $writer->write('');
+ }
+}
+
+
+/**
+ * TActiveBoundColumn class
+ *
+ * TActiveBoundColumn represents a column that is bound to a field in a data source.
+ * The cells in the column will be displayed using the data indexed by
+ * {@link setDataField DataField}. You can customize the display by
+ * setting {@link setDataFormatString DataFormatString}.
+ *
+ * This is the active counterpart to the {@link TBoundColumn} control. For that purpose,
+ * if sorting is allowed, the header links/buttons are replaced by active controls.
+ *
+ * Please refer to the original documentation of the {@link TBoundColumn} for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveBoundColumn extends TBoundColumn {
+ protected function initializeHeaderCell($cell,$columnIndex) {
+ $text=$this->getHeaderText();
+
+ if(($classPath=$this->getHeaderRenderer())!=='') {
+ $control=Prado::createComponent($classPath);
+ if($control instanceof IDataRenderer) {
+ if($control instanceof IItemDataRenderer) {
+ $item=$cell->getParent();
+ $control->setItemIndex($item->getItemIndex());
+ $control->setItemType($item->getItemType());
+ }
+ $control->setData($text);
+ }
+ $cell->getControls()->add($control);
+ }
+ else if($this->getAllowSorting()) {
+ $sortExpression=$this->getSortExpression();
+ if(($url=$this->getHeaderImageUrl())!=='') {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveImageButton');
+ $button->setImageUrl($url);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ if($text!=='') {
+ $button->setAlternateText($text);
+ $button->setToolTip($text);
+ }
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else if($text!=='') {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveLinkButton');
+ $button->setText($text);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else
+ $cell->setText(' ');
+ }
+ else {
+ if(($url=$this->getHeaderImageUrl())!=='') {
+ $image=Prado::createComponent('System.Web.UI.WebControls.TActiveImage');
+ $image->setImageUrl($url);
+ if($text!=='') {
+ $image->setAlternateText($text);
+ $image->setToolTip($text);
+ }
+ $cell->getControls()->add($image);
+ }
+ else if($text!=='')
+ $cell->setText($text);
+ else
+ $cell->setText(' ');
+ }
+ }
+}
+
+
+/**
+ * TActiveEditCommandColumn class
+ *
+ * TActiveEditCommandColumn contains the Edit command buttons for editing data items in each row.
+ *
+ * TActiveEditCommandColumn will create an edit button if a cell is not in edit mode.
+ * Otherwise an update button and a cancel button will be created within the cell.
+ * The button captions are specified using {@link setEditText EditText},
+ * {@link setUpdateText UpdateText}, and {@link setCancelText CancelText}.
+ *
+ * This is the active counterpart to the {@link TEditCommandColumn} control. The buttons for
+ * interaction are replaced by active buttons.
+ *
+ * Please refer to the original documentation of the {@link TEditCommandColumn} for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveEditCommandColumn extends TEditCommandColumn {
+ protected function createButton($commandName,$text,$causesValidation,$validationGroup) {
+ if($this->getButtonType()===TButtonColumnType::LinkButton)
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveLinkButton');
+ else if($this->getButtonType()===TButtonColumnType::PushButton)
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveButton');
+ else // image buttons
+ {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveImageButton');
+ $button->setToolTip($text);
+ if(strcasecmp($commandName,'Update')===0)
+ $url=$this->getUpdateImageUrl();
+ else if(strcasecmp($commandName,'Cancel')===0)
+ $url=$this->getCancelImageUrl();
+ else
+ $url=$this->getEditImageUrl();
+ $button->setImageUrl($url);
+ }
+ $button->setText($text);
+ $button->setCommandName($commandName);
+ $button->setCausesValidation($causesValidation);
+ $button->setValidationGroup($validationGroup);
+ return $button;
+ }
+}
+
+
+/**
+ * TActiveButtonColumn class
+ *
+ * TActiveButtonColumn contains a user-defined command button, such as Add or Remove,
+ * that corresponds with each row in the column.
+ *
+ * This is the active counterpart to the {@link TButtonColumn} control where the
+ * button is replaced by the appropriate active button control.
+ *
+ * Please refer to the original documentation of the {@link TButtonColumn} for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveButtonColumn extends TButtonColumn {
+ public function initializeCell($cell,$columnIndex,$itemType) {
+ if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem) {
+ $buttonType=$this->getButtonType();
+ if($buttonType===TButtonColumnType::LinkButton)
+ $button=new TActiveLinkButton;
+ else if($buttonType===TButtonColumnType::PushButton)
+ $button=new TActiveButton;
+ else // image button
+ {
+ $button=new TActiveImageButton;
+ $button->setImageUrl($this->getImageUrl());
+ $button->setToolTip($this->getText());
+ }
+ $button->setText($this->getText());
+ $button->setCommandName($this->getCommandName());
+ $button->setCausesValidation($this->getCausesValidation());
+ $button->setValidationGroup($this->getValidationGroup());
+ if($this->getDataTextField()!=='' || ($buttonType===TButtonColumnType::ImageButton && $this->getDataImageUrlField()!==''))
+ $button->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
+ $cell->getControls()->add($button);
+ $cell->registerObject('Button',$button);
+ }
+ else
+ parent::initializeCell($cell,$columnIndex,$itemType);
+ }
+}
+
+
+/**
+ * TActiveTemplateColumn class
+ *
+ * TActiveTemplateColumn customizes the layout of controls in the column with templates.
+ * In particular, you can specify {@link setItemTemplate ItemTemplate},
+ * {@link setEditItemTemplate EditItemTemplate}, {@link setHeaderTemplate HeaderTemplate}
+ * and {@link setFooterTemplate FooterTemplate} to customize specific
+ * type of cells in the column.
+ *
+ * This is the active counterpart to the {@link TTemplateColumn} control. For that purpose,
+ * if sorting is allowed, the header links/buttons are replaced by active controls.
+ *
+ * Please refer to the original documentation of the {@link TTemplateColumn} for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveTemplateColumn extends TTemplateColumn {
+ protected function initializeHeaderCell($cell,$columnIndex) {
+ $text=$this->getHeaderText();
+
+ if(($classPath=$this->getHeaderRenderer())!=='') {
+ $control=Prado::createComponent($classPath);
+ if($control instanceof IDataRenderer) {
+ if($control instanceof IItemDataRenderer) {
+ $item=$cell->getParent();
+ $control->setItemIndex($item->getItemIndex());
+ $control->setItemType($item->getItemType());
+ }
+ $control->setData($text);
+ }
+ $cell->getControls()->add($control);
+ }
+ else if($this->getAllowSorting()) {
+ $sortExpression=$this->getSortExpression();
+ if(($url=$this->getHeaderImageUrl())!=='') {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveImageButton');
+ $button->setImageUrl($url);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ if($text!=='')
+ $button->setAlternateText($text);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else if($text!=='') {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveLinkButton');
+ $button->setText($text);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else
+ $cell->setText(' ');
+ }
+ else {
+ if(($url=$this->getHeaderImageUrl())!=='') {
+ $image=Prado::createComponent('System.Web.UI.WebControls.TActiveImage');
+ $image->setImageUrl($url);
+ if($text!=='')
+ $image->setAlternateText($text);
+ $cell->getControls()->add($image);
+ }
+ else if($text!=='')
+ $cell->setText($text);
+ else
+ $cell->setText(' ');
+ }
+ }
+}
+
+/**
+ * TActiveHyperLinkColumn class
+ *
+ * TActiveHyperLinkColumn contains a hyperlink for each item in the column.
+ *
+ * This is the active counterpart to the {@link THyperLinkColumn} control. For that purpose,
+ * if sorting is allowed, the header links/buttons are replaced by active controls.
+ *
+ * Please refer to the original documentation of the {@link THyperLinkColumn} for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveHyperLinkColumn extends THyperLinkColumn
+{
+
+ protected function initializeHeaderCell($cell,$columnIndex)
+ {
+ $text=$this->getHeaderText();
+
+ if(($classPath=$this->getHeaderRenderer())!=='')
+ {
+ $control=Prado::createComponent($classPath);
+ if($control instanceof IDataRenderer)
+ {
+ if($control instanceof IItemDataRenderer)
+ {
+ $item=$cell->getParent();
+ $control->setItemIndex($item->getItemIndex());
+ $control->setItemType($item->getItemType());
+ }
+ $control->setData($text);
+ }
+ $cell->getControls()->add($control);
+ }
+ else if($this->getAllowSorting())
+ {
+ $sortExpression=$this->getSortExpression();
+ if(($url=$this->getHeaderImageUrl())!=='')
+ {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveImageButton');
+ $button->setImageUrl($url);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ if($text!=='')
+ $button->setAlternateText($text);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else if($text!=='')
+ {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveLinkButton');
+ $button->setText($text);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else
+ $cell->setText(' ');
+ }
+ else
+ {
+ if(($url=$this->getHeaderImageUrl())!=='')
+ {
+ $image=Prado::createComponent('System.Web.UI.WebControls.TActiveImage');
+ $image->setImageUrl($url);
+ if($text!=='')
+ $image->setAlternateText($text);
+ $cell->getControls()->add($image);
+ }
+ else if($text!=='')
+ $cell->setText($text);
+ else
+ $cell->setText(' ');
+ }
+ }
+}
+
+/**
+ * TActiveCheckBoxColumn class
+ *
+ * TActiveCheckBoxColumn represents a checkbox column that is bound to a field in a data source.
+ *
+ * This is the active counterpart to the {@link TCheckBoxColumn} control. For that purpose,
+ * if sorting is allowed, the header links/buttons are replaced by active controls.
+ *
+ * Please refer to the original documentation of the {@link TCheckBoxColumn} for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveCheckBoxColumn extends TCheckBoxColumn
+{
+ /**
+ * Initializes the specified cell to its initial values.
+ * This method overrides the parent implementation.
+ * It creates a checkbox inside the cell.
+ * If the column is read-only or if the item is not in edit mode,
+ * the checkbox will be set disabled.
+ * @param TTableCell the cell to be initialized.
+ * @param integer the index to the Columns property that the cell resides in.
+ * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
+ */
+ public function initializeCell($cell,$columnIndex,$itemType)
+ {
+ if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem)
+ {
+ $checkBox=new TActiveCheckBox;
+ if($this->getReadOnly() || $itemType!==TListItemType::EditItem)
+ $checkBox->setEnabled(false);
+ $cell->setHorizontalAlign('Center');
+ $cell->getControls()->add($checkBox);
+ $cell->registerObject('CheckBox',$checkBox);
+ if($this->getDataField()!=='')
+ $checkBox->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
+ }
+ else
+ parent::initializeCell($cell,$columnIndex,$itemType);
+ }
+
+ protected function initializeHeaderCell($cell,$columnIndex)
+ {
+ $text=$this->getHeaderText();
+
+ if(($classPath=$this->getHeaderRenderer())!=='')
+ {
+ $control=Prado::createComponent($classPath);
+ if($control instanceof IDataRenderer)
+ {
+ if($control instanceof IItemDataRenderer)
+ {
+ $item=$cell->getParent();
+ $control->setItemIndex($item->getItemIndex());
+ $control->setItemType($item->getItemType());
+ }
+ $control->setData($text);
+ }
+ $cell->getControls()->add($control);
+ }
+ else if($this->getAllowSorting())
+ {
+ $sortExpression=$this->getSortExpression();
+ if(($url=$this->getHeaderImageUrl())!=='')
+ {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveImageButton');
+ $button->setImageUrl($url);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ if($text!=='')
+ $button->setAlternateText($text);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else if($text!=='')
+ {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveLinkButton');
+ $button->setText($text);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else
+ $cell->setText(' ');
+ }
+ else
+ {
+ if(($url=$this->getHeaderImageUrl())!=='')
+ {
+ $image=Prado::createComponent('System.Web.UI.WebControls.TActiveImage');
+ $image->setImageUrl($url);
+ if($text!=='')
+ $image->setAlternateText($text);
+ $cell->getControls()->add($image);
+ }
+ else if($text!=='')
+ $cell->setText($text);
+ else
+ $cell->setText(' ');
+ }
+ }
+}
+
+/**
+ * TActiveDropDownListColumn class
+ *
+ * TActiveDropDownListColumn represents a column that is bound to a field in a data source.
+ *
+ * This is the active counterpart to the {@link TDropDownListColumn} control. For that purpose,
+ * if sorting is allowed, the header links/buttons are replaced by active controls.
+ *
+ * Please refer to the original documentation of the {@link TDropDownListColumn} for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveDropDownListColumn extends TDropDownListColumn
+{
+ protected function initializeHeaderCell($cell,$columnIndex)
+ {
+ $text=$this->getHeaderText();
+
+ if(($classPath=$this->getHeaderRenderer())!=='')
+ {
+ $control=Prado::createComponent($classPath);
+ if($control instanceof IDataRenderer)
+ {
+ if($control instanceof IItemDataRenderer)
+ {
+ $item=$cell->getParent();
+ $control->setItemIndex($item->getItemIndex());
+ $control->setItemType($item->getItemType());
+ }
+ $control->setData($text);
+ }
+ $cell->getControls()->add($control);
+ }
+ else if($this->getAllowSorting())
+ {
+ $sortExpression=$this->getSortExpression();
+ if(($url=$this->getHeaderImageUrl())!=='')
+ {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveImageButton');
+ $button->setImageUrl($url);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ if($text!=='')
+ $button->setAlternateText($text);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else if($text!=='')
+ {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveLinkButton');
+ $button->setText($text);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else
+ $cell->setText(' ');
+ }
+ else
+ {
+ if(($url=$this->getHeaderImageUrl())!=='')
+ {
+ $image=Prado::createComponent('System.Web.UI.WebControls.TActiveImage');
+ $image->setImageUrl($url);
+ if($text!=='')
+ $image->setAlternateText($text);
+ $cell->getControls()->add($image);
+ }
+ else if($text!=='')
+ $cell->setText($text);
+ else
+ $cell->setText(' ');
+ }
+ }
+
+}
+
+/**
+ * TActiveLiteralColumn class
+ *
+ * TActiveLiteralColumn represents a static text column that is bound to a field in a data source.
+ * The cells in the column will be displayed with static texts using the data indexed by
+ * {@link setDataField DataField}. You can customize the display by
+ * setting {@link setDataFormatString DataFormatString}.
+ *
+ * If {@link setDataField DataField} is not specified, the cells will be filled
+ * with {@link setText Text}.
+ *
+ * If {@link setEncode Encode} is true, the static texts will be HTML-encoded.
+ *
+ * This is the active counterpart to the {@link TLiteralColumn} control. For that purpose,
+ * if sorting is allowed, the header links/buttons are replaced by active controls.
+ *
+ * Please refer to the original documentation of the {@link TLiteralColumn} for usage.
+ *
+ * @author Fabio Bas
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2.0a
+ */
+class TActiveLiteralColumn extends TLiteralColumn {
+ protected function initializeHeaderCell($cell,$columnIndex) {
+ $text=$this->getHeaderText();
+
+ if(($classPath=$this->getHeaderRenderer())!=='') {
+ $control=Prado::createComponent($classPath);
+ if($control instanceof IDataRenderer) {
+ if($control instanceof IItemDataRenderer) {
+ $item=$cell->getParent();
+ $control->setItemIndex($item->getItemIndex());
+ $control->setItemType($item->getItemType());
+ }
+ $control->setData($text);
+ }
+ $cell->getControls()->add($control);
+ }
+ else if($this->getAllowSorting()) {
+ $sortExpression=$this->getSortExpression();
+ if(($url=$this->getHeaderImageUrl())!=='') {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveImageButton');
+ $button->setImageUrl($url);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ if($text!=='') {
+ $button->setAlternateText($text);
+ $button->setToolTip($text);
+ }
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else if($text!=='') {
+ $button=Prado::createComponent('System.Web.UI.WebControls.TActiveLinkButton');
+ $button->setText($text);
+ $button->setCommandName(TDataGrid::CMD_SORT);
+ $button->setCommandParameter($sortExpression);
+ $button->setCausesValidation(false);
+ $cell->getControls()->add($button);
+ }
+ else
+ $cell->setText(' ');
+ }
+ else {
+ if(($url=$this->getHeaderImageUrl())!=='') {
+ $image=Prado::createComponent('System.Web.UI.WebControls.TActiveImage');
+ $image->setImageUrl($url);
+ if($text!=='') {
+ $image->setAlternateText($text);
+ $image->setToolTip($text);
+ }
+ $cell->getControls()->add($image);
+ }
+ else if($text!=='')
+ $cell->setText($text);
+ else
+ $cell->setText(' ');
+ }
+ }
+}
diff --git a/framework/Web/UI/ActiveControls/TActiveDataList.php b/framework/Web/UI/ActiveControls/TActiveDataList.php
new file mode 100644
index 00000000..dbf70067
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TActiveDataList.php
@@ -0,0 +1,117 @@
+
+ * @copyright Copyright © 2008, PradoSoft
+ * @license http://www.pradosoft.com/license
+ * @package System.Web.UI.ActiveControls
+ * @version $Id: TActiveDataList.php 2706 2009-09-24 14:42:30Z rojaro $
+ */
+
+/**
+ * TActiveDataList class
+ *
+ * TActiveDataList represents a data bound and updatable grid control which is the
+ * active counterpart to the original {@link TDataList} control.
+ *
+ * This component can be used in the same way as the regular datalist, the only
+ * difference is that the active datalist uses callbacks instead of postbacks
+ * for interaction.
+ *
+ * Please refer to the original documentation of the regular counterparts for usage.
+ *
+ * @author Marcos Aurelio Nobre
+ * @package System.Web.UI.ActiveControls
+ */
+class TActiveDataList extends TDataList implements IActiveControl {
+
+ /**
+ * Creates a new callback control, sets the adapter to
+ * TActiveControlAdapter.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setAdapter(new TActiveControlAdapter($this));
+ }
+
+ /**
+ * @return TBaseActiveControl standard active control options.
+ */
+ public function getActiveControl()
+ {
+ return $this->getAdapter()->getBaseActiveControl();
+ }
+
+ /**
+ * Sets the data source object associated with the repeater control.
+ * In addition, the render method of all connected pagers is called so they
+ * get updated when the data source is changed. Also the repeater registers
+ * itself for rendering in order to get it's content replaced on client side.
+ * @param Traversable|array|string data source object
+ */
+ public function setDataSource($value)
+ {
+ parent::setDataSource($value);
+ if($this->getActiveControl()->canUpdateClientSide()) {
+ $this->renderPager();
+ $this->getPage()->getAdapter()->registerControlToRender($this,$this->getResponse()->createHtmlWriter());
+ }
+ }
+
+ /**
+ * Returns the id of the surrounding container (span).
+ * @return string container id
+ */
+ protected function getContainerID()
+ {
+ return $this->ClientID.'_Container';
+ }
+
+ /**
+ * Renders the repeater.
+ * If the repeater did not pass the prerender phase yet, it will register itself for rendering later.
+ * Else it will call the {@link renderRepeater()} method which will do the rendering of the repeater.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ public function render($writer)
+ {
+ if($this->getHasPreRendered()) {
+ $this->renderDataList($writer);
+ if($this->getActiveControl()->canUpdateClientSide()) $this->getPage()->getCallbackClient()->replaceContent($this->getContainerID(),$writer);
+ }
+ else {
+ $this->getPage()->getAdapter()->registerControlToRender($this,$writer);
+ }
+ }
+
+ /**
+ * Loops through all {@link TActivePager} on the page and registers the ones which are set to paginate
+ * the repeater for rendering. This is to ensure that the connected pagers are also rendered if the
+ * data source changed.
+ */
+ private function renderPager()
+ {
+ $pager=$this->getPage()->findControlsByType('TActivePager', false);
+ foreach($pager as $item)
+ {
+ if($item->ControlToPaginate==$this->ID) {
+ $writer=$this->getResponse()->createHtmlWriter();
+ $this->getPage()->getAdapter()->registerControlToRender($item,$writer);
+ }
+ }
+ }
+
+ /**
+ * Renders the repeater by writing a span tag with the container id obtained from {@link getContainerID()}
+ * which will be called by the replacement method of the client script to update it's content.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ private function renderDataList($writer)
+ {
+ $writer->write('');
+ parent::render($writer);
+ $writer->write('');
+ }
+}
diff --git a/framework/Web/UI/ActiveControls/TActiveLabel.php b/framework/Web/UI/ActiveControls/TActiveLabel.php
index 4105e3dc..e2d14419 100644
--- a/framework/Web/UI/ActiveControls/TActiveLabel.php
+++ b/framework/Web/UI/ActiveControls/TActiveLabel.php
@@ -1,90 +1,90 @@
-
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Web.UI.ActiveControls
- */
-
-/**
- * Load active control adapter.
- */
-Prado::using('System.Web.UI.ActiveControls.TActiveControlAdapter');
-
-/**
- * TActiveLabel class
- *
- * The active control counterpart of TLabel component. When
- * {@link TBaseActiveControl::setEnableUpdate ActiveControl.EnableUpdate}
- * property is true the during a callback request, setting {@link setText Text}
- * property will also set the text of the label on the client upon callback
- * completion. Similarly, setting {@link setForControl ForControl} will also set
- * the client-side "for" attribute on the label.
- *
- * @author Wei Zhuo
- * @version $Id$
- * @package System.Web.UI.ActiveControls
- * @since 3.1
- */
-class TActiveLabel extends TLabel implements IActiveControl
-{
- /**
- * Creates a new callback control, sets the adapter to
- * TActiveControlAdapter. If you override this class, be sure to set the
- * adapter appropriately by, for example, by calling this constructor.
- */
- public function __construct()
- {
- parent::__construct();
- $this->setAdapter(new TActiveControlAdapter($this));
- }
-
- /**
- * @return TBaseActiveControl basic active control options.
- */
- public function getActiveControl()
- {
- return $this->getAdapter()->getBaseActiveControl();
- }
-
- /**
- * On callback response, the inner HTML of the label is updated.
- * @param string the text value of the label
- */
- public function setText($value)
- {
- parent::setText($value);
- if($this->getActiveControl()->canUpdateClientSide())
- $this->getPage()->getCallbackClient()->update($this, $value);
- }
-
- /**
- * Sets the ID of the control that the label is associated with.
- * The control must be locatable via {@link TControl::findControl} using the ID.
- * On callback response, the For attribute of the label is updated.
- * @param string the associated control ID
- */
- public function setForControl($value)
- {
- parent::setForControl($value);
- if($this->getActiveControl()->canUpdateClientSide())
- {
- $id=$this->findControl($value)->getClientID();
- $this->getPage()->getCallbackClient()->setAttribute($this, 'for', $id);
- }
- }
-
- /**
- * Adds attribute id to the renderer.
+
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2008 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI.ActiveControls
+ */
+
+/**
+ * Load active control adapter.
+ */
+Prado::using('System.Web.UI.ActiveControls.TActiveControlAdapter');
+
+/**
+ * TActiveLabel class
+ *
+ * The active control counterpart of TLabel component. When
+ * {@link TBaseActiveControl::setEnableUpdate ActiveControl.EnableUpdate}
+ * property is true the during a callback request, setting {@link setText Text}
+ * property will also set the text of the label on the client upon callback
+ * completion. Similarly, setting {@link setForControl ForControl} will also set
+ * the client-side "for" attribute on the label.
+ *
+ * @author Wei Zhuo
+ * @version $Id$
+ * @package System.Web.UI.ActiveControls
+ * @since 3.1
+ */
+class TActiveLabel extends TLabel implements IActiveControl
+{
+ /**
+ * Creates a new callback control, sets the adapter to
+ * TActiveControlAdapter. If you override this class, be sure to set the
+ * adapter appropriately by, for example, by calling this constructor.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setAdapter(new TActiveControlAdapter($this));
+ }
+
+ /**
+ * @return TBaseActiveControl basic active control options.
+ */
+ public function getActiveControl()
+ {
+ return $this->getAdapter()->getBaseActiveControl();
+ }
+
+ /**
+ * On callback response, the inner HTML of the label is updated.
+ * @param string the text value of the label
+ */
+ public function setText($value)
+ {
+ parent::setText($value);
+ if($this->getActiveControl()->canUpdateClientSide())
+ $this->getPage()->getCallbackClient()->update($this, $value);
+ }
+
+ /**
+ * Sets the ID of the control that the label is associated with.
+ * The control must be locatable via {@link TControl::findControl} using the ID.
+ * On callback response, the For attribute of the label is updated.
+ * @param string the associated control ID
+ */
+ public function setForControl($value)
+ {
+ parent::setForControl($value);
+ if($this->getActiveControl()->canUpdateClientSide())
+ {
+ $id=$this->findControl($value)->getClientID();
+ $this->getPage()->getCallbackClient()->setAttribute($this, 'for', $id);
+ }
+ }
+
+ /**
+ * Adds attribute id to the renderer.
* @param THtmlWriter the writer used for the rendering purpose
- */
- protected function addAttributesToRender($writer) {
- $writer->addAttribute('id',$this->getClientID());
- parent::addAttributesToRender($writer);
- }
-}
-
+ */
+ protected function addAttributesToRender($writer) {
+ $writer->addAttribute('id',$this->getClientID());
+ parent::addAttributesToRender($writer);
+ }
+}
+
diff --git a/framework/Web/UI/ActiveControls/TActiveMultiView.php b/framework/Web/UI/ActiveControls/TActiveMultiView.php
new file mode 100644
index 00000000..5040ef94
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TActiveMultiView.php
@@ -0,0 +1,110 @@
+
+ * @link http://www.landwehr-software.de/
+ * @copyright Copyright © 2009 LANDWEHR Computer und Software GmbH
+ * @license http://www.pradosoft.com/license/
+ * @package System.Web.UI.ActiveControls
+ */
+
+/**
+ * Includes the following used classes
+ */
+Prado::using('System.Web.UI.WebControls.TMultiView');
+
+/**
+ * TActiveMultiView class.
+ *
+ * TActiveMultiView is the active counterpart to the original {@link TMultiView} control.
+ * It re-renders on Callback when {@link setActiveView ActiveView} or
+ * {@link setActiveViewIndex ActiveViewIndex} is called.
+ *
+ * Please refer to the original documentation of the regular counterpart for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.1.6
+ */
+class TActiveMultiView extends TMultiView implements IActiveControl
+{
+ /**
+ * Creates a new callback control, sets the adapter to
+ * TActiveControlAdapter.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setAdapter(new TActiveControlAdapter($this));
+ }
+
+ /**
+ * @return TBaseActiveControl standard active control options.
+ */
+ public function getActiveControl()
+ {
+ return $this->getAdapter()->getBaseActiveControl();
+ }
+
+ /**
+ * Returns the id of the surrounding container (span).
+ * @return string container id
+ */
+ protected function getContainerID()
+ {
+ return $this->ClientID.'_Container';
+ }
+
+ /**
+ * Renders the TActiveMultiView.
+ * If the MutliView did not pass the prerender phase yet, it will register itself for rendering later.
+ * Else it will call the {@link renderMultiView()} method which will do the rendering of the MultiView.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ public function render($writer)
+ {
+ if($this->getHasPreRendered()) {
+ $this->renderMultiView($writer);
+ if($this->getActiveControl()->canUpdateClientSide())
+ $this->getPage()->getCallbackClient()->replaceContent($this->getContainerID(),$writer);
+ }
+ else
+ $this->getPage()->getAdapter()->registerControlToRender($this,$writer);
+ }
+
+ /**
+ * Renders the TActiveMultiView by writing a span tag with the container id obtained from {@link getContainerID()}
+ * which will be called by the replacement method of the client script to update it's content.
+ * @param $writer THtmlWriter writer for the rendering purpose
+ */
+ protected function renderMultiView($writer)
+ {
+ $writer->addAttribute('id', $this->getContainerID());
+ $writer->renderBeginTag('span');
+ parent::render($writer);
+ $writer->renderEndTag();
+ }
+
+ /**
+ * @param integer the zero-based index of the current view in the view collection. -1 if no active view.
+ * @throws TInvalidDataValueException if the view index is invalid
+ */
+ public function setActiveViewIndex($value)
+ {
+ parent::setActiveViewIndex($value);
+ if($this->getActiveControl()->canUpdateClientSide())
+ $this->getPage()->getAdapter()->registerControlToRender($this,$this->getResponse()->createHtmlWriter());
+ }
+
+ /**
+ * @param TView the view to be activated
+ * @throws TInvalidOperationException if the view is not in the view collection
+ */
+ public function setActiveView($value)
+ {
+ parent::setActiveView($value);
+ if($this->getActiveControl()->canUpdateClientSide())
+ $this->getPage()->getAdapter()->registerControlToRender($this,$this->getResponse()->createHtmlWriter());
+ }
+}
diff --git a/framework/Web/UI/ActiveControls/TActiveRepeater.php b/framework/Web/UI/ActiveControls/TActiveRepeater.php
new file mode 100644
index 00000000..ccfda4aa
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TActiveRepeater.php
@@ -0,0 +1,113 @@
+
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ * @version $Id: TActiveRepeater.php 2707 2009-09-29 10:33:30Z Christophe.Boulain $
+ */
+
+/**
+ * TActiveRepeater class
+ *
+ * TActiveRepeater represents a data bound and updatable grid control which is the
+ * active counterpart to the original {@link TRepeater} control.
+ *
+ * This component can be used in the same way as the regular datagrid, the only
+ * difference is that the active repeater uses callbacks instead of postbacks
+ * for interaction.
+ *
+ * Please refer to the original documentation of the regular counterparts for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveRepeater extends TRepeater implements IActiveControl, ISurroundable {
+
+/**
+ * Creates a new callback control, sets the adapter to
+ * TActiveControlAdapter.
+ */
+ public function __construct() {
+ parent::__construct();
+ $this->setAdapter(new TActiveControlAdapter($this));
+ }
+
+ /**
+ * @return TBaseActiveControl standard active control options.
+ */
+ public function getActiveControl() {
+ return $this->getAdapter()->getBaseActiveControl();
+ }
+
+ /**
+ * Sets the data source object associated with the repeater control.
+ * In addition, the render method of all connected pagers is called so they
+ * get updated when the data source is changed. Also the repeater registers
+ * itself for rendering in order to get it's content replaced on client side.
+ * @param Traversable|array|string data source object
+ */
+ public function setDataSource($value) {
+ parent::setDataSource($value);
+ if($this->getActiveControl()->canUpdateClientSide()) {
+ $this->renderPager();
+ $this->getPage()->getAdapter()->registerControlToRender($this,$this->getResponse()->createHtmlWriter());
+ }
+ }
+
+ /**
+ * Returns the id of the surrounding container (span).
+ * @return string container id
+ */
+ public function getSurroundingTagID() {
+ return $this->ClientID.'_Container';
+ }
+
+ /**
+ * Renders the repeater.
+ * If the repeater did not pass the prerender phase yet, it will register itself for rendering later.
+ * Else it will call the {@link renderRepeater()} method which will do the rendering of the repeater.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ public function render($writer) {
+ if($this->getHasPreRendered()) {
+ $this->renderRepeater($writer);
+ if($this->getActiveControl()->canUpdateClientSide()) $this->getPage()->getCallbackClient()->replaceContent($this->getSurroundingTagId(),$writer);
+ }
+ else {
+ $this->getPage()->getAdapter()->registerControlToRender($this,$writer);
+ }
+ }
+
+ /**
+ * Loops through all {@link TActivePager} on the page and registers the ones which are set to paginate
+ * the repeater for rendering. This is to ensure that the connected pagers are also rendered if the
+ * data source changed.
+ */
+ private function renderPager() {
+ $pager=$this->getPage()->findControlsByType('TActivePager', false);
+ foreach($pager as $item) {
+ if($item->ControlToPaginate==$this->ID) {
+ $writer=$this->getResponse()->createHtmlWriter();
+ $this->getPage()->getAdapter()->registerControlToRender($item,$writer);
+ }
+ }
+ }
+
+ /**
+ * Renders the repeater by writing a span tag with the container id obtained from {@link getSurroundingTagID()}
+ * which will be called by the replacement method of the client script to update it's content.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ private function renderRepeater($writer) {
+ $writer->addAttribute('id',$this->getSurroundingTagID());
+ $writer->renderBeginTag('span');
+ parent::render($writer);
+ $writer->renderEndTag();
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TActiveTableCell.php b/framework/Web/UI/ActiveControls/TActiveTableCell.php
new file mode 100644
index 00000000..833ce6e7
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TActiveTableCell.php
@@ -0,0 +1,244 @@
+
+ * @link http://www.landwehr-software.de/
+ * @copyright Copyright © 2009 LANDWEHR Computer und Software GmbH
+ * @license http://www.pradosoft.com/license/
+ * @package System.Web.UI.ActiveControls
+ * @version $Id$
+ */
+
+/**
+ * Includes the following used classes
+ */
+Prado::using('System.Web.UI.WebControls.TTableRow');
+Prado::using('System.Web.UI.ActiveControls.TActiveControlAdapter');
+Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter');
+
+/**
+ * TActiveTableCell class.
+ *
+ * TActiveTableCell is the active counterpart to the original {@link TTableCell} control
+ * and displays a table cell. The horizontal and vertical alignments of the cell
+ * are specified via {@link setHorizontalAlign HorizontalAlign} and
+ * {@link setVerticalAlign VerticalAlign} properties, respectively.
+ *
+ * TActiveTableCell allows the contents of the table cell to be changed during callback. When
+ * {@link onCellSelected CellSelected} property is set, selecting (clicking on) the cell will
+ * perform a callback request causing {@link onCellSelected OnCellSelected} event to be fired.
+ *
+ * It will also bubble the {@link onCellSelected OnCellSelected} event up to it's parent
+ * {@link TActiveTableRow} control which will fire up the event handlers if implemented.
+ *
+ * TActiveTableCell allows the client-side cell contents to be updated during a
+ * callback response by getting a new writer, invoking the render method and flushing the
+ * output, similar to a {@link TActivePanel} control.
+ *
+ * function callback_request($sender, $param)
+ * {
+ * $this->active_cell->render($param->getNewWriter());
+ * }
+ *
+ *
+ * Please refer to the original documentation of the regular counterpart for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @version $Id$
+ * @since 3.2
+ */
+class TActiveTableCell extends TTableCell implements ICallbackEventHandler, IActiveControl
+{
+
+ /**
+ * @var TTable parent row control containing the cell
+ */
+ private $_row;
+
+ /**
+ * Creates a new callback control, sets the adapter to TActiveControlAdapter.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setAdapter(new TActiveControlAdapter($this));
+ }
+
+ /**
+ * @return TBaseActiveCallbackControl standard callback control options.
+ */
+ public function getActiveControl()
+ {
+ return $this->getAdapter()->getBaseActiveControl();
+ }
+
+ /**
+ * @return string corresponding javascript class name for this TActiveTableCell.
+ */
+ protected function getClientClassName()
+ {
+ return 'Prado.WebUI.TActiveTableCell';
+ }
+
+ /**
+ * Raises the callback event. This method is required by {@link ICallbackEventHandler}
+ * interface. It will raise {@link onCellSelected OnCellSelected} event with a
+ * {@link TActiveTableCellEventParameter} containing the zero-based index of the
+ * TActiveTableCell.
+ * This method is mainly used by framework and control developers.
+ * @param TCallbackEventParameter the event parameter
+ */
+ public function raiseCallbackEvent($param)
+ {
+ $parameter = new TActiveTableCellEventParameter($this->getResponse(), $param->getCallbackParameter(), $this->getCellIndex());
+ $this->onCellSelected($parameter);
+ $this->raiseBubbleEvent($this, $parameter);
+ }
+
+ /**
+ * This method is invoked when a callback is requested. The method raises
+ * 'OnCellSelected' event to fire up the event handlers. If you override this
+ * method, be sure to call the parent implementation so that the event
+ * handler can be invoked.
+ * @param TActiveTableCellEventParameter event parameter to be passed to the event handlers
+ */
+ public function onCellSelected($param)
+ {
+ $this->raiseEvent('OnCellSelected', $this, $param);
+ }
+
+ /**
+ * Ensure that the ID attribute is rendered and registers the javascript code
+ * for initializing the active control if the event handler for the
+ * {@link onCellSelected OnCellSelected} event is set.
+ * @param THtmlWriter the writer responsible for rendering
+ */
+ protected function addAttributesToRender($writer)
+ {
+ parent::addAttributesToRender($writer);
+ $writer->addAttribute('id', $this->getClientID());
+ if ($this->hasEventHandler('OnCellSelected'))
+ $this->getActiveControl()->registerCallbackClientScript($this->getClientClassName(), $this->getPostBackOptions());
+ }
+
+ /**
+ * Renders and replaces the cell's content on the client-side. When render() is
+ * called before the OnPreRender event, such as when render() is called during
+ * a callback event handler, the rendering is defered until OnPreRender event
+ * is raised.
+ * @param THtmlWriter html writer
+ */
+ public function render($writer)
+ {
+ if ($this->getHasPreRendered())
+ {
+ parent::render($writer);
+ if ($this->getActiveControl()->canUpdateClientSide())
+ $this->getPage()->getCallbackClient()->replaceContent($this, $writer);
+ }
+ else {
+ $this->getPage()->getAdapter()->registerControlToRender($this, $writer);
+ // If we update a TActiveTableCell on callback, we shouldn't update all childs,
+ // because the whole content will be replaced by the parent.
+ if ($this->getHasControls())
+ {
+ foreach ($this->findControlsByType('IActiveControl', false) as $control)
+ $control->getActiveControl()->setEnableUpdate(false);
+ }
+ }
+ }
+
+ /**
+ * Returns postback specifications for the table cell.
+ * This method is used by framework and control developers.
+ * @return array parameters about how the row defines its postback behavior.
+ */
+ protected function getPostBackOptions()
+ {
+ $options['ID'] = $this->getClientID();
+ $options['EventTarget'] = $this->getUniqueID();
+ return $options;
+ }
+
+ /**
+ * Returns the zero-based index of the TActiveTableCell within the {@link TTableCellCollection}
+ * of the parent {@link TTableRow} control. Raises a {@link TConfigurationException} if the cell
+ * is no member of the cell collection.
+ * @return integer the zero-based index of the cell
+ */
+ public function getCellIndex()
+ {
+ foreach ($this->getRow()->getCells() as $key => $row)
+ if ($row == $this) return $key;
+ throw new TConfigurationException('tactivetablecell_control_notincollection', get_class($this), $this->getUniqueID());
+ }
+
+ /**
+ * Returns the parent {@link TTableRow} control by looping through all parents until a {@link TTableRow}
+ * is found. Raises a {@link TConfigurationException} if no row control is found.
+ * @return TTableRow the parent row control
+ */
+ public function getRow()
+ {
+ if ($this->_row === null)
+ {
+ $row = $this->getParent();
+ while (!($row instanceof TTableRow) && $row !== null)
+ {
+ $row = $row->getParent();
+ }
+ if ($row instanceof TTableRow) $this->_row = $row;
+ else throw new TConfigurationException('tactivetablecell_control_outoftable', get_class($this), $this->getUniqueID());
+ }
+ return $this->_row;
+ }
+
+}
+
+/**
+ * TActiveTableCellEventParameter class.
+ *
+ * The TActiveTableCellEventParameter provides the parameter passed during the callback
+ * requestion in the {@link getCallbackParameter CallbackParameter} property. The
+ * callback response content (e.g. new HTML content) must be rendered
+ * using an THtmlWriter obtained from the {@link getNewWriter NewWriter}
+ * property, which returns a NEW instance of TCallbackResponseWriter.
+ *
+ * The {@link getSelectedCellIndex SelectedCellIndex} is a zero-based index of the
+ * TActiveTableCell , -1 if the cell is not part of the cell collection (this shouldn't
+ * happen though since an exception is thrown before).
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveTableCellEventParameter extends TCallbackEventParameter
+{
+
+ /**
+ * @var integer the zero-based index of the cell.
+ */
+ private $_selectedCellIndex = -1;
+
+ /**
+ * Creates a new TActiveTableRowEventParameter.
+ */
+ public function __construct($response, $parameter, $index=-1)
+ {
+ parent::__construct($response, $parameter);
+ $this->_selectedCellIndex = $index;
+ }
+
+ /**
+ * Returns the zero-based index of the {@link TActiveTableCell} within the
+ * {@link TTableCellCollection} of the parent {@link TTableRow} control.
+ * @return integer the zero-based index of the cell.
+ */
+ public function getSelectedCellIndex()
+ {
+ return $this->_selectedCellIndex;
+ }
+
+}
\ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TActiveTableRow.php b/framework/Web/UI/ActiveControls/TActiveTableRow.php
new file mode 100644
index 00000000..31287617
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TActiveTableRow.php
@@ -0,0 +1,262 @@
+
+ * @link http://www.landwehr-software.de/
+ * @copyright Copyright © 2009 LANDWEHR Computer und Software GmbH
+ * @license http://www.pradosoft.com/license/
+ * @package System.Web.UI.ActiveControls
+ * @version $Id$
+ */
+
+/**
+ * Includes the following used classes
+ */
+Prado::using('System.Web.UI.WebControls.TTableRow');
+Prado::using('System.Web.UI.ActiveControls.TActiveControlAdapter');
+Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter');
+
+/**
+ * TActiveTableRow class.
+ *
+ * TActiveTableRow is the active counterpart to the original {@link TTableRow} control
+ * and displays a table row. The table cells in the row can be accessed
+ * via {@link getCells Cells}. The horizontal and vertical alignments of the row
+ * are specified via {@link setHorizontalAlign HorizontalAlign} and
+ * {@link setVerticalAlign VerticalAlign} properties, respectively.
+ *
+ * TActiveTableRow allows the contents of the table row to be changed during callback. When
+ * {@link onRowSelected RowSelected} property is set, selecting (clicking on) the row will
+ * perform a callback request causing {@link onRowSelected OnRowSelected} event to be fired.
+ *
+ * It will also respond to a bubbled {@link onCellSelected OnCellSelected} event of a
+ * {@link TActiveTableCell} child control and fire a {@link onRowSelected OnRowSelected} event.
+ *
+ * TActiveTableRow allows the client-side row contents to be updated during a
+ * callback response by getting a new writer, invoking the render method and flushing the
+ * output, similar to a {@link TActivePanel} control.
+ *
+ * function callback_request($sender, $param)
+ * {
+ * $this->active_row->render($param->getNewWriter());
+ * }
+ *
+ *
+ * Please refer to the original documentation of the regular counterpart for usage.
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @version $Id$
+ * @since 3.2
+ */
+class TActiveTableRow extends TTableRow implements ICallbackEventHandler, IActiveControl
+{
+
+ /**
+ * @var TTable parent table control containing the row
+ */
+ private $_table;
+
+ /**
+ * Creates a new callback control, sets the adapter to TActiveControlAdapter.
+ * */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setAdapter(new TActiveControlAdapter($this));
+ }
+
+ /**
+ * @return TBaseActiveCallbackControl standard callback control options.
+ */
+ public function getActiveControl()
+ {
+ return $this->getAdapter()->getBaseActiveControl();
+ }
+
+ /**
+ * @return string corresponding javascript class name for this TActiveTableRow.
+ */
+ protected function getClientClassName()
+ {
+ return 'Prado.WebUI.TActiveTableRow';
+ }
+
+ /**
+ * Raises the callback event. This method is required by {@link ICallbackEventHandler}
+ * interface. It will raise {@link onRowSelected OnRowSelected} event with a
+ * {@link TActiveTableRowEventParameter} containing the zero-based index of the
+ * TActiveTableRow.
+ * This method is mainly used by framework and control developers.
+ * @param TCallbackEventParameter the event parameter
+ */
+ public function raiseCallbackEvent($param)
+ {
+ $parameter = new TActiveTableRowEventParameter($this->getResponse(), $param->getCallbackParameter(), $this->getRowIndex());
+ $this->onRowSelected($parameter);
+ }
+
+ /**
+ * This method overrides parent's implementation and raises the control's
+ * callback event. This will fire the {@link onRowSelected OnRowSelected}
+ * event if an appropriate event handler is implemented.
+ * @param TControl the sender of the event
+ * @param TEventParameter event parameter
+ * @return boolean whether the event bubbling should stop here.
+ */
+ public function bubbleEvent($sender, $param)
+ {
+ if ($param instanceof TActiveTableCellEventParameter)
+ {
+ $this->raiseCallbackEvent($param);
+ return true;
+ }
+ else return false;
+ }
+
+ /**
+ * This method is invoked when a callback is requested. The method raises
+ * 'OnRowSelected' event to fire up the event handlers. If you override this
+ * method, be sure to call the parent implementation so that the event
+ * handler can be invoked.
+ * @param TActiveTableRowEventParameter event parameter to be passed to the event handlers
+ */
+ public function onRowSelected($param)
+ {
+ $this->raiseEvent('OnRowSelected', $this, $param);
+ }
+
+ /**
+ * Ensure that the ID attribute is rendered and registers the javascript code
+ * for initializing the active control if the event handler for the
+ * {@link onRowSelected OnRowSelected} event is set.
+ * @param THtmlWriter the writer responsible for rendering
+ */
+ protected function addAttributesToRender($writer)
+ {
+ parent::addAttributesToRender($writer);
+ $writer->addAttribute('id', $this->getClientID());
+ if ($this->hasEventHandler('OnRowSelected'))
+ $this->getActiveControl()->registerCallbackClientScript($this->getClientClassName(), $this->getPostBackOptions());
+ }
+
+ /**
+ * Renders and replaces the row's content on the client-side. When render() is
+ * called before the OnPreRender event, such as when render() is called during
+ * a callback event handler, the rendering is defered until OnPreRender event
+ * is raised.
+ * @param THtmlWriter html writer
+ */
+ public function render($writer)
+ {
+ if ($this->getHasPreRendered())
+ {
+ parent::render($writer);
+ if ($this->getActiveControl()->canUpdateClientSide())
+ $this->getPage()->getCallbackClient()->replaceContent($this, $writer);
+ }
+ else
+ {
+ $this->getPage()->getAdapter()->registerControlToRender($this, $writer);
+ // If we update a TActiveTableRow on callback, we shouldn't update all childs,
+ // because the whole content will be replaced by the parent.
+ if ($this->getHasControls())
+ {
+ foreach ($this->findControlsByType('IActiveControl', false) as $control)
+ $control->getActiveControl()->setEnableUpdate(false);
+ }
+ }
+ }
+
+ /**
+ * Returns postback specifications for the table row.
+ * This method is used by framework and control developers.
+ * @return array parameters about how the row defines its postback behavior.
+ */
+ protected function getPostBackOptions()
+ {
+ $options['ID'] = $this->getClientID();
+ $options['EventTarget'] = $this->getUniqueID();
+ return $options;
+ }
+
+ /**
+ * Returns the zero-based index of the TActiveTableRow within the {@link TTableRowCollection}
+ * of the parent {@link TTable} control. Raises a {@link TConfigurationException} if the row
+ * is no member of the row collection.
+ * @return integer the zero-based index of the row
+ */
+ public function getRowIndex()
+ {
+ foreach ($this->getTable()->getRows() as $key => $row)
+ if ($row == $this) return $key;
+ throw new TConfigurationException('tactivetablerow_control_notincollection', get_class($this), $this->getUniqueID());
+ }
+
+ /**
+ * Returns the parent {@link TTable} control by looping through all parents until a {@link TTable}
+ * is found. Raises a {@link TConfigurationException} if no table control is found.
+ * @return TTable the parent table control
+ */
+ public function getTable()
+ {
+ if ($this->_table === null)
+ {
+ $table = $this->getParent();
+ while (!($table instanceof TTable) && $table !== null)
+ {
+ $table = $table->getParent();
+ }
+ if ($table instanceof TTable) $this->_table = $table;
+ else throw new TConfigurationException('tactivetablerow_control_outoftable', get_class($this), $this->getUniqueID());
+ }
+ return $this->_table;
+ }
+
+}
+
+/**
+ * TActiveTableRowEventParameter class.
+ *
+ * The TActiveTableRowEventParameter provides the parameter passed during the callback
+ * requestion in the {@link getCallbackParameter CallbackParameter} property. The
+ * callback response content (e.g. new HTML content) must be rendered
+ * using an THtmlWriter obtained from the {@link getNewWriter NewWriter}
+ * property, which returns a NEW instance of TCallbackResponseWriter.
+ *
+ * The {@link getSelectedRowIndex SelectedRowIndex} is a zero-based index of the
+ * TActiveTableRow , -1 if the row is not part of the row collection (this shouldn't
+ * happen though since an exception is thrown before).
+ *
+ * @author LANDWEHR Computer und Software GmbH
+ * @package System.Web.UI.ActiveControls
+ * @since 3.2
+ */
+class TActiveTableRowEventParameter extends TCallbackEventParameter
+{
+ /**
+ * @var integer the zero-based index of the row.
+ */
+ private $_selectedRowIndex = -1;
+
+ /**
+ * Creates a new TActiveTableRowEventParameter.
+ */
+ public function __construct($response, $parameter, $index=-1)
+ {
+ parent::__construct($response, $parameter);
+ $this->_selectedRowIndex = $index;
+ }
+
+ /**
+ * Returns the zero-based index of the {@link TActiveTableRow} within the
+ * {@link TTableRowCollection} of the parent {@link TTable} control.
+ * @return integer the zero-based index of the row.
+ */
+ public function getSelectedRowIndex()
+ {
+ return $this->_selectedRowIndex;
+ }
+
+}
\ No newline at end of file
diff --git a/framework/Web/UI/TTemplateControlInheritable.php b/framework/Web/UI/TTemplateControlInheritable.php
new file mode 100644
index 00000000..1a62740a
--- /dev/null
+++ b/framework/Web/UI/TTemplateControlInheritable.php
@@ -0,0 +1,116 @@
+
+ * @link http://www.schlaue-kids.net/
+ * @copyright Copyright © 2010 Schlaue-Kids.net
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI
+ */
+
+Prado::using('System.Web.UI.TTemplateControl');
+
+/**
+ * TTemplateControlInheritable class.
+ * TTemplateControlInheritable is an extension to the base class for all controls that use templates.
+ * By default, a control template is assumed to be in a file under the same
+ * directory with the control class file. They have the same file name and
+ * different extension name. For template file, the extension name is ".tpl".
+ * If a TTemplateControlInheritable is inherited it uses the base class template unless the
+ * inheriting control defines an own.
+ *
+ * @author Schlaue-Kids.net
+ * @author Kyle Caine
+ * @version $Id$
+ * @package System.Web.UI
+ * @since 3.1.8
+ */
+class TTemplateControlInheritable extends TTemplateControl
+{
+ // methods
+
+ /**
+ * Creates child controls.
+ * This method is overridden to load and instantiate control template.
+ * This method should only be used by framework and control developers.
+ * Uses the controls template if available or the base class template otherwise.
+ *
+ * @return void
+ * @throws TConfigurationException if a template control directive is invalid
+ */
+ public function createChildControls()
+ {
+ if(null === ($_template = $this->getTemplate())) {
+ return $this->doCreateChildControlsFor(get_class($this));
+ }
+
+ foreach($_template->getDirective() as $_name => $_value) {
+ if(!is_string($_value)) {
+ throw new TConfigurationException('templatecontrol_directive_invalid', get_class($this), $name);
+ }
+
+ $this->setSubProperty($_name, $_value);
+ }
+
+ $_template->instantiateIn($this);
+ }
+
+ /**
+ * This method creates the cild controls for the given class
+ *
+ * @param string $parentClass The class to generate the child controls for
+ * @return void
+ */
+ public function doCreateChildControlsFor($parentClass)
+ {
+ if(false !== ($_parentClass = get_parent_class($parentClass)) && 'TTemplateControl' != $_parentClass) {
+ $this->doCreateChildControlsFor($_parentClass);
+ }
+
+ $this->doTemplateForClass($parentClass);
+ }
+
+ /**
+ * This method creates the template object for the given class
+ *
+ * @param string $p_class The class to create the template from
+ * @return void
+ * @throws TConfigurationException if a template control directive is invalid
+ */
+ public function doTemplateForClass($parentClass)
+ {
+ if(null !== ($_template = $this->getService()->getTemplateManager()->getTemplateByClassName($parentClass))) {
+ foreach($_template->getDirective() as $_name => $_value) {
+ if(!is_string($_value)) {
+ throw new TConfigurationException('templatecontrol_directive_invalid', get_class(this), $_name);
+ }
+
+ $this->setSubProperty($_name, $_value);
+ }
+
+ $_template->instantiateIn($this);
+ }
+ }
+
+ // getter/setter
+
+ /**
+ * A source template control loads its template from external storage,
+ * such as file, db, rather than from within another template.
+ *
+ * @return boolean whether the current control is a source template control
+ */
+ public function getIsSourceTemplateControl()
+ {
+ if(null !== ($_template = $this->getTemplate())) {
+ return $_template->getIsSourceTemplate();
+ }
+
+ return ($_template = $this->getService()->getTemplateManager()->getTemplateByClassName(get_parent_class($this)))
+ ? $this->_template->getIsSourceTemplate()
+ : false;
+ }
+}
\ No newline at end of file
--
cgit v1.2.3