* @copyright FancyManiaLinks Copyright © 2014 Steffen Schröder * @license http://www.gnu.org/licenses/ GNU General Public License, Version 3 */ abstract class Control implements Renderable, ScriptFeatureable { /* * Constants */ const CENTER = 'center'; const CENTER2 = 'center2'; const TOP = 'top'; const RIGHT = 'right'; const BOTTOM = 'bottom'; const LEFT = 'left'; /* * Protected properties */ protected $tagName = 'control'; protected $controlId = null; protected $posX = 0.; protected $posY = 0.; protected $posZ = 0.; protected $width = -1.; protected $height = -1.; protected $hAlign = self::CENTER; protected $vAlign = self::CENTER2; protected $scale = 1.; protected $hidden = null; protected $rotation = 0.; /** @var string[] $classes */ protected $classes = array(); /** @var ScriptFeature[] $scriptFeatures */ protected $scriptFeatures = array(); /** * Create a new Control object * * @param string $controlId (optional) Control id * @return static */ public static function create($controlId = null) { return new static($controlId); } /** * Construct a new Control object * * @param string $controlId (optional) Control id */ public function __construct($controlId = null) { if ($controlId !== null) { $this->setId($controlId); } } /** * Check Id for dangerous characters and assign a new unique id if necessary * * @param bool $forceNewId (optional) Whether to force setting a newly generated id * @return static */ public function checkId($forceNewId = false) { if ($forceNewId || !$this->getId()) { $this->setId(new UniqueID()); return $this; } $dangerousCharacters = array(' ', ' ', '.', '|', '-', PHP_EOL); $idCharacters = str_split($this->getId()); $danger = false; foreach ($idCharacters as $character) { if (!in_array($character, $dangerousCharacters)) { continue; } $danger = true; break; } if ($danger) { trigger_error("Please don't use special characters in ids, they might cause problems! (I stripped them for you.)"); $controlId = str_ireplace($dangerousCharacters, '', $this->getId()); $this->setId($controlId); } return $this; } /** * Get the Control id * * @param bool $escaped (optional) Whether the id should be escaped for ManiaScript * @param bool $addApostrophes (optional) Whether to add apostrophes before and after the text * @return string */ public function getId($escaped = false, $addApostrophes = false) { if ($escaped) { return Builder::escapeText($this->controlId, $addApostrophes); } return $this->controlId; } /** * Set Control id * * @param string $controlId Control id * @return static */ public function setId($controlId) { $this->controlId = (string)$controlId; return $this; } /** * Set Control position * * @param float $posX Horizontal position * @param float $posY Vertical position * @param float $posZ (optional) Depth * @return static */ public function setPosition($posX, $posY, $posZ = null) { $this->setX($posX); $this->setY($posY); if ($posZ !== null) { $this->setZ($posZ); } return $this; } /** * Set X position * * @param float $posX Horizontal position * @return static */ public function setX($posX) { $this->posX = (float)$posX; return $this; } /** * Set Y position * * @param float $posY Vertical position * @return static */ public function setY($posY) { $this->posY = (float)$posY; return $this; } /** * Set Z position * * @param float $posZ Depth * @return static */ public function setZ($posZ) { $this->posZ = (float)$posZ; return $this; } /** * Set Control size * * @param float $width Control width * @param float $height Control height * @return static */ public function setSize($width, $height) { $this->setWidth($width); $this->setHeight($height); return $this; } /** * Set Control width * * @param float $width Control width * @return static */ public function setWidth($width) { $this->width = (float)$width; return $this; } /** * Set Control height * * @param float $height Control height * @return static */ public function setHeight($height) { $this->height = (float)$height; return $this; } /** * Center alignment * * @return static */ public function centerAlign() { $this->setAlign(self::CENTER, self::CENTER2); return $this; } /** * Set horizontal and vertical alignment * * @param string $hAlign Horizontal alignment * @param string $vAlign Vertical alignment * @return static */ public function setAlign($hAlign, $vAlign) { $this->setHAlign($hAlign); $this->setVAlign($vAlign); return $this; } /** * Set horizontal alignment * * @param string $hAlign Horizontal alignment * @return static */ public function setHAlign($hAlign) { $this->hAlign = (string)$hAlign; return $this; } /** * Set vertical alignment * * @param string $vAlign Vertical alignment * @return static */ public function setVAlign($vAlign) { $this->vAlign = (string)$vAlign; return $this; } /** * Reset alignment * * @return static */ public function resetAlign() { $this->setAlign(null, null); return $this; } /** * Set Control scale * * @param float $scale Control scale * @return static */ public function setScale($scale) { $this->scale = (float)$scale; return $this; } /** * Set visibility * * @param bool $visible Whether the Control should be visible * @return static */ public function setVisible($visible = true) { $this->hidden = ($visible ? 0 : 1); return $this; } /** * Set Control rotation * * @param float $rotation Control rotation * @return static */ public function setRotation($rotation) { $this->rotation = (float)$rotation; return $this; } /** * Add a new class name * * @param string $class Class name * @return static */ public function addClass($class) { $class = (string)$class; if (!in_array($class, $this->classes)) { array_push($this->classes, $class); } return $this; } /** * Add a dynamic Action Trigger * * @param string $actionName Action to trigger * @param string $eventLabel (optional) Event on which the action is triggered * @return static */ public function addActionTriggerFeature($actionName, $eventLabel = ScriptLabel::MOUSECLICK) { if ($actionName instanceof ActionTrigger) { $this->addScriptFeature($actionName); } else { $actionTrigger = new ActionTrigger($actionName, $this, $eventLabel); $this->addScriptFeature($actionTrigger); } return $this; } /** * Add a new Script Feature * * @param ScriptFeature $scriptFeature Script Feature * @return static */ public function addScriptFeature(ScriptFeature $scriptFeature) { if (!in_array($scriptFeature, $this->scriptFeatures, true)) { array_push($this->scriptFeatures, $scriptFeature); } return $this; } /** * Add a dynamic Feature opening the current map info * * @param string $eventLabel (optional) Event on which the map info will be opened * @return static */ public function addMapInfoFeature($eventLabel = ScriptLabel::MOUSECLICK) { $mapInfo = new MapInfo($this, $eventLabel); $this->addScriptFeature($mapInfo); return $this; } /** * Add a dynamic Feature to open a specific player profile * * @param string $login Login of the player * @param string $eventLabel (optional) Event on which the player profile will be opened * @return static */ public function addPlayerProfileFeature($login, $eventLabel = ScriptLabel::MOUSECLICK) { $playerProfile = new PlayerProfile($login, $this, $eventLabel); $this->addScriptFeature($playerProfile); return $this; } /** * Add a dynamic Feature playing a UISound * * @param string $soundName UISound name * @param int $variant (optional) Sound variant * @param string $eventLabel (optional) Event on which the sound will be played * @return static */ public function addUISoundFeature($soundName, $variant = 0, $eventLabel = ScriptLabel::MOUSECLICK) { $uiSound = new UISound($soundName, $this, $variant, $eventLabel); $this->addScriptFeature($uiSound); return $this; } /** * Add a dynamic Feature toggling another Control * * @param Control $toggledControl Toggled Control * @param string $labelName (optional) Script label name * @param bool $onlyShow (optional) Whether it should only show the Control but not toggle * @param bool $onlyHide (optional) Whether it should only hide the Control but not toggle * @return static */ public function addToggleFeature(Control $toggledControl, $labelName = Scriptlabel::MOUSECLICK, $onlyShow = false, $onlyHide = false) { $toggle = new Toggle($this, $toggledControl, $labelName, $onlyShow, $onlyHide); $this->addScriptFeature($toggle); return $this; } /** * Add a dynamic Feature showing a Tooltip on hovering * * @param Control $tooltipControl Tooltip Control * @param bool $stayOnClick (optional) Whether the Tooltip should stay on click * @param bool $invert (optional) Whether the visibility toggling should be inverted * @return static */ public function addTooltipFeature(Control $tooltipControl, $stayOnClick = false, $invert = false) { $tooltip = new Tooltip($this, $tooltipControl, $stayOnClick, $invert); $this->addScriptFeature($tooltip); return $this; } /** * Add a dynamic Feature showing a Tooltip on hovering * * @param Label $tooltipControl Tooltip Control * @param string $text Text to display on the Tooltip Label * @param bool $stayOnClick (optional) Whether the Tooltip should stay on click * @param bool $invert (optional) Whether the visibility toggling should be inverted * @return static */ public function addTooltipLabelFeature(Label $tooltipControl, $text, $stayOnClick = false, $invert = false) { $tooltip = new Tooltip($this, $tooltipControl, $stayOnClick, $invert, $text); $this->addScriptFeature($tooltip); return $this; } /** * Add a custom Control Script text part * * @param string $scriptText Script text * @param string $label (optional) Script label name * @return static */ public function addScriptText($scriptText, $label = ScriptLabel::MOUSECLICK) { $customText = new ControlScript($this, $scriptText, $label); $this->addScriptFeature($customText); return $this; } /** * Remove all Script Features * * @return static */ public function removeScriptFeatures() { $this->scriptFeatures = array(); return $this; } /** * @see \FML\Types\ScriptFeatureable::getScriptFeatures() */ public function getScriptFeatures() { return $this->scriptFeatures; } /** * @see \FML\Types\Renderable::render() */ public function render(\DOMDocument $domDocument) { $xmlElement = $domDocument->createElement($this->tagName); if ($this->controlId) { $xmlElement->setAttribute('id', $this->controlId); } if ($this->posX || $this->posY || $this->posZ) { $xmlElement->setAttribute('posn', "{$this->posX} {$this->posY} {$this->posZ}"); } if ($this->width >= 0. || $this->height >= 0.) { $xmlElement->setAttribute('sizen', "{$this->width} {$this->height}"); } if ($this->hAlign !== self::LEFT) { $xmlElement->setAttribute('halign', $this->hAlign); } if ($this->vAlign !== self::TOP) { $xmlElement->setAttribute('valign', $this->vAlign); } if ($this->scale != 1.) { $xmlElement->setAttribute('scale', $this->scale); } if ($this->hidden) { $xmlElement->setAttribute('hidden', $this->hidden); } if ($this->rotation) { $xmlElement->setAttribute('rot', $this->rotation); } if (!empty($this->classes)) { $classes = implode(' ', $this->classes); $xmlElement->setAttribute('class', $classes); } return $xmlElement; } /** * Get the ManiaScript class of the Control * * @return string */ public abstract function getManiaScriptClass(); }