The source code

    Ext.onReady(function(){
        Ext.QuickTips.init();

        var xg = Ext.grid;
        // turn off default shadows which look funky in air
        xg.GridEditor.prototype.shadow = false;

        var conn = Ext.data.SqlDB.getInstance();
    	conn.open('tasks.db');

        // the main grid store
        var taskStore = new TaskStore(conn);

        // Category store shared by category combos
        var catStore = new CategoryStore();

    	taskStore.load({
    		callback: function(){
    			// first time?
    			if(taskStore.getCount() < 1){
    				Ext.Msg.confirm('Create Tasks?', 'Your database is currently empty. Would you like to insert some demo data?',
    					function(btn){
    						if(btn == 'yes'){
    							loadDemoTasks(taskStore);
    						}
    						catStore.init(taskStore);
    					});
    			}else{
    				catStore.init(taskStore);
    			}
    		}
    	});

        // custom event to notify when a new category is available
        taskStore.on('newcategory', catStore.addCategory, catStore);

        // set of event handlers shared by combos to allow them to share
        // the same local store
        var comboEvents = {
            focus: function(){
                this.bindStore(catStore);
            },
            blur: function(c){
                catStore.purgeListeners();
            }
        }

        var completeColumn = new CompleteColumn();

        // custom template for the grid header
        var headerTpl = new Ext.Template(
            '',
            '{cells}',
            '',
                '',
                '',
                '',
                '',
            '',
            ""
        );

        var selections = new Ext.grid.RowSelectionModel();

        // The main grid in all its configuration option glory
        var grid = new xg.EditorGridPanel({
            id:'tasks-grid',
            store: taskStore,
            sm: selections,
            clicksToEdit: 'auto',
            enableColumnHide:false,
            enableColumnMove:false,
    		border:false,
    		title:'All Tasks',
    		iconCls:'icon-show-all',
    		region:'center',

            plugins: completeColumn,

            columns: [
                completeColumn,
                {
                    header: "Task",
                    width:400,
                    sortable: true,
                    dataIndex: 'title',
                    id:'task-title',
                    editor: new Ext.form.TextField({
                        allowBlank: false
                    })
                },
                {
                    header: "Category",
                    width:150,
                    sortable: true,
                    dataIndex: 'category',
                    editor: new Ext.form.ComboBox({
                        displayField: 'text',
                        triggerAction: 'all',
                        mode:'local',
                        selectOnFocus:true,
                        listClass:'x-combo-list-small',
                        listeners: comboEvents
                    })
                },
                {
                    header: "Due Date",
                    width: 150,
                    sortable: true,
                    renderer: Ext.util.Format.dateRenderer('D m/d/Y'),
                    dataIndex: 'dueDate',
                    groupRenderer: textDate(),
                    groupName: 'Due',
                    editor: new Ext.form.DateField({
                        format : "m/d/Y"
                    })
                }
            ],

            view: new Ext.grid.GroupingView({
                forceFit:true,
                ignoreAdd: true,
                emptyText: 'No Tasks to display',

                templates: {
                    header: headerTpl
                },

                getRowClass : function(r){
                    var d = r.data;
                    if(d.completed){
                        return 'task-completed';
                    }
                    if(d.dueDate && d.dueDate.getTime() < new Date().clearTime().getTime()){
                        return 'task-overdue';
                    }
                    return '';
                }
            })
        });

        var viewPanel = new Ext.Panel({
        	frame:true,
        	title: 'Views',
        	collapsible:true,
        	contentEl:'task-views',
        	titleCollapse: true
        });

        var taskActions = new Ext.Panel({
        	frame:true,
        	title: 'Task Actions',
        	collapsible:true,
        	contentEl:'task-actions',
        	titleCollapse: true
        });

        var groupActions = new Ext.Panel({
        	frame:true,
        	title: 'Task Grouping',
        	collapsible:true,
        	contentEl:'task-grouping',
        	titleCollapse: true
        });

        var actionPanel = new Ext.Panel({
        	id:'action-panel',
        	region:'west',
        	split:true,
        	collapsible: true,
        	collapseMode: 'mini',
        	width:200,
        	minWidth: 150,
        	border: false,
        	baseCls:'x-plain',
        	items: [taskActions, viewPanel, groupActions]
        });

        if(Ext.isAir){ // create AIR window
            var win = new Ext.air.MainWindow({
                layout:'border',
                items: [actionPanel, grid],
                title: 'Simple Tasks',
                iconCls: 'icon-show-all'
            }).render();
    	}else{
            var viewport = new Ext.Viewport({
                layout:'border',
                items: [actionPanel, grid]
            });
        }

        var ab = actionPanel.body;
        ab.on('mousedown', doAction, null, {delegate:'a'});
    	ab.on('click', Ext.emptyFn, null, {delegate:'a', preventDefault:true});

        grid.on('resize', syncFields);
    	grid.on('columnresize', syncFields);

        grid.on('afteredit', function(e){
            if(e.field == 'category'){
                catStore.addCategory(e.value);
            }
            if(e.field == taskStore.getGroupState()){
                taskStore.applyGrouping();
            }

        });

        grid.on('keydown', function(e){
             if(e.getKey() == e.DELETE && !grid.editing){
                 actions['action-delete']();
             }
        });

        selections.on('selectionchange', function(sm){
        	var bd = taskActions.body, c = sm.getCount();
        	bd.select('li:not(#new-task)').setDisplayed(c > 0);
        	bd.select('span.s').setDisplayed(c > 1);
        });

        // The fields in the grid's header
        var ntTitle = new Ext.form.TextField({
            renderTo: 'new-task-title',
            emptyText: 'Add a task...'
        });

        var ntCat = new Ext.form.ComboBox({
            renderTo: 'new-task-cat',
            disabled:true,
            displayField: 'text',
            triggerAction: 'all',
            mode:'local',
            selectOnFocus:true,
            listClass:'x-combo-list-small',
            listeners: comboEvents
        });

        var ntDue = new Ext.form.DateField({
            renderTo: 'new-task-due',
            value: new Date(),
            disabled:true,
            format : "m/d/Y"
        });

        // syncs the header fields' widths with the grid column widths
        function syncFields(){
            var cm = grid.getColumnModel();
            ntTitle.setSize(cm.getColumnWidth(1)-2);
            ntCat.setSize(cm.getColumnWidth(2)-4);
            ntDue.setSize(cm.getColumnWidth(3)-4);
        }
        syncFields();

        var editing = false, focused = false, userTriggered = false;
        var handlers = {
            focus: function(){
                focused = true;
            },
            blur: function(){
                focused = false;
                doBlur.defer(250);
            },
            specialkey: function(f, e){
                if(e.getKey()==e.ENTER){
                    userTriggered = true;
                    e.stopEvent();
                    f.el.blur();
                    if(f.triggerBlur){
                        f.triggerBlur();
                    }
                }
            }
        }
        ntTitle.on(handlers);
        ntCat.on(handlers);
        ntDue.on(handlers);

        ntTitle.on('focus', function(){
            focused = true;
            if(!editing){
                ntCat.enable();
                ntDue.enable();
                syncFields();
                editing = true;
            }
        });

        // when a field in the add bar is blurred, this determines
        // whether a new task should be created
        function doBlur(){
            if(editing && !focused){
                var title = ntTitle.getValue();
                if(!Ext.isEmpty(title)){
                    taskStore.addTask({
                        taskId: Task.nextId(),
                        title: title,
                        dueDate: ntDue.getValue()||'',
                        description: '', // ???
                        category: ntCat.getValue(),
                        completed: false
                    });
                    ntTitle.setValue('');
                    if(userTriggered){ // if the entered to add the task, then go to a new add automatically
                        userTriggered = false;
                        ntTitle.focus.defer(100, ntTitle);
                    }
                }
                ntCat.disable();
                ntDue.disable();
                editing = false;
            }
        }

        var actions = {
        	'view-all' : function(){
        		taskStore.applyFilter('all');
        		grid.setTitle('All Tasks', 'icon-show-all');
        	},

        	'view-active' : function(){
        		taskStore.applyFilter(false);
        		grid.setTitle('Active Tasks', 'icon-show-active');
        	},

        	'view-complete' : function(){
        		taskStore.applyFilter(true);
        		grid.setTitle('Completed Tasks', 'icon-show-complete');
        	},

        	'action-new' : function(){
        		ntTitle.focus();
        	},

        	'action-complete' : function(){
        		selections.each(function(s){
        			s.set('completed', true);
        		});
                taskStore.applyFilter();
        	},

        	'action-active' : function(){
        		selections.each(function(s){
        			s.set('completed', false);
        		});
                taskStore.applyFilter();
        	},

        	'action-delete' : function(){
        		Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?',
        		function(btn){
                    if(btn == 'yes'){
                    	selections.each(function(s){
    		    			taskStore.remove(s);
    		    		});
                    }
                });
        	},

        	'group-date' : function(){
        		taskStore.groupBy('dueDate');
        	},

        	'group-cat' : function(){
        		taskStore.groupBy('category');
        	},

        	'no-group' : function(){
        		taskStore.clearGrouping();
        	}
        };

        function doAction(e, t){
        	e.stopEvent();
        	actions[t.id]();
        }

        // generates a renderer function to be used for textual date groups
        function textDate(){
            // create the cache of ranges to be reused
            var today = new Date().clearTime(true);
            var year = today.getFullYear();
            var todayTime = today.getTime();
            var yesterday = today.add('d', -1).getTime();
            var tomorrow = today.add('d', 1).getTime();
            var weekDays = today.add('d', 6).getTime();
            var lastWeekDays = today.add('d', -6).getTime();

            return function(date){
                if(!date) {
                    return '(No Date)';
                }
                var notime = date.clearTime(true).getTime();

                if (notime == todayTime) {
                    return 'Today';
                }
                if(notime > todayTime){
                    if (notime == tomorrow) {
                        return 'Tomorrow';
                    }
                    if (notime <= weekDays) {
                        return date.format('l');
                    }
                }else {
                	if(notime == yesterday) {
                    	return 'Yesterday';
    	            }
    	            if(notime >= lastWeekDays) {
    	                return 'Last ' + date.format('l');
    	            }
                }
                return date.getFullYear() == year ? date.format('D m/d') : date.format('D m/d/Y');
           }
        }
    });

    /* This is used to laod some demo tasks if the task database is empty */
    function loadDemoTasks(store){
    	var s = new Date();
    	// hardcoded demo tasks
    	store.addTask({taskId: Task.nextId(), title:'Start documentation of Ext 2.0', category:'Ext', description:'', dueDate: s.add('d', 21), completed: false});
    	store.addTask({taskId: Task.nextId(), title:'Release Ext 1.l Beta 2', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
    	store.addTask({taskId: Task.nextId(), title:'Take wife to see movie', category:'Family', description:'', dueDate:s.add('d', 2), completed: false});
    	store.addTask({taskId: Task.nextId(), title:'Finish task list demo app', category:'Ext', description:'', dueDate:s.add('d', 2), completed: false});
    	store.addTask({taskId: Task.nextId(), title:'Do something other than work', category:'Family', description:'', dueDate:s.add('d', -1), completed: false});
    	store.addTask({taskId: Task.nextId(), title:'Go to the grocery store', category:'Family', description:'', dueDate:s.add('d', -1), completed: true});
    	store.addTask({taskId: Task.nextId(), title:'Reboot my computer', category:'Misc', description:'', dueDate:s, completed: false});
    	store.addTask({taskId: Task.nextId(), title:'Respond to emails', category:'Ext', description:'', dueDate:s, completed: true});
    }