.. _ext_composer:

ExtComposer
==============

Это :ref:`внешний компонент<ext_component>`, предназначенный для размещением :term:`фреймов<Фрейм>`, связанных отношением мастер-деталь.
Клиентский код компоновщика должен создавать HTML-элементы для каждого детального фрейма, которые идентифицируются по
авто-формируемому ключу ``key``.

.. seealso::

    1. Метаданные :xsd:class:`ExtComposer<View.Representation.Layout.ExtComposer>`
    2. Core-интерфейс :java:type:`CoreExtComposer<ru.bitec.gtk.core.gl.ext.composer.CoreExtComposer>`
    3. JS-api :java:type:`ExtComposer<ru.bitec.presenter.model.ui.ext.composer.api.ExtComposer>`

.. _ext_composer_backend_template:

.. code-block:: scala
  :caption: Шаблон серверного кода внешнего компоновщика

    class Gs3_ExtComposerExampleAbi extends ExtComposerAbi {

    }


.. _ext_composer_frontend_template:

.. code-block:: js
  :caption: Шаблон клиентского кода внешнего компоновщика
  :linenos:

  class MyComposer {
      constructor(name) {
          this.name = name;
          this.isAttached = false;
      }

      init(extContext) {
          this.extContext = extContext;
          this.unsubscribeNodeChanges = this.extContext.extController.subscribeNodeChanges({
              onSubscribe(rootNode) {},
              beforeVisitModel() {},
              beforeVisitNode(pNode) {},
              beforeAddToParent(pNode, parentNode) {},
              afterLoadNode(pNode) {},
              afterVisitNode(pNode) {},
              beforeCleanNode(pNode, parentNode) {},
              afterVisitModel() {},
              beforeConsignmentVersionChange() {},
              afterConsignmentVersionChange() {}
          });
      }

      destroy() {
          this.unsubscribeNodeChanges();
          this.extContext = null;
      }

      attach(parent) {
          this.composerParent = parent;
          // Здесь создаём в `composerParent` необходимые HTML-элементы.
          this.isAttached = true;
      }

      detach() {
          this.isAttached = false;
          while (this.composerParent.lastChild) this.composerParent.removeChild(this.composerParent.lastChild);
          this.composerParent = null;
      }

      beforeChildrenChange() {
      }

      addChild(key, docker) {
      }

      removeChild(key) {
      }

      afterChildrenChange() {
      }

      doLayout() {
      }
  }

.. code-block:: xml
  :caption: Пример кода :term:`Avm`
  :linenos:

    <representation name="ExtComposer">
        <layout>
            <extComposer
                    name="gs3/ExtComposerExample"
                    backendClass="ru.bitec.app.gs3.test.extctrl.Gs3_ExtComposerExampleAbi"
                    frontendUri="gs3/extctrl/composer.js">
                <frame>
                    <grid/>
                </frame>
            </extComposer>
        </layout>
    </representation>

Список детальных выборок
--------------------------------------

Возможны статическое и динамическое определение списка детальных выборок.

Статический список
```````````````````````````````````````

В :term:`Avm` файле определяется перечень детальных выборок.

.. code-block:: xml
  :caption: Статическое определение списка детальных выборок
  :linenos:

    <representation name="ExtComposerStaticItems" editMode="edit" caption="Тест ExtComposer'a">
        <layout>
            <extComposer
                    name="gs3/ExtComposerExample"
                    backendClass="ru.bitec.app.gs3.test.extctrl.Gs3_ExtComposerExampleAbi"
                    frontendUri="ru/bitec/app/gs3/test/extctrl/web/composer.js">
                <frame>
                    <grid/>
                </frame>
                <details>
                    <detail selection="gtk-Gs3_ExtControlExampleAvi" representation="ExtControl" name="item-1"/>
                    <detail selection="gtk-ru.bitec.app.btk.Btk_NotificationAvi" representation="Head" name="item-2"/>
                </details>
            </extComposer>
        </layout>
    </representation>

Динамический список
```````````````````````````````````````

В :term:`Avm` файле указываются имя и отображение выборки, которая содержит записи с именами детальных выборок.

.. code-block:: xml
  :caption: Динамическое определение списка детальных выборок
  :linenos:

    <representation name="ExtComposerSelectionItems" editMode="edit" caption="Тест ExtComposer'a">
        <layout>
            <extComposer
                    name="gs3/ExtComposerExample"
                    backendClass="ru.bitec.app.gs3.test.extctrl.Gs3_ExtComposerExampleAbi"
                    frontendUri="ru/bitec/app/gs3/test/extctrl/web/composer.js">
                <frame>
                    <grid/>
                </frame>
                <details selection="gtk-Gs3_ExtControlExample" representation="ExtItemSource"/>
            </extComposer>
        </layout>
    </representation>


.. code-block:: scala
  :caption: Пример отображения выборки со списком деталей
  :linenos:

    trait ExtItemSource extends Default {
      override protected def onRefresh: Recs = {
          List(
            ExtItemRec(1, "item-1", "gtk-Gs3_ExtControlExample", "ExtControl", 1, ""),
            ExtItemRec(2, "item-2", "gtk-ru.bitec.app.btk.Btk_Notification", "Head", 1, ""),
          )
      }
    }

    case class ExtItemRec(
                           var ID: Int,
                           var SNAME: String,
                           var SSELECTIONNAME: String,
                           var SREPRESENTATIONNAME: String,
                           var NVISIBLE: Int,
                           var JSONPARAMS: String,
                         )