00001 <?php
00002
00015 abstract class TKContainer extends TKComponent {
00018 protected $children = array('main' => array());
00021 protected $slotInfo = array('main' => array());
00024 protected $childParams = array('main' => array());
00027 protected $defaultSlot = 'main';
00030 protected $defaultSlotOptions;
00031
00033 const SLOT_ACCESS_PUBLIC = 0;
00035 const SLOT_ACCESS_PRIVATE = 1;
00036
00038 const SLOT_SIZE_SINGLE = 0;
00040 const SLOT_SIZE_MULTI = 1;
00041
00043 public static $ENABLE_ADD_CHECKS = false;
00044
00045 public function __construct() {
00046 parent::__construct();
00047
00048 $this->defaultSlotOptions = array(
00049 'access' => self::SLOT_ACCESS_PUBLIC,
00050 'type' => 'TKComponent',
00051 'size' => self::SLOT_SIZE_MULTI
00052 );
00053
00054 $this->slotInfo = array('main' => $this->defaultSlotOptions);
00055 }
00056
00057 public function __call($name, $args) {
00058 if(substr($name, 0, 3) != "add")
00059 return parent::__call($name, $args);
00060
00061 if(substr($name, -2) == "To") {
00062
00063
00064 $className1 = "TK" . substr($name, 3, -2);
00065 $className2 = "TK" . substr($name, 3);
00066 if(!class_exists($className1)) {
00067 if(!class_exists($className2)) {
00068 $this->setError("Invalid component type specified: "
00069 . "'$className1' or '$className2'");
00070 return null;
00071 }
00072 $className = $className2;
00073 $withSlot = false;
00074 }
00075 else {
00076 $className = $className1;
00077 $withSlot = true;
00078 }
00079
00080 }
00081 else {
00082 $withSlot = false;
00083 $className = substr($name, 3);
00084 $className = "TK$className";
00085 if(!class_exists($className)) {
00086 $this->setError("Invalid component type specified: '$className'");
00087 return null;
00088 }
00089 }
00090
00091 if($withSlot) {
00092 $slot = $args[0];
00093 $start = 1;
00094 }
00095 else {
00096 $slot = "";
00097 $start = 0;
00098 }
00099
00100 if(count($args) > 0 && is_array($args[count($args) - 1])) {
00101 $params = $args[count($args) - 1];
00102 $oneLess = true;
00103 }
00104 else
00105 $params = array();
00106
00107 $paramStr = '';
00108 for($i = $start; $i < count($args) - isset($oneLess) ? 1 : 0; $i++) {
00109 $paramStr .= '$args['.$i.'],';
00110 }
00111 $paramStr = rtrim($paramStr, ',');
00112
00113 $obj = eval("return new $className($paramStr);");
00114
00115 return $this->add($obj, $slot, $params);
00116 }
00117
00118
00119 public function addLabel($txt, $params = array()) {
00120 return $this->add(new TKLabel($txt), "", $params);
00121 }
00122
00123 public function addLabelTo($slot, $txt, $params = array()) {
00124 return $this->add(new TKLabel($txt), $slot, $params);
00125 }
00126
00127 public function addButton($caption, $params = array()) {
00128 return $this->add(new TKButton($caption), "", $params);
00129 }
00130
00131 public function addSelect($name, $multiple = false, $params = array()) {
00132 return $this->add(new TKSelect($name, $multiple), "", $params);
00133 }
00134
00135 public function addFormInput($type, $name, $value = "", $params = array()) {
00136 return $this->add(new TKFormInput($type, $name, $value), "", $params);
00137 }
00138
00139
00140
00141 public function __clone() {
00142 foreach($this->children as $s) {
00143 foreach($this->children[$s] as $c)
00144 $this->children[$s][$c] = clone $this->children[$s][$c];
00145 }
00146 }
00147
00170 public function add($component, $slot = "", $params = array()) {
00171 if(is_array($slot)) {
00172 $params = $slot;
00173 $slot = "";
00174 }
00175 if(!is_string($slot))
00176 $this->setError("Slot must be a string!");
00177 if($slot == "" || !is_string($slot))
00178 $slot = $this->defaultSlot;
00179 if(!is_object($component)) {
00180 $this->setError("Component must not be null or a non-object!");
00181 return null;
00182 }
00183
00184 if(self::$ENABLE_ADD_CHECKS) {
00185 if($this->getSlotOption($slot, 'access') != self::SLOT_ACCESS_PUBLIC) {
00186 $this->setError("Cannot add item to slot '$slot' because it is "
00187 . "private");
00188 return null;
00189 }
00190 $type = $this->getSlotOption($slot, 'type');
00191 if($type != "" && !is_a($component, $type)) {
00192 $this->setError("Cannot add item to slot '$slot' because item is of"
00193 . " incorrect type");
00194 return null;
00195 }
00196 if($this->getSlotOption($slot, 'size') == self::SLOT_SIZE_SINGLE
00197 && count($this->children[$slot]) != 0) {
00198 $this->setError("Cannot add item to slot '$slot' because it is "
00199 . "full");
00200 return null;
00201 }
00202 }
00203 if(!$this->onAdd($component, $slot, $params, $component->getId())) {
00204 return null;
00205 }
00206 $this->children[$slot][$component->getId()] = $component;
00207 $this->childParams[$slot][$component->getId()] = $params;
00208 return $component;
00209 }
00210
00222 public function addText($txt, $params = array()) {
00223
00224 if(!is_string($txt) && !ctype_digit((string) $txt))
00225 $txt = "";
00226 $slot = $this->defaultSlot;
00227 if(!$this->onAdd($txt, $slot, $params, count($this->children)))
00228 return false;
00229 array_push($this->children[$this->defaultSlot], $txt);
00230 array_push($this->childParams[$this->defaultSlot], $params);
00231 return true;
00232 }
00233
00246 public function addTextTo($slot, $txt, $params = array()) {
00247 if(!is_string($txt))
00248 $txt = "";
00249 if(!$this->onAdd($txt, $slot, $params, count($this->children)))
00250 return false;
00251 array_push($this->children[$slot], $txt);
00252 array_push($this->childParams[$slot], $params);
00253 return true;
00254 }
00255
00256
00257
00258
00259
00260 protected function updateIds() {
00261 foreach($this->children as $s => $children) {
00262 foreach($children as $id => $obj) {
00263 $newId = $obj->getId();
00264 if($newId != $id) {
00265 unset($this->children[$s][$id]);
00266 $this->children[$s][$newId] = $obj;
00267 }
00268 }
00269 }
00270 }
00271
00290 protected function addSlot($slotName, $options = array()) {
00291 if(isset($this->children[$slotName]))
00292 $this->setWarning("Slot '$slotName' already exists; existing"
00293 . " members will be destroyed.");
00294 $this->children[$slotName] = array();
00295 $this->childParams[$slotName] = array();
00296 $this->slotInfo[$slotName] = array_merge($this->defaultSlotOptions, $options);
00297 return true;
00298 }
00299
00310 protected function removeSlot($slotName) {
00311 if(count($this->children[$slotName]) != 0)
00312 $this->setWarning("Remove non-empty slot '$slotName'");
00313 unset($this->children[$slotName]);
00314 unset($this->childParams[$slotName]);
00315 unset($this->slotInfo[$slotName]);
00316 return true;
00317 }
00318
00330 protected function getSlotOption($slot, $option) {
00331 if(!isset($this->children[$slot])) {
00332 $this->setError("Invalid slot '$slot' (DEVELOPER ERROR!)");
00333
00334 return $this->defaultSlotOptions[$option];
00335 }
00336
00337 if(!isset($this->slotInfo[$slot][$option])) {
00338 return $this->defaultSlotOptions[$option];
00339 }
00340 else {
00341 return $this->slotInfo[$slot][$option];
00342 }
00343 return $this->slotInfo[$slot][$option];
00344 }
00345
00355 protected function setSlotOption($slot, $option, $value) {
00356 if(!isset($this->slotInfo[$slot])) {
00357 $this->setError("Invalid slot '$slot' (DEVELOPER ERROR!)");
00358 return false;
00359 }
00360 $this->slotInfo[$slot][$option] = $value;
00361 return true;
00362 }
00363
00373 protected function setDefaultSlot($slot) {
00374 $this->defaultSlot = $slot;
00375 }
00376
00388 protected function addPriv($component, $slot, $params = array()) {
00389 if(!is_a($component, $this->getSlotOption($slot, 'type'))) {
00390 $this->setError("Cannot add item to slot '$slot' because item is of"
00391 . " incorrect type");
00392 return null;
00393 }
00394 if(count($this->children[$slot]) != 0
00395 && $this->getSlotOption($slot, 'size') == self::SLOT_SIZE_SINGLE) {
00396 $this->setError("Cannot add item to slot '$slot' because it is "
00397 . "full");
00398 return null;
00399 }
00400 $this->children[$slot][$component->getId()] = $component;
00401 $this->childParams[$slot][$component->getId()] = $params;
00402 return $component;
00403 }
00404
00412 protected function getChildrenBySlot($slotName) {
00413 return $this->children[$slotName];
00414 }
00415
00424 protected function getChild($slot, $id) {
00425 return $this->children[$slot][$id];
00426 }
00427
00436 protected function getChildParams($slot, $child) {
00437 if(!is_object($child))
00438 return $this->childParams[$slot][$child];
00439 else
00440 return $this->childParams[$slot][$child->getId()];
00441 }
00442
00455 protected function setChildParams($slot, $child, $params) {
00456 if(!is_object($child))
00457 $this->childParams[$slot][$child] = $params;
00458 else
00459 $this->childParams[$slot][$child->getId()] = $params;
00460 }
00461
00473 protected function addToChildParams($slot, $child, $params) {
00474 if(!is_object($child))
00475 $this->childParams[$slot][$child] += $params;
00476 else
00477 $this->childParams[$slot][$child->getId()] += $params;
00478 }
00479
00480
00481
00482
00483
00484
00485 protected function renderComponent($class, $style, $events, $id) {
00486 return $this->renderContainer($class, $style, $events, $id);
00487 }
00488
00501 abstract protected function renderContainer($class, $style, $events, $id);
00502
00519 protected function onAdd(&$component, &$slot, &$params, $id) {
00520 return true;
00521 }
00522
00534 protected static function convertStdChildren($obj, $children) {
00535 foreach($children as $child) {
00536 if(substr($child['tag'], 0, 2) == 'TK') {
00537 $nobj = self::convertChild($child);
00538 if($nobj !== null)
00539 $obj->add($nobj);
00540 }
00541 }
00542 }
00543 }
00544
00545 ?>