diff --git a/src/IPub/Widgets/Components/Control.php b/src/IPub/Widgets/Components/Control.php index 3e84502..670ed1b 100644 --- a/src/IPub/Widgets/Components/Control.php +++ b/src/IPub/Widgets/Components/Control.php @@ -28,6 +28,7 @@ use IPub\Widgets\Exceptions; use IPub\Widgets\Managers; use IPub\Widgets\Widgets; +use Tracy\Debugger; /** * Widgets container control definition @@ -135,6 +136,13 @@ protected function attached($presenter) */ public function render() { + foreach (func_get_args() as $arg) { + // Check if decorator name is provided + if (is_string($arg)) { + $this->setDecorator($arg); + } + } + // Check if control has template if ($this->template instanceof Nette\Bridges\ApplicationLatte\Template) { // Assign vars to template @@ -174,6 +182,12 @@ public function setDecorator(string $decorator) { // Try to find decorator factory if ($factory = $this->decoratorsManager->get($decorator)) { + // Check if some decorator is registered... + if ($component = $this->getComponent('decorator', FALSE)) { + // ... if yes, remove it + $this->removeComponent($component); + } + // Register decorator component $this->addComponent($factory->create(), 'decorator'); diff --git a/src/IPub/Widgets/DI/WidgetsExtension.php b/src/IPub/Widgets/DI/WidgetsExtension.php index 7edb0a1..cca66cc 100644 --- a/src/IPub/Widgets/DI/WidgetsExtension.php +++ b/src/IPub/Widgets/DI/WidgetsExtension.php @@ -186,6 +186,10 @@ public function beforeCompile() } } } + + // Install extension latte macros + $latteFactory = $builder->getDefinition($builder->getByType(Nette\Bridges\ApplicationLatte\ILatteFactory::class) ?: 'nette.latteFactory'); + $latteFactory->addSetup('IPub\Widgets\Latte\Macros::install(?->getCompiler())', ['@self']); } /** diff --git a/src/IPub/Widgets/Latte/Macros.php b/src/IPub/Widgets/Latte/Macros.php new file mode 100644 index 0000000..bad134d --- /dev/null +++ b/src/IPub/Widgets/Latte/Macros.php @@ -0,0 +1,98 @@ + + */ +final class Macros extends Bridges\ApplicationLatte\UIMacros +{ + /** + * @param Compiler $compiler + * + * @return void + */ + public static function install(Compiler $compiler) + { + $me = new static($compiler); + + /** + * {widget positionName} + */ + $me->addMacro('widgets', [$me, 'macroWidgets']); + } + + /** + * @param MacroNode $node + * @param PhpWriter $writer + * + * @return string + * + * @throws Latte\CompileException + */ + public static function macroWidgets(MacroNode $node, PhpWriter $writer) : string + { + $words = $node->tokenizer->fetchWords(); + if (!$words) { + throw new Latte\CompileException('Missing widgets position name in {widgets}'); + } + $name = $writer->formatWord($words[0]); + $method = isset($words[1]) ? ucfirst($words[1]) : ''; + $method = Utils\Strings::match($method, '#^\w*\z#') ? "render$method" : "{\"render$method\"}"; + + $tokens = $node->tokenizer; + $pos = $tokens->position; + $param = $writer->formatArray(); + $tokens->position = $pos; + while ($tokens->nextToken()) { + if ($tokens->isCurrent('=>') && !$tokens->depth) { + $wrap = TRUE; + break; + } + } + if (empty($wrap)) { + $param = substr($param, 1, -1); // removes array() or [] + } + $prefix = ''; + if (is_string($name) && strpos($name, '-') === FALSE) { + $prefix = '"widgets-" .'; + } + return "/* line $node->startLine */ " + . ($name[0] === '$' ? "if (is_object($name)) \$_tmp = $name; else " : '') + . '$_tmp = $this->global->uiControl->getComponent('. $prefix . $name . '); ' + . 'if ($_tmp instanceof Nette\Application\UI\IRenderable) $_tmp->redrawControl(NULL, FALSE); ' + . ($node->modifiers === '' + ? "\$_tmp->$method($param);" + : $writer->write("ob_start(function () {}); \$_tmp->$method($param); echo %modify(ob_get_clean());") + ); + } +} diff --git a/src/IPub/Widgets/Widgets/Widget.php b/src/IPub/Widgets/Widgets/Widget.php index ad1ed6b..ea7e062 100644 --- a/src/IPub/Widgets/Widgets/Widget.php +++ b/src/IPub/Widgets/Widgets/Widget.php @@ -27,6 +27,7 @@ use IPub\Widgets\Decorators; use IPub\Widgets\Entities; use IPub\Widgets\Exceptions; +use Tracy\Debugger; /** * Widgets control definition @@ -172,8 +173,14 @@ protected function beforeRender() $this->template->setTranslator($this->getTranslator()); } + $templateFile = $this->getTemplate()->getFile(); + + if (is_callable($templateFile)) { + $templateFile = call_user_func($templateFile); + } + // If template was not defined before... - if ($this->template->getFile() === NULL) { + if ($templateFile === NULL) { // Get component actual dir $dir = dirname($this->getReflection()->getFileName());