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

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

Все компоненты, используемые в дизайнере описаны в файле 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’)