<@interface name="KitEditors" alias="$ENV"> Extension point for defining kit editors (c) SAP AG 2003-2006. All rights reserved. + # For complete description of editor definition see @env:KitEditors!EDITOR_DEF ? * # Represents a property of the editor You can assign the 'type' attribute for evaluating the value of the property as a function * # For complete description of group definition see @env:KitEditors!EDITOR_GROUP ? * # Represents a property of the group You can assign the 'type' attribute for evaluating of the value of the property as a function * # For complete description of editor elements and properties see @env:KitEditors!EDITOR_ELEM * # Represents a property of the editor element You can assign the 'type' attribute for evaluating of the value of the property as a function Example PROPERTIES 100 General on 75 function defineEditor(def) { if (!def) def={}; if (typeof def != 'object') return raiseKitError('Invalid editor definition near %where%', STR(def)); var id=UPPER(def.id); if (id) { if (!isValidId(def.id)) return raiseKitError('Invalid namespace specification of Id:'+ def.id + " in kit :" + _currentPackage); if (id in _kitEditors) return raiseKitError('Editor "'+id+'" is already defined'); } var edt=[]; edt.category = def.category || ''; edt.priority = POS(def.priority) || 0; edt.visible = def.visible || null; edt.color = UPPER(def.color); edt.description = def.description || ''; edt.userdata = def.userdata || null; edt.findPos = _findEditorPos; edt.getItem = _getEditorElem; edt.append = _appendEditorElem; edt.insert = _insertEditorElem; edt.remove = _removeEditorElem; edt.appendToGroup = _appendToGroup; edt.clearGroup = _clearGroup; edt.removeGroup = _removeGroup; edt.clear = _clearEditorItems; edt.index = null; if (id) { edt.id = id; _kitEditors[edt.id] = edt; } return edt; } <@method name="getEditor"> Returns a specified editor definition Editor Id The requested editor definition function getEditor(id) { return _kitEditors[UPPER(id)] || null; } <@method name="getEditorsTable"> Returns the complete editors table Table of editor definitions, indexed by editor id Editor id's are stored in uppercase. Use @lib:Basic!UPPER macro to convert the editor's id to uppercase before using it as the index in this table. function getEditorsTable() { return _kitEditors; } <@method name="getSelectedEditors"> Returns the editor definitions that belong to a given category, sorted by priority The requested editors category Array of selected editor definitions function getSelectedEditors(category) { var E=[], cat=UPPER(category); for (var k in _kitEditors) { var edt=_kitEditors[k]; if (UPPER(edt.category) == cat) E.push(edt) } SORT(E, 'priority'); return E; } <@method name="removeEditor"> Removes a specified editor definition The id of the editor definition to remove function removeEditor(id) { delete _kitEditors[UPPER(id)]; } <@method name="parseEditor" scope="private"> Parses the given editor node and returns a string which represents its details Editor node to parse Map of properties to override existing properties function parseEditor(editorNode, override) { var res=""; var map = getNodeProps(editorNode, override); res+="var editor = $ENV.defineEditor(" + __xmlMap2Str(map) + ");"; var groups = editorNode.selectNodes('GROUP') || [] ; for (var k=0;k Creates the editor element definition for the specified property, according to metadata of that property Current unit Object to take the propery from Array to add the new element into Property name function addPropertyEditorDef(unit, object, elements, propName) { var property = object.properties[propName]; if (!property.metadata || !property.metadata.editor) return null; var elemDefs = property.metadata.editor; if (!ISARRAY(elemDefs)) elemDefs = [elemDefs]; for (var k in elemDefs) { var elemDef = elemDefs[k]; var type = elemDef.editor ? elemDef.editor : elemDef.type; if (!type) continue; // editor=false or the metadata doesn't describe a valid property editor element if (!elemDef.group) elemDef.group = 'General'; // assuming there's always a general group var elem = CLONE(elemDef); delete elem.editor; elem.id = property.name; elem.type = type; elements.push(elem); } } <@method name="addPropertyEditor" scope="private"> Adds the elements in the given collection to the given propert editor Editor definition Collection of @EDITOR_ELEM elements 'group' elements in the @elements collection each must have 'id' parameter set. Elements in the @elements collection can have 'group' property that holds the 'id' of the group to put the element into. function addPropertyEditor(editorDef, elements) { var lastGroup = null; for (var k in elements) { elem = elements[k]; if (!elem) return; if (elem.type == "group") { editorDef.append(elem); // append a group lastGroup = elem; } else { var gid = (elem.group) ? elem.group : lastGroup && lastGroup.id; if (!gid) return; delete elem.group; editorDef.appendToGroup(gid, elem); } } } // INTERNAL: parses the given group node, and returns its details function parseGroup(res, groupNode) { var group = getNodeProps(groupNode); group['type'] = 'group'; res+="editor.append( " + __xmlMap2Str(group) + ");"; return parseControls(res, groupNode); } // INTERNAL: parses the controls in the given group, and returns their details function parseControls(res, group) { var controls = group && group.childNodes|| []; for (var i=0;i Defines an editor element Element Types

The editor element definition is a union of a variety of editor element types, classified as follows:

Category | Type | Description | Datatype ACTION | BTN | Text or image button | N.A. | LINK | Text or image link | N.A. | PUSH | Pushbutton | N.A. | | | CHOICE | RADIO | Radio buttons group | String | CHECKLIST | Checkbox buttons group | String | SELECT | Single selection list | String | MULTISEL | Multiple selection list | String | | | CUSTOM | CUSTOM | Owner-drawn (custom) element | Variant | | | DISPLAY | DISPLAY | Formatted values display | Variant | | | DRAG | DRAG | Draggable element | N.A. | | | INPUT | BOOL | Boolean input field | Boolean | COLOR | Color input field | String | COMBO | Combobox input field | String | DATE | Date input field | Date | ENUM | Dropdown input field | String | EXPR | GML expression input field | String | FLOAT | Floating-point input field | Number | HTML | HTML input field | String | INT | Integer input field | Number | STR | Simple string input field | String | TEXT | Multi-line string field | String | TIME | Time input field | Date | URL | Url input field | String | USER | User-defined input field | String | | | STATIC | HTML | Static html content | N.A. | SUBTITLE | Sub-title | N.A. | DIVIDER | Dividing line | N.A. | SPACER | Spacing line | N.A. | | | SLIDER | SLIDER | Numeric slider | Number | | | TOGGLE | CHECK | Checkbox button | Boolean | TOGGLE | Toggle button | Boolean | | | TREE | TREE | Hierarchical tree selector | String | | | Element Properties

The editor element's definition is made of the following properties:

General
PropertyTypeApplies%SP%toDescription
idQNameALLElement's identifier. The identifier is required for data bound elements, and must be unique within the editor's scope. The identifier can also be optionally provided for static elements.
typeEnumALLElement's type according to the available types listed above
priorityNumberALLElement's priority. The element will be positioned according to it's relative priority

Data
PropertyTypeApplies%SP%toDescription
domain@lib:Global!ENUM_DEFINPUT, CHOICEAn enumeration that defines the allowed values domain. Dynamic enumerations are allowed only for INPUT elements.
domainArrayTREEA recursive array that contains the tree nodes data (or a function returning such an array). Each item in the array is an object {value, text, children} that represents a tree node, where ~value is the node's value, ~text is the node's display text label, and ~children is an nested array (with same structure) representing the child nodes (if any).
minNumberINPUT, SLIDERMinimum value for numeric data types
maxNumberINPUT, SLIDERMaximum value for numeric data types
stepNumberINPUT, SLIDERStepping value for numeric data types
popupStringINPUTUrn of the custom popup for user-defined data types

Display
PropertyTypeApplies%SP%toDescription
labelStringALLLabel to display near the element
descrStringALLDescription to display in the element's tooltip
iconStringACTION, DRAGUrl of icon to display in the element. Typically, ACTION elements use small icons (16x16), and DRAG elements use large icons (32x32).
contentStringSTATICHtml content to display in the element
minLabelStringSLIDERLabel to display for the minimum value
maxLabelStringSLIDERLabel to display for the maximum value
expandNumberTREENumber of levels to expand when the tree is first displayed (default is 1)

Style
PropertyTypeApplies%SP%toDescription
frameEnumCHOICE, DISPLAY, INPUT, TREE The element's frame style, according to:
NONENo frame (default for INPUT and CHOICE(RADIO|CHECKLIST) types)
SOLIDSolid frame drawn around the element (default for CHOICE(SELECT|MULTISEL) and TREE types)
INSETSunken frame drawn around the element
flatBoolCHOICE, TOGGLEIndicates whether to use flat or classic buttons style
arrowEnumINPUT Indicates when the dropdown arrow should be displayed, according to:
ALWAYSAlways show the dropdown arrow (default)
AUTOShow the dropdown arrow only when the element receives the input focus
NEVERNever show the dropdown arrow
styleStringALLCustom styling rules to apply on the element

Layout
PropertyTypeApplies%SP%toDescription
outerNumberACTION(link), CHOICE, DISPLAY, INPUT, SLIDER, STATIC, TOGGLE, TREEThe element's outer margin (gutter), in grid units. The outer margin defines the indentation of the element's label.
innerNumberCHOICE, DISPLAY, INPUT, SLIDER, STATIC, TREEThe element's inner margin (indentation), in grid units. The outer margin defines the indentation of the element itself. If the inner margin is equal to or less than the outer margin, then the element will be placed below the label.
columnsNumberCHOICENumber of displayed columns (default is 1; 0 implies no columns)
heightEnumCHOICE, DISPLAY, STATIC, TREEThe element's height, if the element is inside a group with flow layout:
AUTOAdjust the element's height to fit its contents (default)
nnnSet the element to fixed height nnn, in pixels
widthEnumACTIONElement's width, if the element is inside a group with flow layout:
AUTOStandard width according to element's type (default)
SHORTShort width
MEDIUMMedium width
LONGLong width
nnnFixed width, in pixels
nnn%Variable width, as percentage of the containing group's width
left,
top,
width,
height
NumberALLThe element's bounding box, if the element is inside a group with absolute layout.

Each of the values can be specified either as a fixed number of pixels (nnn), or as a percentage of the corresponding dimension of the containing group (nnn%).

Constraints
PropertyTypeApplies%SP%toDescription
getter FunctionCHOICE, CUSTOM, DISPLAY, INPUT, SLIDER, TOGGLE, TREE Dynamic value getter for the editor element. If provided, this function will be called whenever a value needs to be set in the element, using:

value = getter(data, def)

Where ~data is the editor's data object and ~def is this element's definition. The ~getter function should return the value that needs to be represented in the element.
setterFunctionCHOICE, CUSTOM, INPUT, SLIDER, TOGGLE, TREE Dynamic value setter for the editor element. If provided, this function will be called whenever the element's value is changed, using:

actualValue = setter(value, data, def)

Where ~value is the value to set, ~data is the editor's data object, and ~def is this element's definition.

The ~setter function may carry out any required actions based on the new value. If these actions modify other members of the ~data object, then the ~sideEffects property must be set to indicate this fact to the system.

If the ~setter function returns a value, then this value is considered to be the ~actualValue to use in place of the original ~value. This enables placing constraints on the values space of the editor element. If the ~setter function does not return any value, then the values space will not be constrained.

formatFunctionDISPLAY, SLIDER Dynamic value formatter for the editor element. If provided, this function will be called whenever the element's value is displayed, using:

displayValue = format(value, data, def)

Where ~value is the value to format, ~data is the editor's data object, and ~def is this element's definition. The ~format function should format the given ~value and return the result ~displayValue.
visibleFunctionALL Dynamic visibility state of the editor element:

flag = visible(data, def)

Where ~data is the editor's data object, and ~def is this element's definition. If the function returns ~true the element will be visible; otherwise, it will be hidden. If this function is omitted, the element will be visible by default.
activeFunctionALL Dynamic activation state of the editor element:

flag = active(data, def)

Where ~data is the editor's data object, and ~def is this element's definition. If the function returns ~true the element will be activated (enabled); otherwise, it will be deactivated (disabled). If this function is omitted, the element will be active by default.
sideEffectsBooleanCHOICE, CUSTOM, INPUT, SLIDER, TOGGLE, TREE Indicates whether this editor element has side-effects that may require repainting other elements in the editor.

Events
PropertyTypeApplies%SP%toDescription
signal@lib:Global!SIGNAL_DEFACTIONThe signal to raise when the button is clicked
ondragFunctionDRAG This function will be called when the user starts to drag the element, using:

ondrag(dnd, def)

Where ~dnd is the drag and drop object (see @dev:Controller!DND_OBJECT) and ~def is this definition. Use this function to perform any setup required prior to the drag and drop operation.
ondropFunctionDRAG This function will be called when the user drops the element, using:

ondrop(dnd, def)

Where ~dnd is the drag and drop object (see @dev:Controller!DND_OBJECT) and ~def is this definition. The ~dnd parameter is provided only if the element was dropped on a valid target (otherwise, ~dnd will be ~null). Use this function to carry out the relevant actions and cleanup the drag and drop operation.

Rules
PropertyTypeApplies%SP%toDescription
dragRuleStringDRAG Holds the Rule name that can be executed from within the ondrag function implementation.
dropRuleStringDRAG Holds the Rule name that can be executed from within the ondrop function implementation.

Owner Draw
PropertyTypeApplies%SP%toDescription
paintFunctionCUSTOM Custom paint function to use for building the element's HTML markup. This function will be called when the element is first constructed, using:

elem = paint(def, parent)

Where ~def is this definition and ~parent is the HTML container into which the new element needs to be added. The ~paint function should create the new element under the given parent element, and return the new element to its caller.
repaintFunctionCUSTOM Custom value repaint function for the element. This function will be called whenever the element's value is changed, using:

elem.repaint(value)

Where ~elem is the element's HTML object (can be referenced using the ~this keyword) and ~value is the new element's value (for data bound elements). The ~repaint function should repaint the element according to its new value.
captureFunctionCUSTOM Custom capture function for the element. This function will be called whenever the value stored in the element needs to be captured, using:

value = elem.capture()

Where ~elem is the element's HTML object (can be referenced using the ~this keyword). The ~capture function should obtain the element's value and return it to its caller.
setVisibleFunctionCUSTOM Custom function for setting the element's visiblity state, in the form:

elem.setVisible(visible)

Where ~elem is the element's HTML object (can be referenced using the ~this keyword) and ~visible is the new element's visibility state.
setActiveFunctionCUSTOM Custom function for setting the element's activation state, in the form:

elem.setActive(active)

Where ~elem is the element's HTML object (can be referenced using the ~this keyword) and ~active is the new element's activation state.
Data Binding

Data binding is the mechanism by which data is read from or written to the different editor elements. The data type depends on the element type, according to the ~Datatype column in the element types table above (~N.A. indicates that the element does not support data binding).

Typically, the editor is bound to a data object which serves as the data source for its elements. Each editor element corresponds to a member of the data object with the same name. Whenever the value of an element is changed, the value of the corresponding member in the data object will be updated to reflect the change, and vice versa. The concrete mechanism by which the data binding is achieved depends on the implementation of the component that renders the editor (see, for example, @lib:SmartForm).

Dynamic Constraints

All dynamic constraints (~getter, ~setter, ~visible, and ~active) can be written as a JavaScript function with the specific parameters described above, or as a string containing a simple JavaScript expression according to the following rules: Use a single statement that evaluates to the expected return value, or use a statement block ending with an explicit ~return statement. Access the parameters ~data, ~value, and ~definition directly by their names. Access members of the data object by prefixing their names with the '\@' symbol (i.e., ~\@field is equivalent to ~data.field). Use \@\@ to access the current ~value parameter.

Dependencies created using the shortcut notation (3) above are detected by the system and thus do not need to be declared explicitly with the ~sideEffects property. For example:

{ id:'min', type:'int', sideEffects:true}, { id:'max', type:'int', sideEffects:true}, { id:'xyz', type:'int', setter:function(value, data, definition) { // constrain value to min-max range var minValue = data.min; var maxValue = data.max; var theValue = LIMIT(minValue, value, maxValue); // round value to nearest multiple of 10 if (theValue % 10 != 0) theValue = ROUND(theValue/10)*10; // return the actual value return theValue; } } is equivalent to: { id:'min', type:'int'}, { id:'max', type:'int'}, { id:'xyz', type:'int', setter:'ROUND(LIMIT(\@min, value, \@max),10)' } Note how, in the second form, the ~sideEffects property is inferred from the references made in the ~setter expression.

Cross Reference Property | ACTION | CHOICE | CUSTOM | DISPLAY | DRAG | INPUT | SLIDER | STATIC | TOGGLE | TREE active | + | + | + | + | + | + | + | + | + | + arrow | | | | | | + | | | | capture | | | + | | | | | | | columns | | + | | | | | | | | content | | | | | | | | + | | descr | + | + | + | + | + | + | + | + | + | + domain | | ! | | | | + | | | | ! dragRule | | | | | + | | | | | dropRule | | | | | + | | | | | expand | | | | | | | | | | + flat | | + | | | | | | | + | format | | | | + | | | + | | | frame | | + | | + | | + | | | | + getter | | + | + | + | | + | + | | + | + height%SP%(abs) | + | + | + | + | + | + | + | + | + | + height%SP%(flow) | | + | | + | | | | + | | + icon | + | | | | + | | | | | id | + | ! | ! | ! | + | ! | ! | + | ! | ! inner | | + | | + | | + | + | + | | + label | + | + | + | + | + | + | + | + | + | + left%SP%(abs) | + | + | + | + | + | + | + | + | + | + max | | | | | | + | + | | | maxLabel | | | | | | | + | | | min | | | | | | + | + | | | minLabel | | | | | | | + | | | ondrag | | | | | + | | | | | ondrop | | | | | + | | | | | outer | + | + | | + | | + | + | + | + | + paint | | | + | | | | | | | popup | | | | | | + | | | | priority | + | + | + | + | + | + | + | + | + | + repaint | | | + | | | | | | | setter | | + | + | | | + | + | | + | + sideEffects | | + | + | | | + | + | | + | + signal | + | | | | | | | | | step | | | | | | + | + | | | style | + | + | + | + | + | + | + | + | + | + toggle | | | + | | | | | | | top%SP%(abs) | + | + | + | + | + | + | + | + | + | + type | ! | ! | ! | ! | ! | ! | ! | ! | ! | ! visible | + | + | + | + | + | + | + | + | + | + width%SP%(abs) | + | + | + | + | + | + | + | + | + | + width%SP%(flow) | + | | | | | | | | |

LEGEND: + optional, ! required

<@struct name="EDITOR_GROUP" also="EDITOR_DEF EDITOR_ELEM"> Defines a group container holding other editor elements

All editor elements always belong to exactly one editor group. The elements that belong to a group start with the first element following the group, and continue until the next group, or until the last element in the editor definition. If the first element in an editor definition is not a group, then a default group will be implicitly created. The group definition is made of the following properties:


General
PropertyTypeDescription
idQNameGroup identifier (optional)
typeStringAlways set to ~group
sortByStringThe sortBy holds the name of the attribute to sort the group's properties by. By default it is set to 'label'.

Display
PropertyTypeDescription
titleStringThe text to display in the group's titlebar. If omitted, the group's titlebar will not be shown.
descrStringThe description to display in the group's tooltip
toggleEnum The group's toggle mode, according to:
NONEGroup has no toggle (default)
ONGroup has toggle, initially expanded
OFFGroup has toggle, initially collapsed
LASTGroup expands/collapses together with the last group that has a toggle

Styles
PropertyTypeDescription
colorEnum The group's background color, according to:
NONENo background (default)
WHITEWhite background
GRAYGray background
LIGHTLight color background
DARKDark color background
DIALOGDefault dialog background
frameEnum The group's frame style, according to:
NONENo frame (default)
SOLIDDraw a solid frame inside the group's margins
INSETDraw a sunken frame inside the group's margins
TOPLEVELDraw a top-level frame and titlebar around the group's exterior
paletteEnum The group's palette style for defining how drag elements in the group will be displayed, according to:
INHERITInherit global palette style (default)
PAL-I32DDisplay 32x32 icons and full descriptions, arranged in a vertical list
PAL-I32LDisplay 32x32 icons plus names, arranged in a vertical list
PAL-I32NDisplay 32x32 icons plus names, arranged in a grid
PAL-I32Display only 32x32 icons, arranged in a grid
PAL-I16LDisplay 16x16 icons plus names, arranged in a vertical list
PAL-I16Display only 16x16 icons, arranged in a grid
PAL-LISTDisplay only names, arranged in a vertical list
PAL-BULDisplay only names, arranged in a vertical list with bullets
dividerEnum The type of divider(s) to add to the group, according to:
NONENo divider (default)
ABOVESolid line drawn at the top of the group
BELOWSolid line drawn at the bottom of the group
BOTHBoth dividers, above and below the group
captionEnum The group's titlebar style, according to:
NONENo title
BOLDShow title in bold text (default)
PLAINShow title in normal text
ITALICShow title in italic text
UNDERLINEShow title in bold text and with an underline
scrollEnum The group's scrolling options, according to:
NONENo scrollbars (default for auto-fit and fixed-size groups)
AUTOShow scrollbars when needed (default for variable-size groups)
ALWAYSAlways show scrollbars
styleStringCustom styling rules to apply on the group

Layout
PropertyTypeDescription
layoutEnum The group's elements layout, according to:
FLOWArrange the group's elements in a vertical flow (default)
ABSOLUTEArrange the group's elements using absolute positioning (requires that the group has a fixed height)
heightEnum The group's height, according to:
FITAutomatically fit size to contents (default)
nnnFixed size, in pixels
nnn%Variable size, as percentage of available freespace
When the group has an absolute layout, then the height must be a fixed number of pixels.
alignEnum Indicates how to align floating elements (such as buttons or static content) within the group, according to:
LEFTAlign left (default)
CENTERAlign center
RIGHTAlign right
outerNumberThe group's default outer margin (gutter), in grid units
innerNumberThe group's default inner margin (indentation), in grid units

Constraints
PropertyTypeDescription
visibleFunction Dynamic visibility state of the editor group:

flag = visible(data, definition)

Where ~data is the editor's data object, and ~definition is this group's definition. If the function returns ~true the group will be visible; otherwise, it will be hidden. If this function is omitted, the group will be visible by default.
activeFunction Dynamic activation state of the editor group:

flag = active(data, definition)

Where ~data is the editor's data object, and ~definition is this group's definition. If the function returns ~true the group will be activated (enabled); otherwise, it will be deactivated (disabled). If this function is omitted, the group will be active by default.

For best visual appearance, it is recommended to group editor elements by their type and cardinality.

<@struct name="EDITOR_DEF" also="EDITOR_GROUP EDITOR_ELEM"> Defines an editor An editor is a collection of one or more groups of editing elements that are shown or hidden together Name | Type | Description id | QName | The editor's identifier - must be prefixed with namespace e.g. com.sap.mypackage:id category | String | The editor's category, used for relating editors to specific tasks or dialogs priority | Number | The editor's priority, used for calculating the display order of editors within the same category visible | Function | Dynamic visibility state of the editor:

flag = visible(data, definition)

Where ~data is the editor's data object, and ~definition is this editor's definition. If the function returns ~true the editor will be visible; otherwise, it will be hidden. If the function is omitted, the editor will be visible by default. color | Enum | The editor's default background color. Can be overridden on the group level. See @EDITOR_GROUP for the enumeration of the available color values. description | String | The editor's description 0..n | @EDITOR_ELEM or @EDITOR_GROUP | The elements contained in the editor, listed by display order
In addition, the structure has the following methods: <i>editor</i>.append(elem, after) Appends an element just after another element in the editor, where: Parameter | Type | Description elem | @EDITOR_ELEM | The element to append after | QName | Optional. The id of the element after which the new element will be appended If ~after is omitted or not found, the new element will be appended at the end of this editor. elem = <i>editor</i>.getItem(id) Gets s a specified editor element by Id or by position, where: Parameter | Type | Description id | QName/Number | The element id or ordinal position elem | @EDITOR_ELEM | The requested editor element <i>editor</i>.insert(elem, before) Inserts an element just before another element in the editor, where: Parameter | Type | Description elem | @EDITOR_DEF | The element to insert before | QName | Optional. The id of the element before which the new element will be inserted If ~before is omitted, the new element will be inserted at the beginning of this editor. If ~before is not found, the new element will be inserted at the end of this editor. <i>editor</i>.remove(id) Removes an element from the editor, where: Parameter | Type | Description id | QName | The Id of the element to remove <i>editor</i>.clear(id) Clears all elements in the editor Parameter | Type | Description