.. _components:

================================================
Добавление и измененение компонентов в дизайнере
================================================

Описание доступных типов и свойств компонентов
==============================================

Все компоненты, используемые в дизайнере описаны в файле model-types-config.js. Внутри него находится объект
typesConfig, полями которого являются доступные типы. Рассмотрим на примере ExtFormPanel::
    
    formPanel: {
            parent:'panel',
            isContainer:true,
            properties : {
                id : {
                    defaultValue:'frm_formpanel',
                    isInitProperty:true,
                    isQuickEditable: true
                },
                layout: {
                    defaultValue:'form',
                    isInitProperty:true,
                    isQuickEditable: true
                },
                title: {
                    defaultValue:'',
                    isInitProperty:true,
                    isQuickEditable: true
                },
                url: {
                    defaultValue:''
                },
                fileUpload:{
                    defaultValue:false
                },
                urlShortName:{
                    defaultValue:'',
                    isQuickEditable:true
                }
            },
            childTypesRestrictions:{
                disallowed:['arrayStore','gridColumn','jsonStore','pagingToolbar']
            },
            toolboxData: {
                category:'Containers',
                text:'Form panel'
            },
            treeIconCls:'designer-formpanel'
        }

        
*parent:'panel'*  - Ссылка на тип, который является предком текущего типа. Типы компонентов наследуют 
свойства друг друга(под свойствами в данном контексте подразумеваются объекты в properties, ограничения и другие объекты первого
уровня вложенности не наследуются) Раз formPanel является наследником Panel она получит свойства layout, region, height, width и тд

*isContainer:true* - В случае если поле указано и равно true, то в компонент можно добавлять дочерние компоненты. Нужно отметить что
под добавление дочерних в данном случае подразумевается чисто абстрактное условие, регламентирующее возможность иметь дочерние компоненты во внутренней структуре данных используемых дизайнером,
и никак не связана напрямую с объектной моделью ExtJs. Так ComboBox имеет isContainer:true тк в него можно добавить подчиненный DataStore.
 
*properties: {}* - Вложенные свойства это те поля что доступны для редактирования пользователю.

*defaultValue:'form'* - обязательное поле для каждого свойства типа. По типу(javascript типу) определеяется редактор. К примеру height и width у контенейров обязан быть числом,
и поэтому defaultValue:0 и редактироваться будет NumberField'ом.

*isInitProperty:true* - Необязательное поле. Если установлено то при создании нового экземпляра поле будет проинициализировано. Типичный пример тайтлы у всего что можно

*isQuickEditable:true* - Необязательное поле. True - свойство появиться в редакторе быстрых свойств

*propertyType:'enum'* - Необязательное поле. Если не указано, то Javascript тип свойства будет определен по значению defaultValue. В данный момент обрабатываюются
значения 'enum' и 'object' Значения перечисления обрабатываютcя в файле property-editor.js Для значения 'object' - вводимый пользователем текст будет про'eval'ен, это
нужно для вложенных объектов. Значения перечислений прописываются в model-types.js

*isNotEditable:true* - Необязательное поле. Используется когда нужно проинизализировать что-то в экземпляре объекта, но не давать пользователю рукам это что-то перебить. Пример TabPanel,
дабы не унаследовать от Panel значение layout по умолчанию 'auto'

*childTypesRestrictions* - Ограничения для подчиненных объектов. Состоит из трех массивов со строковыми названиями типов. allowed - то что можно добавлять, disallowed - то что нельзя, single - одиночные типы
Каждый из массивов может отсутствовать, в таком случае условие игнорируется при проверке. К примеру disallowed:undefined, allowed:['panel'], single:['panel'] - к текущему компоненту можно добавить ровно одну панель

*toolboxData* - Информация для панели инструментов. Может отсутствовать

*treeIconCls* - Очевидно иконка типа компонента. Необязательное поле


Визуальное отображение компонентов
==================================

Код рисующий штуки на экране уютно расположился в файле ui.js Для рисования использовался хитрый паттерн "Посетитель" Для рисования нужно добавить новую функцию
объекту mapObject, имя которой совпадало бы с названием типа определенного в файле конфигов. Если функция не определена - ничего не случится. Просто компонент не нарисуется::
    comboBox:function(model, cfg) {
        var store = undefined;
        //попробуем найти стор
        for (var i = 0; i < model.childNodes.length; i++) {
            if (model.childNodes[i].attributes.type == 'arrayStore') {
                store = new Ext.data.ArrayStore(
                            Ext.apply({
                                fields:['id',model.attributes.properties.displayField]
                            },model.childNodes[i].attributes.properties)
                        );
            }
        }
        //или создадим пустой
        if (!store) {
            store = new Ext.data.Store({
                autoDestroy:true
            });
        }
        return Ext.apply( cfg , {
                    store:store,
                    mode:'local',
                    xtype:'combo'
                });
    }
        
В аргументе model передается объект внутренней модели дизайнера, через него можно получить доступ к родительскому компоненту или к дочерним. cfg - готовый объект конфига со свойствами
отредактированными пользователем. Для простых случаев, например, textField достаточно в объект конфига добавить xtype для того чтобы экст корректно создал визуальный компонент. Можно не использовать xtype,
и создавать инстансы классов. В примере выше рассамтривается создание комбобокса. Чаще всего для дизайна нам не требуется сложное поведение компонентов, и поэтому можно создать ограниченую болванку, которой достаточно
чтобы послужить отражением более сложного компонента(или закрыть от активации какое то поведение, как правило обмен данными с севрером)


Сериализация/десериализация
===========================

Код находиться в файле transfer.js В подавляющих случаях туда не нужно ничего добавлять. Но иногда, когда у компонентов есть компоненты не принадлежащие items, приходится добавлять
всячески исключения. Пример тому свойство store, или массив columns у грида. Смотреть нужно на объект childPropertyObjects. В массивы добавляются свойства для особенной десериализации, в функции типы требующие
сериалзиации как-то поособенному.



Серверный маппинг
=================

Для того, чтобы код успешно серриализовался в python код и обратно нужно добавлять компоненты в серверный маппинг.

Серверный маппинг находится в файле m3_designer/ide/mapping.json. Рассматорим пример маппинга::
    {
        "class": {
            "objectGrid": "ExtObjectGrid"
        },
        "config": {
            "urlNew":"url_new"
            ,"urlEdit":"url_edit"
            ,"urlDelete":"url_delete"
            ,"urlData":"url_data"
            ,"rowIdName":"row_id_name"
            ,"columnParamName":"column_param_name"
            ,"allowPaging":"allow_paging"
            ,"localEdit": "local_edit"

            ,"urlDataShortName": {
                "type":"shortname"
                ,"value":"url_data"
            }
            ,"urlEditShortName": {
                "type":"shortname"
                ,"value":"url_edit"
            }
            ,"urlDeleteShortName":{
                "type":"shortname"
                ,"value":"url_delete"
            }
            ,"urlNewShortName":{
                "type":"shortname"
                ,"value":"url_new"
            }
        }
        ,"parent": "gridPanel"
    }

Объект class говорит о том, что клиентский класс *objectGrid* будет маппиться в серверный класс *ExtObjectGrid*.
Конфиг объектов данного класса так же маппится из клиенского кода *urlNew* в серверный код *url_new* и наоборот.
Могут быть сложные свойтсва, такие свойства помечаются свойством "type", например объект "shortname", имеющий свойство
"create" будет отображен в серверный поиска шортнейма - *instanse.attr = urls.get_url('create')*