Skip to content
Snippets Groups Projects
Commit 931ce914 authored by legac's avatar legac
Browse files

Redesign the App.form.field.Dict using the Ext.form.FieldContainer.

parent 5bfcea0c
No related branches found
No related tags found
No related merge requests found
......@@ -10,12 +10,11 @@
fieldsModifier = dbui.FieldsModifier('new_fields')
fieldsModifier.configure_field('dictionary', headers=['foo', 'faa'],
modifyKeys=True,
height=150,
dictCfg={"string": "test",
"boolean": False,
"integer": 0,
"float": 0.01,
"date": "not implemented"})
value={"string": "test",
"boolean": False,
"integer": 0,
"float": 0.01,
"date": "not implemented"})
fieldsModifier.configure_field('python_code', xtype='xaceeditorfield')
......
/**
* The Dict widget is an Ext.grid.PropertyGrid which is associated
* to a JSON database field. It can be embedded in Ext.form.Panel.
*
* The form field to render the web2py database type JSON.
* The JSON object is a dictionary. It can only contains boolean,
* date, float and string objects.
*
* The default structure of the dictionary can be defined via
* the configuration option #dictCfg.
* It is possible to add / delete key value pairs.
* the configuration option #value:
* {
* "(name)": "My Object",
* "Created": new Date(Date.parse('10/15/2006')),
* "Available": false,
* "Version": .01,
* "Description": "A test object"
* }
*
* The basic syntax is also working:
* {
* foo: 1.23
* }
*
* Keys can be added / modified / deleted key when the configuration
* option #modifyKeys is true.
*
* The interface is less rich than the one of the Ext.form.field.Base.
* It contains the basic methods getValue, setValue, reset, ...
*
* @experimental
* @since 0.4.15.0
*
*/
Ext.define('App.form.field.Dict', {
extend: 'Ext.form.field.Base',
extend: 'Ext.form.FieldContainer',
mixins: {
field: 'Ext.form.field.Field'
},
alias: 'widget.xdictfield',
uses: ['Ext.grid.property.Grid', 'Ext.menu.Menu'],
/**
* @cfg {Object}
* The default configuration for the dictionary, e.g.
*
* {
* "(name)": "My Object",
* "Created": new Date(Date.parse('10/15/2006')),
* "Available": false,
* "Version": .01,
* "Description": "A test object"
* }
*
*/
dictCfg: {},
/**
* @cfg {String[]}
* The labels of the columns to be shown in the grid widget.
......@@ -52,10 +54,25 @@ Ext.define('App.form.field.Dict', {
*/
modifyKeys: false,
/**
* @event keychange
* Fire when a key is added, modified or destroyed.
*
* @param {object} this
* @param {String} action
* @param {String} oldKey
* @param {String} newKey
*/
// Predefined configuration options
layout: 'anchor',
defaults: {
anchor: '100%'
},
// private short cuts
grid: null,
menu: null,
record: null,
// private properties for internationalization
textAddMenu: 'Add',
......@@ -70,89 +87,87 @@ Ext.define('App.form.field.Dict', {
// private method requests by the component model of ExtJS
initComponent: function () {
var columns,
var me = this,
columns,
i,
headerContainer;
this.addEvents(
/**
* @event keychange
* Fire when a key is added, modified or destroyed.
*
* @param {object} this
* @param {String} action
* @param {String} oldKey
* @param {String} newKey
*/
'keychange'
);
// property grid
this.grid = Ext.create('Ext.grid.property.Grid', {
hideHeaders: this.hideHeaders,
source: Ext.apply({}, this.dictCfg)
});
headerContainer,
source = me.value || {};
// configure the property grid embedded in the container
me.items = [{
xtype: 'propertygrid',
hideHeaders: me.hideHeaders,
source: source
}];
// instantiate the base class
me.callParent(arguments);
// short cut to the grid
me.grid = me.child('propertygrid');
// dedicated column headers
if (this.headers) {
if (me.headers) {
headerContainer = this.grid.getDockedItems('headercontainer')[0];
headerContainer = me.grid.getDockedItems('headercontainer')[0];
columns = headerContainer.getGridColumns();
for (i = 0; i < columns.length; i += 1) {
columns[i].setText(this.headers[i]);
columns[i].setText(me.headers[i]);
}
}
// context menu
this.grid.on('cellcontextmenu', this.onCellContextMenu, this);
this.grid.on('containercontextmenu', this.onContainerContextMenu, this);
this.grid.on('headercontextmenu', this.onHeaderContextMenu, this);
me.grid.on('cellcontextmenu', me.onCellContextMenu, me);
me.grid.on('containercontextmenu', me.onContainerContextMenu, me);
me.grid.on('headercontextmenu', me.onHeaderContextMenu, me);
if (this.modifyKeys) {
if (me.modifyKeys) {
this.menu = Ext.create('Ext.menu.Menu', {
me.menu = Ext.create('Ext.menu.Menu', {
items: [{
text: this.textAddMenu,
text: me.textAddMenu,
iconCls: 'xaction-create',
itemId: 'add',
handler: this.onAddKey,
scope: this
handler: me.onAddKey,
scope: me
}, '-', {
text: this.textUpdateMenu,
text: me.textUpdateMenu,
iconCls: 'xaction-update',
itemId: 'update',
handler: this.onUpdateKey,
scope: this
handler: me.onUpdateKey,
scope: me
}, '-', {
text: this.textDestroyMenu,
text: me.textDestroyMenu,
iconCls: 'xaction-destroy',
itemId: 'destroy',
handler: this.onDeleteKey,
scope: this
handler: me.onDeleteKey,
scope: me
}]
});
}
// instantiate the base class
this.callParent(arguments);
// initialize the mixin Field
me.initField();
},
// private method requests by the component model of ExtJS
beforeDestroy: function () {
this.grid.un('cellcontextmenu', this.onCellContextMenu, this);
this.grid.un('containercontextmenu', this.onContainerContextMenu, this);
this.grid.un('headercontextmenu', this.onHeaderContextMenu, this);
var me = this;
Ext.destroyMembers(this, 'grid');
Ext.destroyMembers(this, 'menu');
me.grid.un('cellcontextmenu', me.onCellContextMenu, me);
me.grid.un('containercontextmenu', me.onContainerContextMenu, me);
me.grid.un('headercontextmenu', me.onHeaderContextMenu, me);
this.callParent(arguments);
Ext.destroyMembers(me, 'grid');
Ext.destroyMembers(me, 'menu');
me.callParent(arguments);
},
/**
* Return the value of this field.
* Return the value of me field.
*
* @return {Object} the content of the dictionary.
*
......@@ -160,7 +175,9 @@ Ext.define('App.form.field.Dict', {
getValue: function () {
"use strict";
return Ext.apply({}, this.grid.getSource());
var me = this;
return Ext.apply({}, me.grid.getSource());
},
/**
......@@ -170,21 +187,26 @@ Ext.define('App.form.field.Dict', {
"use strict";
var me = this,
source = me.grid.getSource();
// prompt the user to get the key name
Ext.Msg.prompt(this.textAddTitle, "", function (btn, text) {
Ext.Msg.prompt(me.textAddTitle, "", function (btn, text) {
if (btn === 'ok') {
// check that the key is unique
if (this.grid.getSource().hasOwnProperty(text)) {
Ext.Msg.alert(this.textErrorTitle, this.textErrorMsg);
if (source.hasOwnProperty(text)) {
Ext.Msg.alert(me.textErrorTitle, me.textErrorMsg);
return;
}
// add the new key
this.grid.setProperty(text, null, true);
this.fireEvent('keychange', this, 'add', undefined, text);
source[text] = null;
me.grid.setSource(source);
me.fireEvent('keychange', me, 'add', undefined, text);
}
}, this);
}, me);
},
/**
......@@ -203,15 +225,16 @@ Ext.define('App.form.field.Dict', {
onCellContextMenu: function (table, td, cellIndex, record, tr, rowIndex, event, eOpts) {
"use strict";
var me = this;
event.stopEvent();
if (this.modifyKeys && cellIndex === 0) {
this.record = record;
if (me.modifyKeys && cellIndex === 0) {
this.menu.getComponent('destroy').setDisabled(false);
this.menu.getComponent('update').setDisabled(false);
me.menu.getComponent('destroy').setDisabled(false);
me.menu.getComponent('update').setDisabled(false);
this.menu.showAt(event.getXY());
me.menu.showAt(event.getXY());
}
},
......@@ -227,13 +250,15 @@ Ext.define('App.form.field.Dict', {
onContainerContextMenu: function (view, event, eOpts) {
"use strict";
var me = this;
event.stopEvent();
if (this.modifyKeys) {
this.menu.getComponent('destroy').setDisabled(true);
this.menu.getComponent('update').setDisabled(true);
if (me.modifyKeys) {
me.menu.getComponent('destroy').setDisabled(true);
me.menu.getComponent('update').setDisabled(true);
this.menu.showAt(event.getXY());
me.menu.showAt(event.getXY());
}
},
......@@ -244,14 +269,16 @@ Ext.define('App.form.field.Dict', {
"use strict";
var prop = this.record.get("name");
var me = this,
record = me.grid.getSelectionModel().getSelection()[0],
prop = record.get("name");
Ext.Msg.confirm(this.textDestroyTitle, prop, function (btn) {
Ext.Msg.confirm(me.textDestroyTitle, prop, function (btn) {
if (btn === "yes") {
this.grid.removeProperty(prop);
this.fireEvent('keychange', this, 'destroy', prop, undefined);
me.grid.removeProperty(prop);
me.fireEvent('keychange', me, 'destroy', prop, undefined);
}
}, this);
}, me);
},
/**
......@@ -266,39 +293,17 @@ Ext.define('App.form.field.Dict', {
onHeaderContextMenu: function (headerContainer, column, event, html, eOpts) {
"use strict";
event.stopEvent();
},
/**
* Render the widget.
*
* @param {Ext.Element} ct The container to render to.
* @param {Object} position The position in the container to render to.
*
*/
onRender: function (ct, position) {
this.callParent(arguments);
// wrap an element around the input field
this.resizeEl = this.positionEl = this.wrap = this.bodyEl.wrap();
this.grid.render(this.wrap);
var me = this,
source = me.grid.getSource(),
isSourceEmpty = Object.keys(source).length === 0;
// hide the default input field
this.bodyEl.setVisibilityMode(Ext.dom.Element.DISPLAY).hide();
},
/**
* Resize the component
*
* @param {Number} w
* @param {Number} h
*
*/
onResize: function (w, h) {
event.stopEvent();
this.grid.setSize(w - this.getLabelWidth(), h);
this.callParent(arguments);
// allow to add key if source is not defined
if (me.modifyKeys && isSourceEmpty && column.getItemId() === 'name') {
me.onAddKey();
}
},
/**
......@@ -308,25 +313,30 @@ Ext.define('App.form.field.Dict', {
"use strict";
var key = this.record.get("name"),
value = this.record.get("value");
var me = this,
record = me.grid.getSelectionModel().getSelection()[0],
key = record.get("name"),
value = record.get("value"),
source = me.grid.getSource();
// prompt the user to modify the key
Ext.Msg.prompt(this.textUpdateTitle, "", function (btn, text) {
Ext.Msg.prompt(me.textUpdateTitle, "", function (btn, text) {
if (btn === 'ok') {
// check that the key is unique
if (this.grid.getSource().hasOwnProperty(text)) {
Ext.Msg.alert(this.textErrorTitle, this.textErrorMsg);
if (source.hasOwnProperty(text)) {
Ext.Msg.alert(me.textErrorTitle, me.textErrorMsg);
return;
}
// update the key
this.grid.removeProperty(key);
this.grid.setProperty(text, value, true);
this.fireEvent('keychange', this, 'update', key, text);
delete source[key];
source[text] = value;
me.grid.setSource(source);
me.fireEvent('keychange', me, 'update', key, text);
}
}, this, false, key);
}, me, false, key);
},
......@@ -340,9 +350,15 @@ Ext.define('App.form.field.Dict', {
*/
setValue: function (value) {
var source = value || this.dictCfg;
this.grid.setSource(source);
"use strict";
var me = this,
source = value || me.originalValue;
me.grid.setSource(source);
return this.callParent([source]);
// the standard way to set the value for a field
// extract from Ext.form.field.Base
return me.mixins.field.setValue.call(me, source);
}
});
\ No newline at end of file
});
......@@ -47,7 +47,7 @@ Ext.onReady(function(){
listeners: {
keychange: {
fn: function (cmp, action, oldKey, newKey) {
Ext.Msg.alert('Event', action + ' ' + oldKey + ' ' + newKey);
Ext.Msg.alert('Catch event with arguments:', action + ', ' + oldKey + ', ' + newKey);
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment