TrackManiaControl/libs/FML/Script/Features/Menu.php
2017-03-25 18:40:15 +01:00

184 lines
5.1 KiB
PHP

<?php
namespace FML\Script\Features;
use FML\Controls\Control;
use FML\Script\Builder;
use FML\Script\Script;
use FML\Script\ScriptLabel;
/**
* Script Feature realising a Menu showing specific Controls for the different items
*
* @author steeffeen
* @copyright FancyManiaLinks Copyright © 2017 Steffen Schröder
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
*/
class Menu extends ScriptFeature
{
/*
* Constants
*/
const FUNCTION_UPDATE_MENU = "FML_UpdateMenu";
/**
* @var MenuElement[] $elements Menu Elements
*/
protected $elements = array();
/**
* @var MenuElement $startElement Start Element
*/
protected $startElement = null;
/**
* Construct a new Menu
*
* @api
* @param Control $item (optional) Item Control in the Menu bar
* @param Control $control (optional) Toggled Menu Control
* @param bool $isStartElement (optional) Whether the Menu should start with the given Element
*/
public function __construct(Control $item = null, Control $control = null, $isStartElement = true)
{
if ($item && $control) {
$this->addItem($item, $control, $isStartElement);
}
}
/**
* Get the Menu Elements
*
* @api
* @return MenuElement[]
*/
public function getElements()
{
return $this->elements;
}
/**
* Add a Menu item
*
* @api
* @param Control $item Item Control in the Menu bar
* @param Control $control Toggled Menu Control
* @param bool $isStartElement (optional) Whether the Menu should start with this Element
* @return static
*/
public function addItem(Control $item, Control $control, $isStartElement = false)
{
$menuElement = new MenuElement($item, $control);
$this->addElement($menuElement, $isStartElement);
return $this;
}
/**
* Add a Menu Element
*
* @api
* @param MenuElement $menuElement Menu Element
* @param bool $isStartElement (optional) Whether the Menu should start with this Element
* @return static
*/
public function addElement(MenuElement $menuElement, $isStartElement = false)
{
if (!in_array($menuElement, $this->elements, true)) {
array_push($this->elements, $menuElement);
if ($isStartElement) {
// new start element
$this->setStartElement($menuElement);
} else {
// additional element - set invisible
$menuElement->getControl()
->setVisible(false);
}
}
return $this;
}
/**
* Get the Element to start with
*
* @api
* @return MenuElement
*/
public function getStartElement()
{
return $this->startElement;
}
/**
* Set the Element to start with
*
* @api
* @param MenuElement $startElement Start Element
* @return static
*/
public function setStartElement(MenuElement $startElement = null)
{
$this->startElement = $startElement;
if ($startElement && !in_array($startElement, $this->elements, true)) {
array_push($this->elements, $startElement);
}
return $this;
}
/**
* @see ScriptFeature::prepare()
*/
public function prepare(Script $script)
{
$updateFunctionName = self::FUNCTION_UPDATE_MENU;
$elementsArrayText = $this->getElementsArrayText();
// OnInit
if ($this->startElement) {
$startControlId = Builder::escapeText($this->startElement->getControl()->getId());
$initScriptText = "
{$updateFunctionName}({$elementsArrayText}, {$startControlId});";
$script->appendGenericScriptLabel(ScriptLabel::ONINIT, $initScriptText, true);
}
// MouseClick
$scriptText = "
declare MenuElements = {$elementsArrayText};
if (MenuElements.existskey(Event.Control.ControlId)) {
declare ShownControlId = MenuElements[Event.Control.ControlId];
{$updateFunctionName}(MenuElements, ShownControlId);
}";
$script->appendGenericScriptLabel(ScriptLabel::MOUSECLICK, $scriptText, true);
// Update menu function
$updateFunctionText = "
Void {$updateFunctionName}(Text[Text] _Elements, Text _ShownControlId) {
foreach (ItemId => ControlId in _Elements) {
declare Control <=> (Page.GetFirstChild(ControlId));
Control.Visible = (ControlId == _ShownControlId);
}
}";
$script->addScriptFunction($updateFunctionName, $updateFunctionText);
return $this;
}
/**
* Build the array text for the Elements
*
* @return string
*/
protected function getElementsArrayText()
{
$elements = array();
foreach ($this->elements as $element) {
$elementId = $element->getItem()
->getId();
$elements[$elementId] = $element->getControl()
->getId();
}
return Builder::getArray($elements, true);
}
}