Merge branch 'master' of http://git.roojs.com:8081/app.Builder.js
authorAlan Knowles <alan@akbkhome.com>
Wed, 24 Aug 2011 09:30:57 +0000 (17:30 +0800)
committerAlan Knowles <alan@akbkhome.com>
Wed, 24 Aug 2011 09:30:57 +0000 (17:30 +0800)
JsRender/Base.js [new file with mode: 0644]
JsRender/Gtk.js [new file with mode: 0755]
JsRender/Lang.js [new file with mode: 0644]
JsRender/Roo.js [new file with mode: 0644]

diff --git a/JsRender/Base.js b/JsRender/Base.js
new file mode 100644 (file)
index 0000000..f25a32c
--- /dev/null
@@ -0,0 +1,327 @@
+//<Script type="text/javascript">
+
+
+XObject = imports.XObject.XObject;
+
+
+Lang = imports.JsRender.Lang.Lang;
+
+File = imports.File.File;
+// File Provider..
+
+Base = XObject.define(
+    
+    function(cfg) {
+        
+        XObject.extend(this, cfg);
+        
+    },
+    Object,
+    {
+        /**
+         * @cfg {Array} doubleStringProps list of properties that can be double quoted.
+         */
+        doubleStringProps : false,
+        
+        id : false,
+        name : false,   // is the JS name of the file.
+        path : '',      // is the full path to the file.
+        parent : false, // JS parent.
+        
+        title : false,  // a title.. ?? nickname.. ??? - 
+        project: false, // name...
+        //Project : false, // link to container project!
+        
+        items : false, // the tree of nodes.
+        
+        cn : false, // array used by project tree.
+        
+        
+        save : function()
+        {
+            var write = { }; 
+            var _this = this;
+            var write = this.toJsonArray()
+            print("WRITE: " + this.path);// + "\n" + JSON.stringify(write));
+            File.write(this.path, JSON.stringify(write, null, 4));
+        },
+        
+        /**
+         * accepts:
+         * { success : , failure : , scope : }
+         * 
+         * 
+         * 
+         */
+         
+        getTree : function( o ) {
+            print("File.getTree tree called on base object?!?!");
+        },
+        toJsonArray : function()
+        {
+            var ret = { }; 
+            var _this = this;
+            ['id', 'name', 'parent', 'title', 'path', 'items' , 'permname', 'modOrder' ].forEach( function(k) {
+                ret[k] = typeof(_this[k]) == 'undefined' ? '' : _this[k];
+            });
+            return ret;
+        },
+        getTitle : function()
+        {
+            if (this.title) {
+                return this.title;
+            }
+            return this.path.split('/').pop();
+            
+        },
+        getTitleTip: function()
+        {
+            if (this.title) {
+                return '<b>' + this.title + '</b> ' + this.path;
+            }
+            return this.path;
+        },
+        sortCn: function()
+        {
+            this.cn.sort(function(a,b) {
+                return a.path > b.path;// ? 1 : -1;
+            });
+        },
+        // should be in palete provider really..
+        
+        guessName : function(ar) // turns the object into full name.
+        {
+             // eg. xns: Roo, xtype: XXX -> Roo.xxx
+            if (typeof( ar['|xns'] ) == 'undefined' || typeof( ar['xtype'] ) == 'undefined') {
+                return '';
+               }
+             
+            return ar['|xns'] +'.' + ar['xtype'];
+                            
+                                 
+        },
+        
+        
+        
+        copyTo: function(path, cb)
+        {
+            var _this = this;
+            this.loadItems(function() {
+                
+                _this.path = path;
+                cb();
+            });
+            
+        },
+        
+        /**
+         * 
+         * munge JSON tree into Javascript code.
+         * 
+         * FIXME: + or / prefixes to properties hide it from renderer.
+         * FIXME: '*props' - not supported by this.. ?? - upto rendering code..
+         * FIXME: needs to understand what properties might be translatable (eg. double quotes)
+         * 
+         * @arg {object} obj the object or array to munge..
+         * @arg {boolean} isListener - is the array being sent a listener..
+         * @arg {string} pad - the padding to indent with. 
+         */
+        
+        
+        mungeToString:  function(obj, isListener, pad)
+        {
+            pad = pad || '    ';
+            var keys = [];
+            var isArray = false;
+            isListener = isListener || false;
+             
+            // am I munging a object or array...
+            if (obj.constructor.toString() === Array.toString()) {
+                for (var i= 0; i < obj.length; i++) {
+                    keys.push(i);
+                }
+                isArray = true;
+            } else {
+                for (var i in obj) {
+                    keys.push(i);
+                }
+            }
+            
+            
+            var els = []; 
+            var skip = [];
+            if (!isArray && 
+                    typeof(obj['|xns']) != 'undefined' &&
+                    typeof(obj['xtype']) != 'undefined'
+                ) {
+                    this.mungeXtype(obj['|xns'] + '.' + obj['xtype'], els);
+                    //els.push('xtype: '+ obj['|xns'] + '.' + obj['xtype']);
+                    skip.push('|xns','xtype');
+                }
+            
+            
+            if (!isArray && obj.items && obj.items.length) {
+                // look for props..
+                var newitems = [];
+                obj.items.forEach(function(pl) {
+                    if (typeof(pl['*prop']) == 'undefined') {
+                        newitems.push(pl);
+                        return;
+                    }
+                    // we have a prop...
+                    var prop = pl['*prop'] + '';
+                    delete pl['*prop'];
+                    if (!prop.match(/\[\]$/)) {
+                        // it's a standard prop..
+                        obj[prop] = pl;
+                        keys.push(prop);
+                        return;
+                    }
+                    prop  = prop.substring(0, prop.length -2); //strip []
+                    // it's an array type..
+                    obj[prop] = obj[prop]  || [];
+                    obj[prop].push(pl);
+                    print("ADDNG PROP:" + prop + ' ' + keys.indexOf(prop) );
+                    if (keys.indexOf(prop) < 0) {
+                        keys.push(prop);
+                    }
+                    
+                    
+                    
+                });
+                obj.items = newitems;
+                if (!obj.items.length) {
+                    delete obj.items;
+                }
+                
+            }
+            
+            
+            
+            
+            
+            var _this = this;
+            
+            var left =  '';
+            
+            keys.forEach(function(i) {
+              
+                if (typeof(obj[i]) == 'undefined') { // empty or removed.
+                    return;
+                }
+                var el = obj[i];
+                if (!isArray && skip.indexOf(i) > -1) { // things we do not write..
+                    return;
+                }
+                if (!isArray) {
+                    // set the key to be quoted with singel quotes..
+                    var leftv = i[0] == '|' ? i.substring(1) : i;
+                    if (Lang.isKeyword(leftv) || Lang.isBuiltin(leftv)) {
+                        left = "'" + leftv + "'";
+                    } else if (leftv.match(/[^A-Z_]+/i)) { // not plain a-z... - quoted.
+                        var val = JSON.stringify(leftv);
+                        left = "'" + val.substring(1, val.length-1).replace(/'/g, "\\'") + "'";
+                    } else {
+                        left = '' + leftv;
+                    }
+                    left += ' : ';
+                    
+                }
+                if (isListener) {
+                    // change the lines...
+                    var str= ('' + obj[i]).replace(/^\s+|\s+$/g,"");
+                    var lines = str.split("\n");
+                    if (lines.length > 1) {
+                        str = lines.join("\n" + pad);
+                    }
+                    els.push(left  + str);
+                    return;
+                }
+                 
+                
+                
+                //var left = isArray ? '' : (JSON.stringify(i) + " : " )
+                
+                if (i[0] == '|') {
+                    // does not hapepnd with arrays..
+                    if (typeof(el) == 'string' && !obj[i].length) { //skip empty.
+                        return;
+                    }
+                    // this needs to go...
+                    //if (typeof(el) == 'string'  && obj[i].match(new RegExp("Gtk.main" + "_quit"))) { // we can not handle this very well..
+                    //    return;
+                    //}
+                    
+                    var str= ('' + obj[i]).replace(/^\s+|\s+$/g,"");;
+                    var lines = str.split("\n");
+                    if (lines.length > 1) {
+                        str = lines.join("\n" + pad);
+                    }
+                    
+                    els.push(left + str);
+                    return;
+                }
+                
+                
+                
+                
+                if (typeof(el) == 'object') {
+                    
+                    // we can skip empty items lists and empty listeners..
+                    //if (!isArray && i == 'items' && !el.length) {
+                    //    return; 
+                    //}
+                   // 
+                    var right = _this.mungeToString(el, i == 'listeners', pad + '    ');
+                    if (typeof(right) != 'undefined') {
+                        els.push(left + right);
+                    }
+                
+                    return;
+                }
+                // standard. .
+                if (typeof(obj[i]) != 'string') {
+                    els.push(left + JSON.stringify(obj[i]));
+                    return;
+                }
+                // strings..
+                if (!_this.doubleStringProps) {
+                    els.push(left + JSON.stringify(obj[i]));
+                    return;
+                }
+                if (_this.doubleStringProps.indexOf(i) > -1) {
+                    els.push(left + JSON.stringify(obj[i]));
+                    return;
+                }
+                // single quote..
+                els.push(left + "'" + obj[i].replace(/'/g, "\\'") + "'");
+                
+
+            });
+            
+            if (!isArray && !els.length) {
+                return;
+            }
+            //output the thing.
+            var spad = pad.substring(0, pad.length-4);
+            return (isArray ? '[' : '{') + "\n" +
+                pad  + els.join(",\n" + pad ) + 
+                "\n" + spad + (isArray ? ']' : '}');
+               
+            
+            
+        } 
+        
+         
+        
+    }
+    
+     
+    
+);
+
+
+
+
+
+
diff --git a/JsRender/Gtk.js b/JsRender/Gtk.js
new file mode 100755 (executable)
index 0000000..9cf029d
--- /dev/null
@@ -0,0 +1,185 @@
+//<Script type="text/javascript">
+Gio = imports.gi.Gio;
+GLib = imports.gi.GLib;
+
+XObject = imports.XObject.XObject;
+File = imports.File.File;
+  
+//----------------------- our roo verison
+Base = imports.Builder.Provider.File.Base.Base;
+
+var gid = 1;
+
+Gtk = XObject.define( 
+    function(cfg) {
+        
+        // id ,
+        //"name":"Edit Module Details",
+        // items : 
+        //"btype":"FORM", // was to be components...
+        //"app":"Builder",
+        //"module":"Pman.Tab.BuilderTop2"
+        //console.dump(cfg);
+        cfg.parent = cfg.parent || '';
+        if (!cfg.name || !cfg.fullname ) {
+            
+            // name is in theory filename without .bjs (or .js eventually...)
+            cfg.name = cfg.path.split('/').pop().replace(/\.(bjs|js)$/, '');
+            
+            cfg.fullname = (cfg.parent.length ? (cfg.parent + '.') : '' ) + cfg.name;
+        }
+        
+        
+        this.items = false;
+        if (cfg.json) {
+            var jstr =  JSON.parse(cfg.json);
+            this.items = [ jstr ];
+            //console.log(cfg.items.length);
+            delete cfg.json; // not needed!
+        }
+        this.cn = [];
+         /*
+        var p = cfg.items && cfg.items.length && cfg.items[0].parent ? cfg.items[0].parent : false;
+        
+        // ensure real data is set...
+        Roo.apply(this, {
+            name : cfg.module,
+            parent : p,
+            title : cfg.name,
+            project : cfg.app
+            
+        });
+        
+        this.cn = [];
+        */
+        Gtk.superclass.constructor.call(this, cfg);
+
+        
+        // super?!?!
+        this.id = 'file-gtk-' + gid++;
+        //console.dump(this);
+        // various loader methods..
+       
+    },
+    Base,   
+    {
+        xtype : 'Gtk',
+        setNSID : function(id)
+        {
+            
+            this.items[0]['*class'] = id;
+            
+            
+        },
+        getType: function() {
+            return 'Gtk';
+        },
+        
+        loadItems : function(cb)
+        {
+          
+            print("load Items!");
+            if (this.items !== false) {
+                return false;
+            }
+            if (!cb) {  
+                throw {
+                    name: "ArgumentError", 
+                    message : "no callback for loadItems"
+                };
+            }
+            Seed.print("load: " + this.path);
+            
+            
+
+            
+            var _this = this;     
+            var src = File.read(this.path);
+            
+            var cfg = JSON.parse(src);
+            print("loaded data");
+            //console.dump(cfg);
+            
+            //_this.name = cfg.name; -- this should not happen - name should always match filename!!
+            _this.parent =  cfg.parent;
+            _this.title =  cfg.title;
+            _this.items = cfg.items || []; 
+           
+             cb();
+             
+             
+            
+            
+            
+        },
+        /**
+         * convert xtype for munged output..
+         * 
+         */
+        mungeXtype : function(xtype, els)
+        {
+            els.push('xtype: '+ xtype);
+        },
+        
+        toSource : function()
+        {
+            
+            if (!this.items[0]) {
+                return false;
+            }
+            var data = JSON.parse(JSON.stringify(this.items[0]));
+            // we should base this on the objects in the tree really..
+            var i = [ 'Gtk', 'Gdk', 'Pango', 'GLib', 'Gio', 'GObject', 
+                'GtkSource', 'WebKit', 'Vte' , 'GtkClutter' , 'Gdl'];
+            var src = "";
+            i.forEach(function(e) {
+                src += e+" = imports.gi." + e +";\n";
+            });
+            
+            src += "console = imports.console;\n"; // path?!!?
+            src += "XObject = imports.XObject.XObject;\n"; // path?!!?
+            
+            
+            src += this.name + '=new XObject('+ this.mungeToString(data) + ");\n";
+            src += this.name + '.init();\n';
+            // register it in the cache
+            src += "XObject.cache['/" + this.name + "'] = " + this.name + ";\n";
+            
+            
+            return src;
+            
+            
+        },
+        
+        
+        /** 
+         *  saveJS
+         * 
+         * save as a javascript file.
+         * why is this not save...???
+         * 
+         * 
+         */
+        saveJS: function()
+        {
+             
+            var fn = GLib.path_get_dirname(this.path) + '/' + this.name + '.js';
+            print("WRITE : " + fn);
+            File.write(fn, this.toSource());
+            
+            return fn;
+        },
+        /*
+        getTree : function( o ) {
+            
+            
+            
+        }
+        */
+        getHelpUrl : function(cls)
+        {
+            return 'http://devel.akbkhome.com/seed/' + cls + '.html';
+        }
+        
+    });
\ No newline at end of file
diff --git a/JsRender/Lang.js b/JsRender/Lang.js
new file mode 100644 (file)
index 0000000..51f9ad5
--- /dev/null
@@ -0,0 +1,155 @@
+//<script type="text/javscript">
+
+/**
+       @namespace
+*/
+Lang = {
+    
+    
+    isBuiltin : function(name) {
+        return (this.coreObjects.indexOf(name) > -1);
+    }, 
+    coreObjects : ['_global_', 'Array', 'Boolean', 'Date', 'Error', 
+        'Function', 'Math', 'Number', 'Object', 'RegExp', 'String'],
+        
+
+    whitespace : function(ch) {
+        return this.whitespaceNames[ch];
+    },
+    
+    whitespaceNames : {
+        " ":      "SPACE",
+        "\f":     "FORMFEED",
+        "\t":     "TAB",
+        "\u0009": "UNICODE_TAB",
+        "\u000A": "UNICODE_NBR",
+        "\u0008": "VERTICAL_TAB"
+    },
+
+    newline : function(ch) {
+        return this.newlineNames[ch];
+    },
+    newlineNames : {
+        "\n":     "NEWLINE",
+        "\r":     "RETURN",
+        "\u000A": "UNICODE_LF",
+        "\u000D": "UNICODE_CR",
+        "\u2029": "UNICODE_PS",
+        "\u2028": "UNICODE_LS"
+    },
+
+    keyword : function(word) {
+        return this.keywordNames["="+word];
+    },
+    isKeyword: function(word) {
+        return typeof(this.keywordNames["="+word]) == 'undefined' ? false : true;
+    },
+
+    keywordNames : {
+        "=break":      "BREAK",
+        "=case":       "CASE",
+        "=catch":      "CATCH",
+        "=const":      "VAR",
+        "=continue":   "CONTINUE",
+        "=default":    "DEFAULT",
+        "=delete":     "DELETE",
+        "=do":         "DO",
+        "=else":       "ELSE",
+        "=false":      "FALSE",
+        "=finally":    "FINALLY",
+        "=for":        "FOR",
+        "=function":   "FUNCTION",
+        "=if":         "IF",
+        "=in":         "IN",
+        "=instanceof": "INSTANCEOF",
+        "=new":        "NEW",
+        "=null":       "NULL",
+        "=return":     "RETURN",
+        "=switch":     "SWITCH",
+        "=this":       "THIS",
+        "=throw":      "THROW",
+        "=true":       "TRUE",
+        "=try":        "TRY",
+        "=typeof":     "TYPEOF",
+        "=void":       "VOID",
+        "=while":      "WHILE",
+        "=with":       "WITH",
+        "=var":        "VAR"
+    },
+
+    punc : function(ch) {
+        return this.puncNames[ch];
+    },
+    puncNames : {
+        ";":   "SEMICOLON",
+        ",":   "COMMA",
+        "?":   "HOOK",
+        ":":   "COLON",
+        "||":  "OR", 
+        "&&":  "AND",
+        "|":   "BITWISE_OR",
+        "^":   "BITWISE_XOR",
+        "&":   "BITWISE_AND",
+        "===": "STRICT_EQ", 
+        "==":  "EQ",
+        "=":   "ASSIGN",
+        "!==": "STRICT_NE",
+        "!=":  "NE",
+        "<<":  "LSH",
+        "<=":  "LE", 
+        "<":   "LT",
+        ">>>": "URSH",
+        ">>":  "RSH",
+        ">=":  "GE",
+        ">":   "GT", 
+        "++":  "INCREMENT",
+        "--":  "DECREMENT",
+        "+":   "PLUS",
+        "-":   "MINUS",
+        "*":   "MUL",
+        "/":   "DIV", 
+        "%":   "MOD",
+        "!":   "NOT",
+        "~":   "BITWISE_NOT",
+        ".":   "DOT",
+        "[":   "LEFT_BRACE",
+        "]":   "RIGHT_BRACE",
+        "{":   "LEFT_CURLY",
+        "}":   "RIGHT_CURLY",
+        "(":   "LEFT_PAREN",
+        ")":   "RIGHT_PAREN"
+    },
+
+    matching : function(name) {
+        return this.matchingNames[name];
+    },
+    matchingNames : {
+        "LEFT_PAREN": "RIGHT_PAREN",
+        "RIGHT_PAREN": "LEFT_PAREN",
+        "LEFT_CURLY": "RIGHT_CURLY",
+        "RIGHT_CURLY": "LEFT_CURLY",
+        "LEFT_BRACE": "RIGHT_BRACE",
+        "RIGHT_BRACE": "LEFT_BRACE"
+    },
+
+    isNumber : function(str) {
+        return /^(\.[0-9]|[0-9]+\.|[0-9])[0-9]*([eE][+-][0-9]+)?$/i.test(str);
+    },
+
+    isHexDec : function(str) {
+        return /^0x[0-9A-F]+$/i.test(str);
+    },
+
+    isWordChar : function(str) {
+        return /^[a-zA-Z0-9$_.]+$/.test(str);
+    },
+
+    isSpace : function(str) {
+        return (typeof this.whitespace(str) != "undefined");
+    },
+
+    isNewline : function(str) {
+        return (typeof this.newline(str) != "undefined");
+    }
+    
+};
\ No newline at end of file
diff --git a/JsRender/Roo.js b/JsRender/Roo.js
new file mode 100644 (file)
index 0000000..9619f72
--- /dev/null
@@ -0,0 +1,436 @@
+//<Script type="text/javascript">
+
+Gio = imports.gi.Gio;
+XObject = imports.XObject.XObject;
+
+  
+//----------------------- our roo verison
+Base = imports.JsRender.Base.Base;
+File = imports.File.File;
+
+
+//----------------------- our roo verison
+
+var rid = 0;
+
+Roo = XObject.define(
+    function(cfg) {
+        
+        // id ,
+        //"name":"Edit Module Details",
+        // items : 
+        //"btype":"FORM", // was to be components...
+        //"app":"Builder",
+        //"module":"Pman.Tab.BuilderTop2"
+        //console.dump(cfg);
+        
+        if (!cfg.name || !cfg.fullname ) {
+            cfg.name = cfg.path.split('/').pop().replace(/\.bjs$/, '');
+            //cfg.fullname = (cfg.parent && cfg.parent.length ? (cfg.parent + '.') : '' ) + cfg.name;
+            cfg.fullname = cfg.name;
+        }
+        
+        
+        this.items = false;
+        if (cfg.json) {
+            var jstr =  JSON.parse(cfg.json);
+            this.items = [ jstr ];
+            //console.log(cfg.items.length);
+            delete cfg.json; // not needed!
+        }
+        this.cn = [];
+         /*
+        var p = cfg.items && cfg.items.length && cfg.items[0].parent ? cfg.items[0].parent : false;
+        
+        // ensure real data is set...
+        Roo.apply(this, {
+            name : cfg.module,
+            parent : p,
+            title : cfg.name,
+            project : cfg.app
+            
+        });
+        
+        this.cn = [];
+        */
+        Roo.superclass.constructor.call(this, cfg);
+
+        
+        // super?!?!
+        this.id = 'roo-file-' + (rid++);
+        // various loader methods..
+    },
+    Base,
+    {
+        doubleStringProps : [ 
+            'title',
+            'legend',
+            'loadingText',
+            'emptyText',
+            'qtip',
+            'value',
+            'text'
+        ],
+        modOrder : '001', /// sequence id that this uses.
+        region : 'center',
+        parent : '',
+        title : '', // the title on displayed when loading.
+        disable : '', // use a function to that returns false to disable this..
+        permname: '', /// permission name
+        
+        setNSID : function(id)
+        {
+            
+            this.items[0]['|module'] = id;
+       
+            
+        },
+        
+        
+        getType: function() {
+            return 'Roo';
+        },
+        
+      
+        loadItems : function(cb)
+        {
+            print("load Items!");
+            if (this.items !== false) {
+                return false;
+            }
+            var file = Gio.file_new_for_path(this.path);
+            
+            var _this = this;                        
+            file.read_async(0, null, function(source,result) {
+                var stream = source.read_finish(result)
+                var dstream = new Gio.DataInputStream.c_new(stream);
+                
+                var src = dstream.read_until("")
+                
+                var cfg = JSON.parse(src);
+                print("loaded data");
+                print(JSON.stringify(cfg));
+                _this.modOrder = cfg.modOrder || '001';
+                _this.name = cfg.name.replace(/\.bjs/, ''); // BC!
+                _this.parent =  cfg.parent;
+                _this.permname =  cfg.permname || '';
+                _this.title =  cfg.title;
+                _this.items = cfg.items || []; 
+                
+                _this.fixItems(_this, false);
+                
+                
+                
+                cb();
+                 
+                
+            });
+            
+            
+            
+        },
+        /**
+         * old code had broken xtypes and used arrays differently,
+         * this code should try and clean it up..
+         * 
+         * 
+         */
+        fixItems : function(node, fixthis)
+        {
+            if (fixthis) {
+                // fix xtype.
+                var fn = this.guessName(node);
+                //print("guessname got " + fn);
+                if (fn) {
+                    var bits = fn.split('.');
+                    node.xtype = bits.pop();
+                    node['|xns'] = bits.join('.');
+                    
+                }
+                // fix array???
+                 
+                
+            }
+            if (!node.items || !node.items.length) {
+                return;
+            }
+            var _this = this;
+            var aitems = [];
+            var nitems = [];
+            node.items.forEach(function(i) {
+                
+                
+                
+                _this.fixItems(i, true);
+                if (i.xtype == 'Array') {
+                    aitems.push(i);
+                    return;
+                }    
+                nitems.push(i);
+            });
+            node.items = nitems; 
+            
+            if (!aitems.length) {
+                return;
+            }
+            
+            aitems.forEach(function(i) {
+                
+                if (!i.items || !i.items.length) {
+                    return;
+                }
+                var prop = i['*prop'] + '[]';
+                // colModel to cm?
+                i.items.forEach(function(c) {
+                    c['*prop']  = prop;
+                    node.items.push(c);
+                    
+                });
+                
+                
+            });
+            
+            
+            // array handling.. 
+            
+            
+            
+            
+            
+        },
+        
+        save : function()
+        {
+            Base.prototype.save.call(this);
+            // now write the js file..
+            var js = this.path.replace(/\.bjs$/, '.js');
+            var d = new Date();
+            var js_src = this.toSource();
+            print("TO SOURCE in " + ((new Date()) - d) + "ms");
+            File.write(js, js_src);
+            
+            
+            
+        },
+         /**
+         * convert xtype for munged output..
+         * 
+         */
+        mungeXtype : function(xtype, els)
+        {
+            var bits = xtype.split('.');
+            // assume it has lenght!
+            
+            els.push("xtype: '"+ bits.pop()+"'");
+            els.push('xns: '+ bits.join('.'));
+        },
+        
+        /**
+         * This needs to use some options on the project
+         * to determine how the file is output..
+         * 
+         * At present we are hard coding it..
+         * 
+         * 
+         */
+        toSource: function()
+        {
+            // dump the file tree back out to a string.
+            
+            // we have 2 types = dialogs and components
+            // 
+            var top = this.guessName(this.items[0]);
+            if (!top) {
+                return false;
+            }
+            if (top.match(/Dialog/)) {
+                return this.toSourceDialog();
+            }
+            return this.toSourceLayout();
+            
+            /*
+            eventually support 'classes??'
+             return this.toSourceStdClass();
+            */
+              
+        },
+       
+        outputHeader : function()
+        {
+            return [
+                "//<script type=\"text/javascript\">",
+                "",
+                "// Auto generated file - created by app.Builder.js- do not edit directly (at present!)",
+                ""
+            ].join("\n");
+            
+       
+        },
+        // a standard dialog module.
+        // fixme - this could be alot neater..
+        toSourceDialog : function() 
+        {
+            var items = JSON.parse(JSON.stringify(this.items[0]));
+            var o = this.mungeToString(items, false, '            ');   
+            return [
+                this.outputHeader(),
+                this.name + " = {",
+                "",
+                "    dialog : false,",
+                "    callback:  false,",
+                "",   
+                "    show : function(data, cb)",
+                "    {",
+                "        if (!this.dialog) {",
+                "            this.create();",
+                "        }",
+                "",
+                "        this.callback = cb;",
+                "        this.data = data;",
+                "        this.dialog.show(this.data._el);",
+                "        if (this.form) {",
+                "           this.form.reset();",
+                "           this.form.setValues(data);",
+                "           this.form.fireEvent('actioncomplete', this.form,  { type: 'setdata', data: data });",
+                "        }",
+                "",   
+                "    },",
+                "",
+                "    create : function()",
+                "    {",
+                "        var _this = this;",
+                "        this.dialog = Roo.factory(" + o +  ");",
+                "    }",
+                "};",
+                ""
+                
+             ].join("\n");
+             
+             
+             
+        },
+        // a layout compoent 
+        toSourceLayout : function() 
+        {
+            var items = JSON.parse(JSON.stringify(this.items[0]));
+            var o = this.mungeToString(items, false, '            ');   
+             
+            var modkey = this.modOrder + '-' + this.name.replace('/[^A-Z]+/ig', '-');
+            
+            
+            if (this.name.match(/^Pman/)) {
+                    
+                
+                // old BC way we did things..
+                return [
+                    this.outputHeader(),
+                    "",
+                    "",
+                    "// register the module first",
+                    "Pman.on('beforeload', function()",
+                    "{",
+                    "    Pman.register({",
+                    "        modKey : '" +modkey+"',",
+                    "        module : " + this.name + ",",
+                    "        region : '" + this.region   +"',",
+                    "        parent : " + (this.parent ||  'false') + ",",
+                    "        name : " + JSON.stringify(this.title  || "unnamed module") + ",",
+                    "        disabled : " + (this.disabled || 'false') +", ",
+                    "        permname: '" + (this.permname|| '') +"' ",
+                    "    });",
+                    "});",
+                    "",
+                    
+                    this.name  +  " = new Roo.util.Observable({",
+                    "",
+                    "    panel : false,",
+                    "    disabled : false,",
+                    "    parentLayout:  false,",
+                    "",
+                    "    add : function(parentLayout, region)",
+                    "    {",
+                    "",
+                    "        var _this = this;", // standard avaialbe..
+                    "        this.parentLayout = parentLayout;",
+                    "",
+                    "        this.panel = parentLayout.addxtype(" + o +  ");",
+                    "        this.layout = this.panel.layout;",
+                    "",
+                    "    }",
+                    "});",
+                    ""
+                     
+                    
+                 ].join("\n");
+            }
+            
+        
+            return [
+                this.outputHeader(),
+                
+                this.name  +  " = new Roo.XComponent({",
+                "    order    : '" +modkey+"',",
+                "    region   : '" + this.region   +"',",
+                "    parent   : "+ (this.parent ?  "'" + this.parent + "'" :  'false') + ",",
+                "    name     : " + JSON.stringify(this.title  || "unnamed module") + ",",
+                "    disabled : " + (this.disabled || 'false') +", ",
+                "    tree : function()",
+                "    {",
+                "        var _this = this;", // bc
+                "        var MODULE = this;", /// this looks like a better name.
+                "        return " + o + ';',
+                "    }",
+                "});",
+                ""
+                 
+             ].join("\n");
+            
+        },
+            
+        guessName : function(ar) // turns the object into full name.
+        {
+             // eg. xns: Roo, xtype: XXX -> Roo.xxx
+            if (!ar) {
+                return false;
+            }
+            var ret = [];
+            ret.push(typeof( ar['|xns'] ) == 'undefined' ? 'Roo' : ar['|xns'] );
+            
+            
+            
+            if (typeof( ar['xtype'] ) == 'undefined' || !ar['xtype'].length) {
+                return false;
+            }
+            var xtype = ar['xtype'] + '';
+            if (xtype[0] == '*') { // prefixes????
+                xtype  = xtype.substring(1);
+            }
+            if (xtype.match(/^Roo/)) {
+                // already starts with roo...
+                ret = [];
+            }
+            ret.push(xtype);
+            var str =  ret.join('.');
+            
+            
+            
+            var pm = imports.Builder.Provider.ProjectManager.ProjectManager;
+            return pm.getPalete('Roo').guessName(ret.join('.'));
+            
+                            
+                                 
+        },
+        /*
+        getTree : function( o ) {
+            
+            
+            
+        }
+        */
+         getHelpUrl : function(cls)
+        {
+            return 'http://www.akbkhome.com/roojs1/docs/symbols/' + cls + '.html';
+        }
+        
+});
\ No newline at end of file