commit extjs-2.2.1
[extjs.git] / air / samples / tasks / ext-air / ext-air.js
1 /*\r
2  * Ext JS Library 0.30\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 /*\r
10  * Ext JS Library 2.0.1\r
11  * Copyright(c) 2006-2008, Ext JS, LLC.\r
12  * licensing@extjs.com\r
13  * \r
14  * http://extjs.com/license\r
15  */\r
16 \r
17 \r
18 Ext.namespace('Ext.air', 'Ext.sql');\r
19 \r
20 Ext.Template.prototype.compile = function() {\r
21         var fm = Ext.util.Format;\r
22         var useF = this.disableFormats !== true;\r
23         
24         var prevOffset = 0;\r
25         var arr = [];\r
26         var tpl = this;\r
27         var fn = function(m, name, format, args, offset, s){\r
28                 if (prevOffset != offset) {\r
29                         var action = {type: 1, value: s.substr(prevOffset, offset - prevOffset)};\r
30                         arr.push(action);\r
31                 }\r
32                 prevOffset = offset + m.length;\r
33                 if(format && useF){\r
34                                 if (args) {\r
35                                         var re = /^\s*['"](.*)["']\s*$/;\r
36                                         args = args.split(/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/);\r
37                                         for(var i = 0, len = args.length; i < len; i++){\r
38                                                 args[i] = args[i].replace(re, "$1");\r
39                                         }\r
40                                         args = [''].concat(args);\r
41                                 } else {\r
42                                                 args = [''];\r
43                                 }\r
44                         if(format.substr(0, 5) != "this."){\r
45                                 var action = {type: 3, value:name, format: fm[format], args: args, scope: fm};\r
46                                 arr.push(action);                                       \r
47                         }else{\r
48                                 var action = {type: 3, value:name, format:tpl[format.substr(5)], args:args, scope: tpl};\r
49                                 arr.push(action);                                       \r
50                         }\r
51                 }else{\r
52                         var action  = {type: 2, value: name};\r
53                         arr.push(action);                               \r
54                 }\r
55                 return m;\r
56         };\r
57         \r
58         var s = this.html.replace(this.re, fn);\r
59         if (prevOffset != (s.length - 1)) {\r
60                 var action = {type: 1, value: s.substr(prevOffset, s.length - prevOffset)};\r
61                 arr.push(action);\r
62         }\r
63 \r
64         this.compiled = function(values) {\r
65                 function applyValues(el) {\r
66                         switch (el.type) {\r
67                                         case 1:\r
68                                                         return el.value;\r
69                                         case 2:\r
70                                                         return (values[el.value] ? values[el.value] : '');\r
71                                         default:\r
72                                                         el.args[0] = values[el.value];\r
73                                                         return el.format.apply(el.scope, el.args);\r
74                         }\r
75                 }       \r
76                 return arr.map(applyValues).join('');\r
77         }\r
78         return this;\r
79 };\r
80 \r
81 Ext.Template.prototype.call = function(fnName, value, allValues){\r
82     return this[fnName](value, allValues);\r
83 }\r
84 \r
85 \r
86 Ext.DomQuery = function(){\r
87     var cache = {}, simpleCache = {}, valueCache = {};\r
88     var nonSpace = /\S/;\r
89     var trimRe = /^\s+|\s+$/g;\r
90     var tplRe = /\{(\d+)\}/g;\r
91     var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;\r
92     var tagTokenRe = /^(#)?([\w-\*]+)/;\r
93     var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;\r
94 \r
95     function child(p, index){\r
96         var i = 0;\r
97         var n = p.firstChild;\r
98         while(n){\r
99             if(n.nodeType == 1){\r
100                if(++i == index){\r
101                    return n;\r
102                }\r
103             }\r
104             n = n.nextSibling;\r
105         }\r
106         return null;\r
107     };\r
108 \r
109     function next(n){\r
110         while((n = n.nextSibling) && n.nodeType != 1);\r
111         return n;\r
112     };\r
113 \r
114     function prev(n){\r
115         while((n = n.previousSibling) && n.nodeType != 1);\r
116         return n;\r
117     };\r
118 \r
119     function children(d){\r
120         var n = d.firstChild, ni = -1;\r
121             while(n){\r
122                 var nx = n.nextSibling;\r
123                 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){\r
124                     d.removeChild(n);\r
125                 }else{\r
126                     n.nodeIndex = ++ni;\r
127                 }\r
128                 n = nx;\r
129             }\r
130             return this;\r
131         };\r
132 \r
133     function byClassName(c, a, v){\r
134         if(!v){\r
135             return c;\r
136         }\r
137         var r = [], ri = -1, cn;\r
138         for(var i = 0, ci; ci = c[i]; i++){\r
139             if((' '+ci.className+' ').indexOf(v) != -1){\r
140                 r[++ri] = ci;\r
141             }\r
142         }\r
143         return r;\r
144     };\r
145 \r
146     function attrValue(n, attr){\r
147         if(!n.tagName && typeof n.length != "undefined"){\r
148             n = n[0];\r
149         }\r
150         if(!n){\r
151             return null;\r
152         }\r
153         if(attr == "for"){\r
154             return n.htmlFor;\r
155         }\r
156         if(attr == "class" || attr == "className"){\r
157             return n.className;\r
158         }\r
159         return n.getAttribute(attr) || n[attr];\r
160 \r
161     };\r
162 \r
163     function getNodes(ns, mode, tagName){\r
164         var result = [], ri = -1, cs;\r
165         if(!ns){\r
166             return result;\r
167         }\r
168         tagName = tagName || "*";\r
169         if(typeof ns.getElementsByTagName != "undefined"){\r
170             ns = [ns];\r
171         }\r
172         if(!mode){\r
173             for(var i = 0, ni; ni = ns[i]; i++){\r
174                 cs = ni.getElementsByTagName(tagName);\r
175                 for(var j = 0, ci; ci = cs[j]; j++){\r
176                     result[++ri] = ci;\r
177                 }\r
178             }\r
179         }else if(mode == "/" || mode == ">"){\r
180             var utag = tagName.toUpperCase();\r
181             for(var i = 0, ni, cn; ni = ns[i]; i++){\r
182                 cn = ni.children || ni.childNodes;\r
183                 for(var j = 0, cj; cj = cn[j]; j++){\r
184                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){\r
185                         result[++ri] = cj;\r
186                     }\r
187                 }\r
188             }\r
189         }else if(mode == "+"){\r
190             var utag = tagName.toUpperCase();\r
191             for(var i = 0, n; n = ns[i]; i++){\r
192                 while((n = n.nextSibling) && n.nodeType != 1);\r
193                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){\r
194                     result[++ri] = n;\r
195                 }\r
196             }\r
197         }else if(mode == "~"){\r
198             for(var i = 0, n; n = ns[i]; i++){\r
199                 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));\r
200                 if(n){\r
201                     result[++ri] = n;\r
202                 }\r
203             }\r
204         }\r
205         return result;\r
206     };\r
207 \r
208     function concat(a, b){\r
209         if(b.slice){\r
210             return a.concat(b);\r
211         }\r
212         for(var i = 0, l = b.length; i < l; i++){\r
213             a[a.length] = b[i];\r
214         }\r
215         return a;\r
216     }\r
217 \r
218     function byTag(cs, tagName){\r
219         if(cs.tagName || cs == document){\r
220             cs = [cs];\r
221         }\r
222         if(!tagName){\r
223             return cs;\r
224         }\r
225         var r = [], ri = -1;\r
226         tagName = tagName.toLowerCase();\r
227         for(var i = 0, ci; ci = cs[i]; i++){\r
228             if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){\r
229                 r[++ri] = ci;\r
230             }\r
231         }\r
232         return r;\r
233     };\r
234 \r
235     function byId(cs, attr, id){\r
236         if(cs.tagName || cs == document){\r
237             cs = [cs];\r
238         }\r
239         if(!id){\r
240             return cs;\r
241         }\r
242         var r = [], ri = -1;\r
243         for(var i = 0,ci; ci = cs[i]; i++){\r
244             if(ci && ci.id == id){\r
245                 r[++ri] = ci;\r
246                 return r;\r
247             }\r
248         }\r
249         return r;\r
250     };\r
251 \r
252     function byAttribute(cs, attr, value, op, custom){\r
253         var r = [], ri = -1, st = custom=="{";\r
254         var f = Ext.DomQuery.operators[op];\r
255         for(var i = 0, ci; ci = cs[i]; i++){\r
256             var a;\r
257             if(st){\r
258                 a = Ext.DomQuery.getStyle(ci, attr);\r
259             }\r
260             else if(attr == "class" || attr == "className"){\r
261                 a = ci.className;\r
262             }else if(attr == "for"){\r
263                 a = ci.htmlFor;\r
264             }else if(attr == "href"){\r
265                 a = ci.getAttribute("href", 2);\r
266             }else{\r
267                 a = ci.getAttribute(attr);\r
268             }\r
269             if((f && f(a, value)) || (!f && a)){\r
270                 r[++ri] = ci;\r
271             }\r
272         }\r
273         return r;\r
274     };\r
275 \r
276     function byPseudo(cs, name, value){\r
277         return Ext.DomQuery.pseudos[name](cs, value);\r
278     };\r
279 \r
280  \r
281     
282     
283     eval("var batch = 30803;");\r
284 \r
285     var key = 30803;\r
286 \r
287     function nodup(cs){\r
288         if(!cs){\r
289             return [];\r
290         }\r
291         var len = cs.length, c, i, r = cs, cj, ri = -1;\r
292         if(!len || typeof cs.nodeType != "undefined" || len == 1){\r
293             return cs;\r
294         }\r
295         var d = ++key;\r
296         cs[0]._nodup = d;\r
297         for(i = 1; c = cs[i]; i++){\r
298             if(c._nodup != d){\r
299                 c._nodup = d;\r
300             }else{\r
301                 r = [];\r
302                 for(var j = 0; j < i; j++){\r
303                     r[++ri] = cs[j];\r
304                 }\r
305                 for(j = i+1; cj = cs[j]; j++){\r
306                     if(cj._nodup != d){\r
307                         cj._nodup = d;\r
308                         r[++ri] = cj;\r
309                     }\r
310                 }\r
311                 return r;\r
312             }\r
313         }\r
314         return r;\r
315     }\r
316 \r
317     function quickDiff(c1, c2){\r
318         var len1 = c1.length;\r
319         if(!len1){\r
320             return c2;\r
321         }\r
322         var d = ++key;\r
323         for(var i = 0; i < len1; i++){\r
324             c1[i]._qdiff = d;\r
325         }\r
326         var r = [];\r
327         for(var i = 0, len = c2.length; i < len; i++){\r
328             if(c2[i]._qdiff != d){\r
329                 r[r.length] = c2[i];\r
330             }\r
331         }\r
332         return r;\r
333     }\r
334 \r
335     function quickId(ns, mode, root, id){\r
336         if(ns == root){\r
337            var d = root.ownerDocument || root;\r
338            return d.getElementById(id);\r
339         }\r
340         ns = getNodes(ns, mode, "*");\r
341             return byId(ns, null, id);\r
342     }\r
343 \r
344        function search(path, root, type) {\r
345                     type = type || "select";\r
346             
347             var n = root || document;\r
348             
349             var q = path, mode, lq;\r
350             var tk = Ext.DomQuery.matchers;\r
351             var tklen = tk.length;\r
352             var mm;\r
353 \r
354             var lmode = q.match(modeRe);\r
355             if(lmode && lmode[1]){\r
356                 mode=lmode[1].replace(trimRe, "");\r
357                 q = q.replace(lmode[1], "");\r
358             }\r
359             while(path.substr(0, 1)=="/"){\r
360                 path = path.substr(1);\r
361             }\r
362             while(q && lq != q){\r
363                 lq = q;\r
364                 var tm = q.match(tagTokenRe);\r
365                 if(type == "select"){\r
366                     if(tm){\r
367                         if(tm[1] == "#"){\r
368                             n = quickId(n, mode, root, tm[2]);\r
369                         }else{\r
370                             n = getNodes(n, mode, tm[2]);\r
371                         }\r
372                         q = q.replace(tm[0], "");\r
373                     }else if(q.substr(0, 1) != '@'){\r
374                         n = getNodes(n, mode, "*");\r
375                     }\r
376                 }else{\r
377                     if(tm){\r
378                         if(tm[1] == "#"){\r
379                             n = byId(n, null, tm[2]);\r
380                         }else{\r
381                             n = byTag(n, tm[2]);\r
382                         }\r
383                         q = q.replace(tm[0], "");\r
384                     }\r
385                 }\r
386                 while(!(mm = q.match(modeRe))){\r
387                     var matched = false;\r
388                     for(var j = 0; j < tklen; j++){\r
389                         var t = tk[j];\r
390                         var m = q.match(t.re);\r
391                         if(m){\r
392                             switch(j) {\r
393                                 case 0:\r
394                                     n = byClassName(n, null, " " + m[1] +" ");\r
395                                     break;\r
396                                 case 1:\r
397                                     n = byPseudo(n, m[1], m[2]);\r
398                                     break;\r
399                                 case 2:\r
400                                     n = byAttribute(n, m[2], m[4], m[3], m[1]);\r
401                                     break;\r
402                                 case 3:\r
403                                     n = byId(n, null, m[1]);\r
404                                     break;\r
405                                 case 4:\r
406                                     return {firstChild:{nodeValue:attrValue(n, m[1])}};\r
407                                     \r
408                             }\r
409                             q = q.replace(m[0], "");\r
410                             matched = true;\r
411                             break;\r
412                         }\r
413                     }\r
414 \r
415                     if(!matched){\r
416                         throw 'Error parsing selector, parsing failed at "' + q + '"';\r
417                     }\r
418                 }\r
419                 if(mm[1]){\r
420                     mode=mm[1].replace(trimRe, "");\r
421                     q = q.replace(mm[1], "");\r
422                 }\r
423             }\r
424             return nodup(n);\r
425         }               \r
426 \r
427      return {\r
428         getStyle : function(el, name){\r
429              return Ext.fly(el).getStyle(name);\r
430         },\r
431                 \r
432                 compile: function(path, type) {\r
433                         return function(root) {\r
434                                         return search(path, root, type);\r
435                         }\r
436                 },\r
437 \r
438         \r
439         select : function(path, root, type){\r
440             if(!root || root == document){\r
441                 root = document;\r
442             }\r
443             if(typeof root == "string"){\r
444                 root = document.getElementById(root);\r
445             }\r
446             var paths = path.split(",");\r
447             var results = [];\r
448             for(var i = 0, len = paths.length; i < len; i++){\r
449                 var p = paths[i].replace(trimRe, "");\r
450                 if(!cache[p]){\r
451                     cache[p] = Ext.DomQuery.compile(p);\r
452                     if(!cache[p]){\r
453                         throw p + " is not a valid selector";\r
454                     }\r
455                 }\r
456                 var result = cache[p](root);\r
457                 if(result && result != document){\r
458                     results = results.concat(result);\r
459                 }\r
460             }\r
461             if(paths.length > 1){\r
462                 return nodup(results);\r
463             }\r
464             return results;\r
465         },\r
466 \r
467         \r
468         selectNode : function(path, root){\r
469             return Ext.DomQuery.select(path, root)[0];\r
470         },\r
471 \r
472         \r
473         selectValue : function(path, root, defaultValue){\r
474             path = path.replace(trimRe, "");\r
475             if(!valueCache[path]){\r
476                 valueCache[path] = Ext.DomQuery.compile(path, "select");\r
477             }\r
478             var n = valueCache[path](root);\r
479             n = n[0] ? n[0] : n;\r
480             var v = (n && n.firstChild ? n.firstChild.nodeValue : null);\r
481             return ((v === null||v === undefined||v==='') ? defaultValue : v);\r
482         },\r
483 \r
484         \r
485         selectNumber : function(path, root, defaultValue){\r
486             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);\r
487             return parseFloat(v);\r
488         },\r
489 \r
490         \r
491         is : function(el, ss){\r
492             if(typeof el == "string"){\r
493                 el = document.getElementById(el);\r
494             }\r
495             var isArray = Ext.isArray(el);\r
496             var result = Ext.DomQuery.filter(isArray ? el : [el], ss);\r
497             return isArray ? (result.length == el.length) : (result.length > 0);\r
498         },\r
499 \r
500         \r
501         filter : function(els, ss, nonMatches){\r
502             ss = ss.replace(trimRe, "");\r
503             if(!simpleCache[ss]){\r
504                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");\r
505             }\r
506             var result = simpleCache[ss](els);\r
507             return nonMatches ? quickDiff(result, els) : result;\r
508         },\r
509 \r
510         \r
511         matchers : [{\r
512                 re: /^\.([\w-]+)/,\r
513                 select: 'n = byClassName(n, null, " {1} ");'\r
514             }, {\r
515                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,\r
516                 select: 'n = byPseudo(n, "{1}", "{2}");'\r
517             },{\r
518                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,\r
519                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'\r
520             }, {\r
521                 re: /^#([\w-]+)/,\r
522                 select: 'n = byId(n, null, "{1}");'\r
523             },{\r
524                 re: /^@([\w-]+)/,\r
525                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'\r
526             }\r
527         ],\r
528 \r
529         \r
530         operators : {\r
531             "=" : function(a, v){\r
532                 return a == v;\r
533             },\r
534             "!=" : function(a, v){\r
535                 return a != v;\r
536             },\r
537             "^=" : function(a, v){\r
538                 return a && a.substr(0, v.length) == v;\r
539             },\r
540             "$=" : function(a, v){\r
541                 return a && a.substr(a.length-v.length) == v;\r
542             },\r
543             "*=" : function(a, v){\r
544                 return a && a.indexOf(v) !== -1;\r
545             },\r
546             "%=" : function(a, v){\r
547                 return (a % v) == 0;\r
548             },\r
549             "|=" : function(a, v){\r
550                 return a && (a == v || a.substr(0, v.length+1) == v+'-');\r
551             },\r
552             "~=" : function(a, v){\r
553                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;\r
554             }\r
555         },\r
556 \r
557         \r
558         pseudos : {\r
559             "first-child" : function(c){\r
560                 var r = [], ri = -1, n;\r
561                 for(var i = 0, ci; ci = n = c[i]; i++){\r
562                     while((n = n.previousSibling) && n.nodeType != 1);\r
563                     if(!n){\r
564                         r[++ri] = ci;\r
565                     }\r
566                 }\r
567                 return r;\r
568             },\r
569 \r
570             "last-child" : function(c){\r
571                 var r = [], ri = -1, n;\r
572                 for(var i = 0, ci; ci = n = c[i]; i++){\r
573                     while((n = n.nextSibling) && n.nodeType != 1);\r
574                     if(!n){\r
575                         r[++ri] = ci;\r
576                     }\r
577                 }\r
578                 return r;\r
579             },\r
580 \r
581             "nth-child" : function(c, a) {\r
582                 var r = [], ri = -1;\r
583                 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);\r
584                 var f = (m[1] || 1) - 0, l = m[2] - 0;\r
585                 for(var i = 0, n; n = c[i]; i++){\r
586                     var pn = n.parentNode;\r
587                     if (batch != pn._batch) {\r
588                         var j = 0;\r
589                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){\r
590                             if(cn.nodeType == 1){\r
591                                cn.nodeIndex = ++j;\r
592                             }\r
593                         }\r
594                         pn._batch = batch;\r
595                     }\r
596                     if (f == 1) {\r
597                         if (l == 0 || n.nodeIndex == l){\r
598                             r[++ri] = n;\r
599                         }\r
600                     } else if ((n.nodeIndex + l) % f == 0){\r
601                         r[++ri] = n;\r
602                     }\r
603                 }\r
604 \r
605                 return r;\r
606             },\r
607 \r
608             "only-child" : function(c){\r
609                 var r = [], ri = -1;;\r
610                 for(var i = 0, ci; ci = c[i]; i++){\r
611                     if(!prev(ci) && !next(ci)){\r
612                         r[++ri] = ci;\r
613                     }\r
614                 }\r
615                 return r;\r
616             },\r
617 \r
618             "empty" : function(c){\r
619                 var r = [], ri = -1;\r
620                 for(var i = 0, ci; ci = c[i]; i++){\r
621                     var cns = ci.childNodes, j = 0, cn, empty = true;\r
622                     while(cn = cns[j]){\r
623                         ++j;\r
624                         if(cn.nodeType == 1 || cn.nodeType == 3){\r
625                             empty = false;\r
626                             break;\r
627                         }\r
628                     }\r
629                     if(empty){\r
630                         r[++ri] = ci;\r
631                     }\r
632                 }\r
633                 return r;\r
634             },\r
635 \r
636             "contains" : function(c, v){\r
637                 var r = [], ri = -1;\r
638                 for(var i = 0, ci; ci = c[i]; i++){\r
639                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){\r
640                         r[++ri] = ci;\r
641                     }\r
642                 }\r
643                 return r;\r
644             },\r
645 \r
646             "nodeValue" : function(c, v){\r
647                 var r = [], ri = -1;\r
648                 for(var i = 0, ci; ci = c[i]; i++){\r
649                     if(ci.firstChild && ci.firstChild.nodeValue == v){\r
650                         r[++ri] = ci;\r
651                     }\r
652                 }\r
653                 return r;\r
654             },\r
655 \r
656             "checked" : function(c){\r
657                 var r = [], ri = -1;\r
658                 for(var i = 0, ci; ci = c[i]; i++){\r
659                     if(ci.checked == true){\r
660                         r[++ri] = ci;\r
661                     }\r
662                 }\r
663                 return r;\r
664             },\r
665 \r
666             "not" : function(c, ss){\r
667                 return Ext.DomQuery.filter(c, ss, true);\r
668             },\r
669 \r
670             "any" : function(c, selectors){\r
671                 var ss = selectors.split('|');\r
672                 var r = [], ri = -1, s;\r
673                 for(var i = 0, ci; ci = c[i]; i++){\r
674                     for(var j = 0; s = ss[j]; j++){\r
675                         if(Ext.DomQuery.is(ci, s)){\r
676                             r[++ri] = ci;\r
677                             break;\r
678                         }\r
679                     }\r
680                 }\r
681                 return r;\r
682             },\r
683 \r
684             "odd" : function(c){\r
685                 return this["nth-child"](c, "odd");\r
686             },\r
687 \r
688             "even" : function(c){\r
689                 return this["nth-child"](c, "even");\r
690             },\r
691 \r
692             "nth" : function(c, a){\r
693                 return c[a-1] || [];\r
694             },\r
695 \r
696             "first" : function(c){\r
697                 return c[0] || [];\r
698             },\r
699 \r
700             "last" : function(c){\r
701                 return c[c.length-1] || [];\r
702             },\r
703 \r
704             "has" : function(c, ss){\r
705                 var s = Ext.DomQuery.select;\r
706                 var r = [], ri = -1;\r
707                 for(var i = 0, ci; ci = c[i]; i++){\r
708                     if(s(ss, ci).length > 0){\r
709                         r[++ri] = ci;\r
710                     }\r
711                 }\r
712                 return r;\r
713             },\r
714 \r
715             "next" : function(c, ss){\r
716                 var is = Ext.DomQuery.is;\r
717                 var r = [], ri = -1;\r
718                 for(var i = 0, ci; ci = c[i]; i++){\r
719                     var n = next(ci);\r
720                     if(n && is(n, ss)){\r
721                         r[++ri] = ci;\r
722                     }\r
723                 }\r
724                 return r;\r
725             },\r
726 \r
727             "prev" : function(c, ss){\r
728                 var is = Ext.DomQuery.is;\r
729                 var r = [], ri = -1;\r
730                 for(var i = 0, ci; ci = c[i]; i++){\r
731                     var n = prev(ci);\r
732                     if(n && is(n, ss)){\r
733                         r[++ri] = ci;\r
734                     }\r
735                 }\r
736                 return r;\r
737             }\r
738         }\r
739     };\r
740 }();\r
741 \r
742 Ext.query = Ext.DomQuery.select;\r
743 \r
744 Date.precompileFormats = function(s){\r
745         var formats = s.split('|');\r
746         for(var i = 0, len = formats.length;i < len;i++){\r
747                 Date.createNewFormat(formats[i]);\r
748                 Date.createParser(formats[i]);\r
749         }\r
750 }\r
751 \r
752 Date.precompileFormats("D n/j/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|YmdHis|F d, Y|l, F d, Y|H:i:s|g:i A|g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|m/d/y|m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|Y-m-d H:i:s|d/m/y|d/m/Y|d-m-y|d-m-Y|d/m|d-m|dm|dmy|dmY|Y-m-d|l|D m/d|D m/d/Y|m/d/Y");\r
753 \r
754
755 Ext.ColorPalette.prototype.tpl = new Ext.XTemplate(\r
756     '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'\r
757 );\r
758 \r
759 \r
760 \r
761 \r
762 \r
763
764 \r
765 Ext.air.FileProvider = function(config){\r
766     Ext.air.FileProvider.superclass.constructor.call(this);\r
767         \r
768         this.defaultState = {\r
769                 mainWindow : {\r
770                         width:780,\r
771                         height:580,\r
772                         x:10,\r
773                         y:10\r
774                 }\r
775         };\r
776         \r
777     Ext.apply(this, config);\r
778     this.state = this.readState();\r
779         \r
780         var provider = this;\r
781         air.NativeApplication.nativeApplication.addEventListener('exiting', function(){\r
782                 provider.saveState();\r
783         });\r
784 };\r
785 \r
786 Ext.extend(Ext.air.FileProvider, Ext.state.Provider, {\r
787         file: 'extstate.data',\r
788         \r
789         
790     readState : function(){\r
791                 var stateFile = air.File.applicationStorageDirectory.resolvePath(this.file);\r
792                 if(!stateFile.exists){\r
793                         return this.defaultState || {};\r
794                 }\r
795                 \r
796                 var stream = new air.FileStream();\r
797                 stream.open(stateFile, air.FileMode.READ);\r
798                 \r
799                 var stateData = stream.readObject();\r
800                 stream.close();\r
801                 \r
802                 return stateData || this.defaultState || {};\r
803     },\r
804 \r
805     
806     saveState : function(name, value){\r
807         var stateFile = air.File.applicationStorageDirectory.resolvePath(this.file);\r
808                 var stream = new air.FileStream();\r
809                 stream.open(stateFile, air.FileMode.WRITE);\r
810                 stream.writeObject(this.state);\r
811                 stream.close();\r
812     }\r
813 });
814 Ext.air.NativeObservable = Ext.extend(Ext.util.Observable, {\r
815         addListener : function(name){\r
816                 this.proxiedEvents = this.proxiedEvents || {};\r
817                 if(!this.proxiedEvents[name]){\r
818                         var instance = this;\r
819                         var f = function(){\r
820                                 var args = Array.prototype.slice.call(arguments, 0);\r
821                                 args.unshift(name);\r
822                                 instance.fireEvent.apply(instance, args);\r
823                         };\r
824                         this.proxiedEvents[name] = f;\r
825                         this.getNative().addEventListener(name, f);\r
826                 }\r
827                 Ext.air.NativeObservable.superclass.addListener.apply(this, arguments);\r
828         }\r
829 });\r
830 \r
831 Ext.air.NativeObservable.prototype.on = Ext.air.NativeObservable.prototype.addListener;
832 \r
833 Ext.air.NativeWindow = function(config){\r
834         Ext.apply(this, config);\r
835         \r
836         this.id = this.id || Ext.uniqueId();\r
837         \r
838         this.addEvents(\r
839                 'close', \r
840                 'closing',\r
841                 'move',\r
842                 'moving',\r
843                 'resize',\r
844                 'resizing',\r
845                 'displayStateChange',\r
846                 'displayStateChanging'\r
847         );\r
848         \r
849         Ext.air.NativeWindow.superclass.constructor.call(this);\r
850         \r
851         if(!this.instance){\r
852                 var options = new air.NativeWindowInitOptions();\r
853                 options.systemChrome = this.chrome;\r
854                 options.type = this.type;\r
855                 options.resizable = this.resizable;\r
856                 options.minimizable = this.minimizable;\r
857                 options.maximizable = this.maximizable;\r
858                 options.transparent = this.transparent;\r
859                 \r
860                 this.loader = window.runtime.flash.html.HTMLLoader.createRootWindow(false, options, false);\r
861                 this.loader.load(new air.URLRequest(this.file));\r
862         \r
863                 this.instance = this.loader.window.nativeWindow;\r
864         }else{\r
865                 this.loader = this.instance.stage.getChildAt(0);\r
866         }\r
867         \r
868         var provider = Ext.state.Manager;\r
869         var b = air.Screen.mainScreen.visibleBounds;\r
870         \r
871         var state = provider.get(this.id) || {};\r
872         provider.set(this.id, state);\r
873                 \r
874         var win = this.instance;\r
875         \r
876         var width = Math.max(state.width || this.width, 100);\r
877         var height = Math.max(state.height || this.height, 100);\r
878         \r
879         var centerX = b.x + ((b.width/2)-(width/2));\r
880         var centerY = b.y + ((b.height/2)-(height/2));\r
881         \r
882         var x = !Ext.isEmpty(state.x, false) ? state.x : (!Ext.isEmpty(this.x, false) ? this.x : centerX);\r
883         var y = !Ext.isEmpty(state.y, false) ? state.y : (!Ext.isEmpty(this.y, false) ? this.y : centerY);\r
884         \r
885         win.width = width;\r
886         win.height = height;\r
887         win.x = x;\r
888         win.y = y;\r
889         \r
890         win.addEventListener('move', function(){\r
891                 if(win.displayState != air.NativeWindowDisplayState.MINIMIZED && win.width > 100 && win.height > 100) {\r
892                         state.x = win.x;\r
893                         state.y = win.y;\r
894                 }\r
895         });     \r
896         win.addEventListener('resize', function(){\r
897                 if (win.displayState != air.NativeWindowDisplayState.MINIMIZED && win.width > 100 && win.height > 100) {\r
898                         state.width = win.width;\r
899                         state.height = win.height;\r
900                 }\r
901         });\r
902         \r
903         Ext.air.NativeWindowManager.register(this);\r
904         this.on('close', this.unregister, this);\r
905         \r
906         if(this.minimizeToTray){\r
907                 this.initMinimizeToTray(this.trayIcon, this.trayMenu);\r
908         }\r
909         \r
910 };\r
911 \r
912 Ext.extend(Ext.air.NativeWindow, Ext.air.NativeObservable, {\r
913         chrome: 'standard', 
914         type: 'normal', 
915         width:600,\r
916         height:400,\r
917         resizable: true,\r
918         minimizable: true,\r
919         maximizable: true,\r
920         transparent: false,\r
921         \r
922         getNative : function(){\r
923                 return this.instance;\r
924         },\r
925         \r
926         getCenterXY : function(){\r
927                 var b = air.Screen.mainScreen.visibleBounds;\r
928                 return {\r
929                         x: b.x + ((b.width/2)-(this.width/2)),\r
930                         y: b.y + ((b.height/2)-(this.height/2))\r
931                 };\r
932         },\r
933         \r
934         show :function(){\r
935                 if(this.trayed){\r
936                         Ext.air.SystemTray.hideIcon();\r
937                         this.trayed = false;\r
938                 }\r
939                 this.instance.visible = true;\r
940         },\r
941         \r
942         activate : function(){\r
943                 this.show();\r
944                 this.instance.activate();\r
945         },\r
946         \r
947         hide :function(){\r
948                 this.instance.visible = false;\r
949         },\r
950         \r
951         close : function(){\r
952                 this.instance.close();  \r
953         },\r
954         \r
955         isMinimized :function(){\r
956                 return this.instance.displayState == air.NativeWindowDisplayState.MINIMIZED;\r
957         },\r
958         \r
959         isMaximized :function(){\r
960                 return this.instance.displayState == air.NativeWindowDisplayState.MAXIMIZED;\r
961         },\r
962         \r
963         moveTo : function(x, y){\r
964                 this.x = this.instance.x = x;\r
965                 this.y = this.instance.y = y;   \r
966         },\r
967         \r
968         resize : function(width, height){\r
969                 this.width = this.instance.width = width;\r
970                 this.height = this.instance.height = height;    \r
971         },\r
972         \r
973         unregister : function(){\r
974                 Ext.air.NativeWindowManager.unregister(this);\r
975         },\r
976         \r
977         initMinimizeToTray : function(icon, menu){\r
978                 var tray = Ext.air.SystemTray;\r
979                 tray.setIcon(icon, this.trayTip);\r
980                 this.on('displayStateChanging', function(e){\r
981                         if(e.afterDisplayState == 'minimized'){\r
982                                 e.preventDefault();\r
983                                 this.hide();\r
984                                 tray.showIcon();\r
985                                 this.trayed = true;\r
986                         }\r
987                 }, this);\r
988                 \r
989                 tray.on('click', function(){\r
990                         this.activate();\r
991                 }, this);\r
992                 \r
993                 if(menu){\r
994                         tray.setMenu(menu);\r
995                 }\r
996         }\r
997 });\r
998 \r
999 Ext.air.NativeWindow.getRootWindow = function(){\r
1000         return air.NativeApplication.nativeApplication.openedWindows[0];\r
1001 };\r
1002 \r
1003 Ext.air.NativeWindow.getRootHtmlWindow = function(){\r
1004         return Ext.air.NativeWindow.getRootWindow().stage.getChildAt(0).window;\r
1005 };\r
1006 \r
1007 Ext.air.NativeWindowGroup = function(){\r
1008     var list = {};\r
1009 \r
1010     return {\r
1011         register : function(win){\r
1012             list[win.id] = win;\r
1013         },\r
1014 \r
1015         unregister : function(win){\r
1016             delete list[win.id];\r
1017         },\r
1018 \r
1019         get : function(id){\r
1020             return list[id];\r
1021         },\r
1022 \r
1023         closeAll : function(){\r
1024             for(var id in list){\r
1025                 if(list.hasOwnProperty(id)){\r
1026                     list[id].close();\r
1027                 }\r
1028             }\r
1029         },\r
1030 \r
1031         \r
1032         each : function(fn, scope){\r
1033             for(var id in list){\r
1034                 if(list.hasOwnProperty(id)){\r
1035                     if(fn.call(scope || list[id], list[id]) === false){\r
1036                         return;\r
1037                     }\r
1038                 }\r
1039             }\r
1040         }\r
1041     };\r
1042 };\r
1043 \r
1044 \r
1045 Ext.air.NativeWindowManager = new Ext.air.NativeWindowGroup();
1046
1047 Ext.sql.Connection = function(config){\r
1048         Ext.apply(this, config);\r
1049         Ext.sql.Connection.superclass.constructor.call(this);\r
1050 \r
1051         this.addEvents({\r
1052                 open : true,\r
1053                 close: true\r
1054         });\r
1055 };\r
1056 \r
1057 Ext.extend(Ext.sql.Connection, Ext.util.Observable, {\r
1058         maxResults: 10000,\r
1059         openState : false,\r
1060 \r
1061     
1062     open : function(file){\r
1063         },\r
1064 \r
1065         close : function(){\r
1066         },\r
1067 \r
1068     exec : function(sql){\r
1069         },\r
1070 \r
1071         execBy : function(sql, args){\r
1072         },\r
1073 \r
1074         query : function(sql){\r
1075         },\r
1076 \r
1077         queryBy : function(sql, args){\r
1078         },\r
1079 \r
1080     
1081     isOpen : function(){\r
1082                 return this.openState;\r
1083         },\r
1084 \r
1085         getTable : function(name, keyName){\r
1086                 return new Ext.sql.Table(this, name, keyName);\r
1087         },\r
1088 \r
1089         createTable : function(o){\r
1090                 var tableName = o.name;\r
1091                 var keyName = o.key;\r
1092                 var fs = o.fields;\r
1093                 if(!Ext.isArray(fs)){ 
1094                         fs = fs.items;\r
1095                 }\r
1096                 var buf = [];\r
1097                 for(var i = 0, len = fs.length; i < len; i++){\r
1098                         var f = fs[i], s = f.name;\r
1099                         switch(f.type){\r
1100                     case "int":\r
1101                     case "bool":\r
1102                     case "boolean":\r
1103                         s += ' INTEGER';\r
1104                         break;\r
1105                     case "float":\r
1106                         s += ' REAL';\r
1107                         break;\r
1108                     default:\r
1109                         s += ' TEXT';\r
1110                 }\r
1111                 if(f.allowNull === false || f.name == keyName){\r
1112                         s += ' NOT NULL';\r
1113                 }\r
1114                 if(f.name == keyName){\r
1115                         s += ' PRIMARY KEY';\r
1116                 }\r
1117                 if(f.unique === true){\r
1118                         s += ' UNIQUE';\r
1119                 }\r
1120 \r
1121                 buf[buf.length] = s;\r
1122             }\r
1123             var sql = ['CREATE TABLE IF NOT EXISTS ', tableName, ' (', buf.join(','), ')'].join('');\r
1124         this.exec(sql);\r
1125         }\r
1126 });\r
1127 \r
1128 \r
1129 Ext.sql.Connection.getInstance = function(db, config){\r
1130     if(Ext.isAir){ 
1131         return new Ext.sql.AirConnection(config);\r
1132     } else { 
1133         return new Ext.sql.GearsConnection(config);\r
1134     }\r
1135 };
1136 Ext.sql.Table = function(conn, name, keyName){\r
1137         this.conn = conn;\r
1138         this.name = name;\r
1139         this.keyName = keyName;\r
1140 };\r
1141 \r
1142 Ext.sql.Table.prototype = {\r
1143         update : function(o){\r
1144                 var clause = this.keyName + " = ?";\r
1145                 return this.updateBy(o, clause, [o[this.keyName]]);\r
1146         },\r
1147 \r
1148         updateBy : function(o, clause, args){\r
1149                 var sql = "UPDATE " + this.name + " set ";\r
1150                 var fs = [], a = [];\r
1151                 for(var key in o){\r
1152                         if(o.hasOwnProperty(key)){\r
1153                                 fs[fs.length] = key + ' = ?';\r
1154                                 a[a.length] = o[key];\r
1155                         }\r
1156                 }\r
1157                 for(var key in args){\r
1158                         if(args.hasOwnProperty(key)){\r
1159                                 a[a.length] = args[key];\r
1160                         }\r
1161                 }\r
1162                 sql = [sql, fs.join(','), ' WHERE ', clause].join('');\r
1163                 return this.conn.execBy(sql, a);\r
1164         },\r
1165 \r
1166         insert : function(o){\r
1167                 var sql = "INSERT into " + this.name + " ";\r
1168                 var fs = [], vs = [], a = [];\r
1169                 for(var key in o){\r
1170                         if(o.hasOwnProperty(key)){\r
1171                                 fs[fs.length] = key;\r
1172                                 vs[vs.length] = '?';\r
1173                                 a[a.length] = o[key];\r
1174                         }\r
1175                 }\r
1176                 sql = [sql, '(', fs.join(','), ') VALUES (', vs.join(','), ')'].join('');\r
1177         return this.conn.execBy(sql, a);\r
1178     },\r
1179 \r
1180         lookup : function(id){\r
1181                 return this.selectBy('where ' + this.keyName + " = ?", [id])[0] || null;\r
1182         },\r
1183 \r
1184         exists : function(id){\r
1185                 return !!this.lookup(id);\r
1186         },\r
1187 \r
1188         save : function(o){\r
1189                 if(this.exists(o[this.keyName])){\r
1190             this.update(o);\r
1191         }else{\r
1192             this.insert(o);\r
1193         }\r
1194         },\r
1195 \r
1196         select : function(clause){\r
1197                 return this.selectBy(clause, null);\r
1198         },\r
1199 \r
1200         selectBy : function(clause, args){\r
1201                 var sql = "select * from " + this.name;\r
1202                 if(clause){\r
1203                         sql += ' ' + clause;\r
1204                 }\r
1205                 args = args || {};\r
1206                 return this.conn.queryBy(sql, args);\r
1207         },\r
1208 \r
1209         remove : function(clause){\r
1210                 this.deleteBy(clause, null);\r
1211         },\r
1212 \r
1213         removeBy : function(clause, args){\r
1214                 var sql = "delete from " + this.name;\r
1215                 if(clause){\r
1216                         sql += ' where ' + clause;\r
1217                 }\r
1218                 args = args || {};\r
1219                 this.conn.execBy(sql, args);\r
1220         }\r
1221 };
1222 Ext.sql.Proxy = function(conn, table, keyName, store, readonly){\r
1223     Ext.sql.Proxy.superclass.constructor.call(this);\r
1224     this.conn = conn;\r
1225     this.table = this.conn.getTable(table, keyName);\r
1226     this.store = store;\r
1227 \r
1228         if (readonly !== true) {\r
1229                 this.store.on('add', this.onAdd, this);\r
1230                 this.store.on('update', this.onUpdate, this);\r
1231                 this.store.on('remove', this.onRemove, this);\r
1232         }\r
1233 };\r
1234 \r
1235 Ext.sql.Proxy.DATE_FORMAT = 'Y-m-d H:i:s';\r
1236 \r
1237 Ext.extend(Ext.sql.Proxy, Ext.data.DataProxy, {\r
1238     load : function(params, reader, callback, scope, arg){\r
1239         if(!this.conn.isOpen()){ 
1240                 this.conn.on('open', function(){\r
1241                         this.load(params, reader, callback, scope, arg);\r
1242                 }, this, {single:true});\r
1243                 return;\r
1244         };\r
1245         if(this.fireEvent("beforeload", this, params, reader, callback, scope, arg) !== false){\r
1246                         var clause = params.where || '';\r
1247                         var args = params.args || [];\r
1248                         var group = params.groupBy;\r
1249                         var sort = params.sort;\r
1250                         var dir = params.dir;\r
1251 \r
1252                         if(group || sort){\r
1253                                 clause += ' ORDER BY ';\r
1254                                 if(group && group != sort){\r
1255                                         clause += group + ' ASC, ';\r
1256                                 }\r
1257                                 clause += sort + ' ' + (dir || 'ASC');\r
1258                         }\r
1259 \r
1260                         var rs = this.table.selectBy(clause, args);\r
1261                         this.onLoad({callback:callback, scope:scope, arg:arg, reader: reader}, rs);\r
1262         }else{\r
1263             callback.call(scope||this, null, arg, false);\r
1264         }\r
1265     },\r
1266 \r
1267     onLoad : function(trans, rs, e, stmt){\r
1268         if(rs === false){\r
1269                 this.fireEvent("loadexception", this, null, trans.arg, e);\r
1270             trans.callback.call(trans.scope||window, null, trans.arg, false);\r
1271             return;\r
1272         }\r
1273         var result = trans.reader.readRecords(rs);\r
1274         this.fireEvent("load", this, rs, trans.arg);\r
1275         trans.callback.call(trans.scope||window, result, trans.arg, true);\r
1276     },\r
1277 \r
1278     processData : function(o){\r
1279         var fs = this.store.fields;\r
1280         var r = {};\r
1281         for(var key in o){\r
1282                 var f = fs.key(key), v = o[key];\r
1283                         if(f){\r
1284                                 if(f.type == 'date'){\r
1285                                         r[key] = v ? v.format(Ext.sql.Proxy.DATE_FORMAT,10) : '';\r
1286                                 }else if(f.type == 'boolean'){\r
1287                                         r[key] = v ? 1 : 0;\r
1288                                 }else{\r
1289                                         r[key] = v;\r
1290                                 }\r
1291                         }\r
1292                 }\r
1293                 return r;\r
1294     },\r
1295 \r
1296     onUpdate : function(ds, record){\r
1297         var changes = record.getChanges();\r
1298         var kn = this.table.keyName;\r
1299         this.table.updateBy(this.processData(changes), kn + ' = ?', [record.data[kn]]);\r
1300         record.commit(true);\r
1301     },\r
1302 \r
1303     onAdd : function(ds, records, index){\r
1304         for(var i = 0, len = records.length; i < len; i++){\r
1305                 this.table.insert(this.processData(records[i].data));\r
1306         }\r
1307     },\r
1308 \r
1309     onRemove : function(ds, record, index){\r
1310                 var kn = this.table.keyName;\r
1311         this.table.removeBy(kn + ' = ?', [record.data[kn]]);\r
1312     }\r
1313 });
1314  Ext.sql.AirConnection = Ext.extend(Ext.sql.Connection, {\r
1315         
1316     open : function(db){\r
1317         this.conn = new air.SQLConnection();\r
1318                 var file = air.File.applicationDirectory.resolvePath(db);\r
1319                 this.conn.open(file);\r
1320         this.openState = true;\r
1321                 this.fireEvent('open', this);\r
1322     },\r
1323 \r
1324         close : function(){\r
1325         this.conn.close();\r
1326         this.fireEvent('close', this);\r
1327     },\r
1328 \r
1329         createStatement : function(type){\r
1330                 var stmt = new air.SQLStatement();\r
1331                 stmt.sqlConnection = this.conn;\r
1332                 return stmt;\r
1333         },\r
1334 \r
1335     exec : function(sql){\r
1336         var stmt = this.createStatement('exec');\r
1337                 stmt.text = sql;\r
1338                 stmt.execute();\r
1339     },\r
1340 \r
1341         execBy : function(sql, args){\r
1342                 var stmt = this.createStatement('exec');\r
1343                 stmt.text = sql;\r
1344                 this.addParams(stmt, args);\r
1345                 stmt.execute();\r
1346         },\r
1347 \r
1348         query : function(sql){\r
1349                 var stmt = this.createStatement('query');\r
1350                 stmt.text = sql;\r
1351                 stmt.execute(this.maxResults);\r
1352                 return this.readResults(stmt.getResult());\r
1353         },\r
1354 \r
1355         queryBy : function(sql, args){\r
1356                 var stmt = this.createStatement('query');\r
1357                 stmt.text = sql;\r
1358                 this.addParams(stmt, args);\r
1359                 stmt.execute(this.maxResults);\r
1360                 return this.readResults(stmt.getResult());\r
1361         },\r
1362 \r
1363     addParams : function(stmt, args){\r
1364                 if(!args){ return; }\r
1365                 for(var key in args){\r
1366                         if(args.hasOwnProperty(key)){\r
1367                                 if(!isNaN(key)){\r
1368                                         var v = args[key];\r
1369                                         if(Ext.isDate(v)){\r
1370                                                 v = v.format(Ext.sql.Proxy.DATE_FORMAT);\r
1371                                         }\r
1372                                         stmt.parameters[parseInt(key)] = v;\r
1373                                 }else{\r
1374                                         stmt.parameters[':' + key] = args[key];\r
1375                                 }\r
1376                         }\r
1377                 }\r
1378                 return stmt;\r
1379         },\r
1380 \r
1381     readResults : function(rs){\r
1382         var r = [];\r
1383         if(rs && rs.data){\r
1384                     var len = rs.data.length;\r
1385                 for(var i = 0; i < len; i++) {\r
1386                     r[r.length] = rs.data[i];\r
1387                 }\r
1388         }\r
1389         return r;\r
1390     }\r
1391 });
1392 Ext.air.SystemTray = function(){\r
1393         var app = air.NativeApplication.nativeApplication;\r
1394         var icon, isWindows = false, bitmaps;\r
1395         \r
1396         
1397         if(air.NativeApplication.supportsSystemTrayIcon) {\r
1398         icon = app.icon;\r
1399                 isWindows = true;\r
1400     }\r
1401     \r
1402         
1403     if(air.NativeApplication.supportsDockIcon) {\r
1404                 icon = app.icon;\r
1405     }\r
1406         \r
1407         return {\r
1408                 \r
1409                 setIcon : function(icon, tooltip, initWithIcon){\r
1410                         if(!icon){ 
1411                                 return;\r
1412                         }\r
1413                         var loader = new air.Loader();\r
1414                         loader.contentLoaderInfo.addEventListener(air.Event.COMPLETE, function(e){\r
1415                                 bitmaps = new runtime.Array(e.target.content.bitmapData);\r
1416                                 if (initWithIcon) {\r
1417                                         icon.bitmaps = bitmaps;\r
1418                                 }\r
1419                         });\r
1420                 loader.load(new air.URLRequest(icon));\r
1421                         if(tooltip && air.NativeApplication.supportsSystemTrayIcon) {\r
1422                                 app.icon.tooltip = tooltip;\r
1423                         }\r
1424                 },\r
1425                 \r
1426                 bounce : function(priority){\r
1427                         icon.bounce(priority);\r
1428                 },\r
1429                 \r
1430                 on : function(eventName, fn, scope){\r
1431                         icon.addEventListener(eventName, function(){\r
1432                                 fn.apply(scope || this, arguments);\r
1433                         });\r
1434                 },\r
1435                 \r
1436                 hideIcon : function(){\r
1437                         if(!icon){ 
1438                                 return;\r
1439                         }\r
1440                         icon.bitmaps = [];\r
1441                 },\r
1442                 \r
1443                 showIcon : function(){\r
1444                         if(!icon){ 
1445                                 return;\r
1446                         }\r
1447                         icon.bitmaps = bitmaps;\r
1448                 },\r
1449                 \r
1450                 setMenu: function(actions, _parentMenu){\r
1451                         if(!icon){ 
1452                                 return;\r
1453                         }\r
1454                         var menu = new air.NativeMenu();\r
1455                         \r
1456                         for (var i = 0, len = actions.length; i < len; i++) {\r
1457                                 var a = actions[i];\r
1458                                 if(a == '-'){\r
1459                                         menu.addItem(new air.NativeMenuItem("", true));\r
1460                                 }else{\r
1461                                         var item = menu.addItem(Ext.air.MenuItem(a));\r
1462                                         if(a.menu || (a.initialConfig && a.initialConfig.menu)){\r
1463                                                 item.submenu = Ext.air.SystemTray.setMenu(a.menu || a.initialConfig.menu, menu);\r
1464                                         }\r
1465                                 }\r
1466                                 \r
1467                                 if(!_parentMenu){\r
1468                                         icon.menu = menu;\r
1469                                 }\r
1470                         }\r
1471                         \r
1472                         return menu;\r
1473                 }\r
1474         };      \r
1475 }();
1476
1477 \r
1478 Ext.air.DragType = {\r
1479         TEXT : 'text/plain',\r
1480         HTML : 'text/html',\r
1481         URL : 'text/uri-list',\r
1482         BITMAP : 'image/x-vnd.adobe.air.bitmap',\r
1483         FILES : 'application/x-vnd.adobe.air.file-list'\r
1484 };\r
1485 \r
1486 Ext.apply(Ext.EventObjectImpl.prototype, {\r
1487         hasFormat : function(format){\r
1488                 if (this.browserEvent.dataTransfer) {\r
1489                         for (var i = 0, len = this.browserEvent.dataTransfer.types.length; i < len; i++) {\r
1490                                 if(this.browserEvent.dataTransfer.types[i] == format) {\r
1491                                         return true;\r
1492                                 }\r
1493                         }\r
1494                 }\r
1495                 return false;\r
1496         },\r
1497         \r
1498         getData : function(type){\r
1499                 return this.browserEvent.dataTransfer.getData(type);\r
1500         }\r
1501 });\r
1502 \r
1503 \r
1504
1505 Ext.air.Sound = {\r
1506         play : function(file, startAt){\r
1507                 var soundFile = air.File.applicationDirectory.resolvePath(file);\r
1508                 var sound = new air.Sound();\r
1509                 sound.load(new air.URLRequest(soundFile.url));\r
1510                 sound.play(startAt);\r
1511         }\r
1512 };\r
1513
1514
1515 Ext.air.SystemMenu = function(){\r
1516         var menu;\r
1517         
1518         if(air.NativeWindow.supportsMenu && nativeWindow.systemChrome != air.NativeWindowSystemChrome.NONE) {\r
1519         menu = new air.NativeMenu();\r
1520         nativeWindow.menu = menu;\r
1521     }\r
1522     \r
1523         
1524     if(air.NativeApplication.supportsMenu) {\r
1525                 menu = air.NativeApplication.nativeApplication.menu;\r
1526     }\r
1527 \r
1528     function find(menu, text){\r
1529         for(var i = 0, len = menu.items.length; i < len; i++){\r
1530             if(menu.items[i]['label'] == text){\r
1531                 return menu.items[i];\r
1532             }\r
1533         }\r
1534         return null;\r
1535     }\r
1536 \r
1537     return {\r
1538                 add: function(text, actions, mindex){\r
1539 \r
1540             var item = find(menu, text);\r
1541             if(!item){\r
1542                 item = menu.addItem(new air.NativeMenuItem(text));\r
1543                 item.mnemonicIndex = mindex || 0;\r
1544 \r
1545                 item.submenu = new air.NativeMenu();\r
1546                         }\r
1547                         for (var i = 0, len = actions.length; i < len; i++) {\r
1548                                 item.submenu.addItem(actions[i] == '-' ? new air.NativeMenuItem("", true) : Ext.air.MenuItem(actions[i]));\r
1549                         }\r
1550             return item.submenu;\r
1551         },\r
1552                 \r
1553                 get : function(){\r
1554                         return menu;\r
1555                 }\r
1556         };      \r
1557 }();\r
1558 \r
1559
1560 Ext.air.MenuItem = function(action){\r
1561         if(!action.isAction){\r
1562                 action = new Ext.Action(action);\r
1563         }\r
1564         var cfg = action.initialConfig;\r
1565         var nativeItem = new air.NativeMenuItem(cfg.itemText || cfg.text);\r
1566         \r
1567         nativeItem.enabled = !cfg.disabled;\r
1568 \r
1569     if(!Ext.isEmpty(cfg.checked)){\r
1570         nativeItem.checked = cfg.checked;\r
1571     }\r
1572 \r
1573     var handler = cfg.handler;\r
1574         var scope = cfg.scope;\r
1575         \r
1576         nativeItem.addEventListener(air.Event.SELECT, function(){\r
1577                 handler.call(scope || window, cfg);\r
1578         });\r
1579         \r
1580         action.addComponent({\r
1581                 setDisabled : function(v){\r
1582                         nativeItem.enabled = !v;\r
1583                 },\r
1584                 \r
1585                 setText : function(v){\r
1586                         nativeItem.label = v;\r
1587                 },\r
1588                 \r
1589                 setVisible : function(v){\r
1590                         
1591                         nativeItem.enabled = !v;\r
1592                 },\r
1593                 \r
1594                 setHandler : function(newHandler, newScope){\r
1595                         handler = newHandler;\r
1596                         scope = newScope;\r
1597                 },\r
1598                 
1599                 on : function(){}\r
1600         });\r
1601         \r
1602         return nativeItem;\r
1603 }\r
1604