CodeArea.js 12 KB
Ext.define('amdaUI.CodeArea', {
    extend: 'extensions.SelectableTextArea',
    
    alias: 'widget.CodeArea',

    constructor: function(config) {
        var infotip = '<img amda_clicktip="constructParameter"  src="js/resources/images/16x16/info_mini.png"/>&nbsp;';
        if(config.type ==="parameter"){
            this.itemId = 'formParamConstructParameter';
            this.fieldLabel = infotip+'Construct Parameter';
            this.blankText =  'Construct Parameter is required';
            this.name = 'buildchain';
            this.flex = 0.5;
        }
        else if (config.type ==="search"){
            this.itemId = 'formSearchCondition';
            this.fieldLabel = infotip+'Data Mining Condition';
            this.blankText = 'Condition expression is required';
            this.name = 'expression';
            this.flex = 2;

        }
        this.init(config);
        this.callParent(arguments);
    },
    
    codeMirror:null,

    functionsRegex : new RegExp("(?:" + myDesktopApp.functionList.join("|") + ")\\b"),
	constantRegex : new RegExp("(?:" + myDesktopApp.constantList.join("|") + ")\\b"),
	parametersRegex : new RegExp("(?:" + myDesktopApp.parametersList.join("|") + ")\\b"),

    setValue : function(value){
        if(this.codeMirror){ 
            this.codeMirror.getDoc().setValue(value);
        }
        this.callParent(arguments);
    },
    init : function(config) {
            var me = this;
            CodeMirror.defineSimpleMode("amda_mode", {
				start: [
					{ regex: me.functionsRegex, token: "keyword" },
                    { regex: /tt_\w+|cat_\w+|shared(timeTable|catalog)_\w+/, token: "atom" },
                    { regex: me.constantRegex, token: "variable-3" },
                    { regex: me.parametersRegex, token: "variable-2" },
                    { regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/, token: "number" },
                    { regex: /[-+\/*=<>!]+/, token: "operator" },

				],
				comment: [],
				meta: {}
            });
			  
            CodeMirror.registerHelper("lint", "amda_mode", function(text) {
				var errors = [];
				var paranthesis = [];
				var crochets=[];
			  
				// Split the input text into lines
				var lines = text.split("\n");
				// Loop over each line
				for (var i = 0; i < lines.length; i++) {
				    var line = lines[i];
			  
                    // Loop over each character in the line
                    for (var j = 0; j < line.length; j++) {
                        var ch = line.charAt(j);
                        // Push opening parentheses onto the paranthesis
                        if (ch === "(") {
                            paranthesis.push({
                                type: "open",
                                line: i,
                                ch: j
                            });
                        }
                        // Push opening parentheses onto the crochets
                        if (ch === "[") {
                            crochets.push({
                                type: "open",
                                line: i,
                                ch: j
                            });
                        }
					    // Pop closing parentheses off the paranthesis
                        if (ch === ")") {
                            if (paranthesis.length === 0) {
                                errors.push({
                                    message: "Extra closing parenthesis",
                                    severity: "error",
                                    from: CodeMirror.Pos(i, j),
                                    to: CodeMirror.Pos(i, j + 1)
                                });
                            } else {
                                paranthesis.pop();
                            }
                        }
					    // Pop closing crochets off the crochets
                        if (ch === "]") {
                            if (crochets.length === 0) {
                                errors.push({
                                    message: "Extra closing crochets",
                                    severity: "error",
                                    from: CodeMirror.Pos(i, j),
                                    to: CodeMirror.Pos(i, j + 1)
                                });
                            } 
                            else {
                                crochets.pop();
                            }
                        }
				    }
				}
			  
				// Check for unmatched opening parentheses
				for (var i = 0; i < paranthesis.length; i++) {
                    var item = paranthesis[i];
                    errors.push({
                        message: "Missing closing parenthesis",
                        severity: "error",
                        from: CodeMirror.Pos(item.line, item.ch),
                        to: CodeMirror.Pos(item.line, item.ch + 1)
				    });
				}

				// Check for unmatched opening parentheses
				for (var i = 0; i < crochets.length; i++) {
					var item = crochets[i];
					errors.push({
                        message: "Missing closing crochets",
                        severity: "error",
                        from: CodeMirror.Pos(item.line, item.ch),
                        to: CodeMirror.Pos(item.line, item.ch + 1)
					});
                }
			  
				return errors;
            });
            
            var myConf = {
                labelAlign: 'top',
				labelPad: 0,
				validateOnChange: false,
				validateOnBlur: false,
				validator: this.isBalanced,
				listeners:
				{
					render: function (textArea, op) {
						var me = this;
						var meEl = me.bodyEl;
						var dropTarget = Ext.create('Ext.dd.DropTarget', meEl,
							{
								ddGroup: 'explorerTree',
								notifyEnter: function (ddSource, e, data) { },
								notifyOver: function (ddSource, e, data) {
									if (data.records[0].get('nodeType') == 'localParam' && data.records[0].get('notyet')) {
										this.valid = false;
										return this.dropNotAllowed;
									}

									if (((data.records[0].get('nodeType') == 'localParam') ||
										(data.records[0].get('nodeType') == 'remoteParam') ||
										(data.records[0].get('nodeType') == 'remoteSimuParam') ||
										(data.records[0].get('nodeType') == 'derivedParam') ||
										(data.records[0].get('nodeType') == 'specialParam') ||
										(data.records[0].get('nodeType') == 'myDataParam') ||
										(data.records[0].get('nodeType') == 'timeTable') ||
										(data.records[0].get('nodeType') == 'catalog') ||
										(data.records[0].get('nodeType') == 'sharedtimeTable') ||
										(data.records[0].get('nodeType') == 'sharedcatalog') ||
										(data.records[0].get('nodeType') == 'alias')) &&
                                        config.type === "parameter" &&
										(data.records[0].isLeaf() || data.records[0].get('isParameter')) &&
										!(data.records[0].data.disable)) {
										this.valid = true;
										return this.dropAllowed;
									}
                                    else if(((data.records[0].get('nodeType') == 'localParam') ||
                                        (data.records[0].get('nodeType') == 'remoteParam') ||
                                        (data.records[0].get('nodeType') == 'remoteSimuParam') ||
                                        (data.records[0].get('nodeType') == 'derivedParam') ||
                                        (data.records[0].get('nodeType') == 'specialParam') ||
                                        (data.records[0].get('nodeType') == 'myDataParam') ||
                                        (data.records[0].get('nodeType') == 'alias')) &&
                                        config.type === "search" &&
                                        (data.records[0].isLeaf() || data.records[0].get('isParameter')) &&
                                        !(data.records[0].data.disable)) {
                                        this.valid = true;
                                        return this.dropAllowed;
                                    }
									this.valid = false;
									return this.dropNotAllowed;
								},
								notifyDrop: function (ddSource, e, data) {
									if (!this.valid)
										return false;
									var nameToSent;
									var components = null;
									switch (data.records[0].get('nodeType')) {
										case 'localParam':
										case 'remoteParam':
										case 'remoteSimuParam':
											nameToSent = data.records[0].get('id');
											if (data.records[0].get('alias') != "")
												var nameToSent = "#" + data.records[0].get('alias');
											var component_info = data.records[0].get('component_info');
											if (component_info && component_info.parentId) {
												if (component_info.index1 && component_info.index2) {
													nameToSent = component_info.parentId;
													components = [];
													if (component_info.index1)
														components['index1'] = component_info.index1;
													if (component_info.index2)
														components['index2'] = component_info.index2;
												}
												if (data.records[0].get('needsArgs')) {
													nameToSent = component_info.parentId;
													if (component_info.index1) {
														components = [];
														components['index1'] = component_info.index1;
													}
												}
											}
											break;
										case 'alias':
											nameToSent = "#" + data.records[0].get('text');
											break;
										case 'derivedParam':
											nameToSent = "ws_" + data.records[0].get('text');
											break;
										case 'specialParam':
											nameToSent =  data.records[0].get('id');
											break;
										case 'timeTable':
											nameToSent =  "tt_"+data.records[0].get('text');
											break;
										case 'catalog':
											nameToSent =  "cat_"+data.records[0].get('text');
											break;
										case 'sharedtimeTable':
											nameToSent =  "sharedtimeTable"+data.records[0].get('text');
											break;
										case 'sharedcatalog':
											nameToSent =  "sharedcatalog_"+data.records[0].get('text');
											break;
										case 'myDataParam':
											var name = data.records[0].get('text');
											nameToSent = "wsd_" + name;
											break;
										default:

											return false;
									}
                                    var paramModule;
                                    if( config.type === "parameter")
									    paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id);
									else if (config.type === "search")
                                        paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.search.id);
                                    if (paramModule) {
										if (data.records[0].get('predefinedArgs')) {
											paramModule.parseTemplatedParam(nameToSent, function (param_info) {
												paramModule.addParam(param_info.paramid, data.records[0].get('leaf'), true, components, param_info.template_args, null);
											});
										}
										else {
											paramModule.addParam(nameToSent, data.records[0].get('leaf'), data.records[0].get('needsArgs'), components,null,null);
										}
									}
									return true;
								}
							});
                       me.codeMirror = CodeMirror.fromTextArea(textArea.inputEl.dom, {
                            lineNumbers: false,
                            mode: 'amda_mode',
                            gutters: ["CodeMirror-lint-markers"],
                            extraKeys: {"Ctrl-Space": "autocomplete"},
                            autoCloseBrackets: true,
                            styleActiveLine: true,
                            lineWrapping: true,
                            lint: true
                        });
                        me.codeMirror.on('change', editor => { me.setRawValue(editor.getValue()); });;
					}
				}
				//TODO: ?validator on formula structure?
				//			listener : {
				//				valid : function(field) {
				//
				//				}
				//			}
			};

            Ext.apply (this , Ext.apply (arguments, myConf));
    }
});