--- /dev/null
+<html>\r
+<head>\r
+ <title>The source code</title>\r
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
+</head>\r
+<body onload="prettyPrint();">\r
+ <pre class="prettyprint lang-js">// Initialize the state provider\r
+Ext.state.Manager.setProvider(new Ext.air.FileProvider({\r
+ file: 'tasks.state',\r
+ // if first time running\r
+ defaultState : {\r
+ mainWindow : {\r
+ width:780,\r
+ height:580,\r
+ x:10,\r
+ y:10\r
+ },\r
+ defaultReminder: 480\r
+ }\r
+}));\r
+\r
+Ext.onReady(function(){\r
+ Ext.QuickTips.init();\r
+\r
+ // maintain window state automatically\r
+ var win = new Ext.air.NativeWindow({\r
+ id: 'mainWindow',\r
+ instance: window.nativeWindow,\r
+ minimizeToTray: true,\r
+ trayIcon: 'ext-air/resources/icons/extlogo16.png',\r
+ trayTip: 'Simple Tasks',\r
+ trayMenu : [{\r
+ text: 'Open Simple Tasks',\r
+ handler: function(){\r
+ win.activate();\r
+ }\r
+ }, '-', {\r
+ text: 'Exit',\r
+ handler: function(){\r
+ air.NativeApplication.nativeApplication.exit();\r
+ }\r
+ }]\r
+ });\r
+ \r
+ tx.data.conn.open('tasks.db');\r
+ \r
+ var grid = new TaskGrid();\r
+ var selections = grid.getSelectionModel();\r
+ \r
+ \r
+ // Shared actions used by Ext toolbars, menus, etc.\r
+ var actions = {\r
+ newTask: new Ext.Action({\r
+ text: 'New Task',\r
+ iconCls: 'icon-active',\r
+ tooltip: 'New Task',\r
+ handler: function(){\r
+ taskHeader.ntTitle.focus();\r
+ }\r
+ }),\r
+ \r
+ deleteTask: new Ext.Action({\r
+ itemText: 'Delete',\r
+ iconCls: 'icon-delete-task',\r
+ tooltip: 'Delete Task',\r
+ disabled: true,\r
+ handler: function(){\r
+ Ext.Msg.confirm('Confirm', 'Are you sure you want to delete the selected task(s)?', function(btn){\r
+ if (btn == 'yes') {\r
+ selections.each(function(s){\r
+ tx.data.tasks.remove(s);\r
+ });\r
+ }\r
+ });\r
+ }\r
+ }),\r
+ \r
+ complete: new Ext.Action({\r
+ itemText: 'Mark Complete',\r
+ iconCls: 'icon-mark-complete',\r
+ tooltip: 'Mark Complete',\r
+ disabled: true,\r
+ handler: function(){\r
+ selections.each(function(s){\r
+ s.set('completed', true);\r
+ });\r
+ tx.data.tasks.applyFilter();\r
+ }\r
+ }),\r
+ \r
+ active: new Ext.Action({\r
+ itemText: 'Mark Active',\r
+ tooltip: 'Mark Active',\r
+ iconCls: 'icon-mark-active',\r
+ disabled: true,\r
+ handler: function(){\r
+ selections.each(function(s){\r
+ s.set('completed', false);\r
+ });\r
+ tx.data.tasks.applyFilter();\r
+ }\r
+ }),\r
+ \r
+ newList: new Ext.Action({\r
+ itemText: 'New List',\r
+ tooltip: 'New List',\r
+ iconCls: 'icon-list-new',\r
+ handler: function(){\r
+ var id = tx.data.lists.newList(false, tree.getActiveFolderId()).id;\r
+ tree.startEdit(id, true);\r
+ }\r
+ }),\r
+ \r
+ deleteList: new Ext.Action({\r
+ itemText: 'Delete',\r
+ tooltip: 'Delete List',\r
+ iconCls: 'icon-list-delete',\r
+ disabled: true,\r
+ handler: function(){\r
+ tree.removeList(tree.getSelectionModel().getSelectedNode());\r
+ }\r
+ }),\r
+ \r
+ newFolder: new Ext.Action({\r
+ itemText: 'New Folder',\r
+ tooltip: 'New Folder',\r
+ iconCls: 'icon-folder-new',\r
+ handler: function(){\r
+ var id = tx.data.lists.newList(true, tree.getActiveFolderId()).id;\r
+ tree.startEdit(id, true);\r
+ }\r
+ }),\r
+ \r
+ deleteFolder: new Ext.Action({\r
+ itemText: 'Delete',\r
+ tooltip: 'Delete Folder',\r
+ iconCls: 'icon-folder-delete',\r
+ disabled: true,\r
+ handler: function(s){\r
+ tree.removeList(tree.getSelectionModel().getSelectedNode());\r
+ }\r
+ }),\r
+ \r
+ quit : new Ext.Action({\r
+ text: 'Exit',\r
+ handler: function(){\r
+ air.NativeApplication.nativeApplication.exit();\r
+ }\r
+ }),\r
+ \r
+ pasteAsTask : new Ext.Action({\r
+ itemText: 'Paste as New Task',\r
+ tooltip: 'Paste as New Task',\r
+ iconCls: 'icon-paste-new',\r
+ handler: function(){\r
+ if(air.Clipboard.generalClipboard.hasFormat(air.ClipboardFormats.TEXT_FORMAT)){\r
+ var text = air.Clipboard.generalClipboard.getData(air.ClipboardFormats.TEXT_FORMAT);\r
+ tx.data.tasks.addTask({\r
+ taskId: Ext.uniqueId(),\r
+ title: Ext.util.Format.htmlEncode(text.replace(/[\n\r]/g, '')),\r
+ dueDate: new Date(),\r
+ description: '', \r
+ listId: tx.data.getActiveListId(),\r
+ completed: false, \r
+ reminder: ''\r
+ });\r
+ }else{\r
+ Ext.Msg.alert('Warning', 'Could not create task. The clipboard is empty.');\r
+ }\r
+ }\r
+ }) \r
+ };\r
+ tx.actions = actions;\r
+\r
+ var menus = Ext.air.SystemMenu;\r
+ \r
+ menus.add('File', [\r
+ actions.newTask, \r
+ actions.newList, \r
+ actions.newFolder, \r
+ '-',{\r
+ text:'Import...',\r
+ handler: function(){\r
+ var importer = new tx.Importer();\r
+ importer.doImport(function(){\r
+ tx.data.lists.load();\r
+ root.reload();\r
+ loadList('root');\r
+ Ext.Msg.hide();\r
+ });\r
+ }\r
+ },{\r
+ text:'Export...',\r
+ handler: function(){\r
+ new tx.Exporter();\r
+ }\r
+ },\r
+ '-', \r
+ actions.quit\r
+ ]);\r
+\r
+ menus.add('Edit', [\r
+ actions.pasteAsTask\r
+ ]);\r
+\r
+ \r
+ var viewMenu = menus.add('View', [{\r
+ text: 'All Tasks',\r
+ checked: true,\r
+ handler: function(){\r
+ Ext.getCmp('filter').setActiveItem(0);\r
+ }\r
+ },{\r
+ text: 'Active Tasks',\r
+ checked: false,\r
+ handler: function(){\r
+ Ext.getCmp('filter').setActiveItem(1);\r
+ }\r
+ },{\r
+ text: 'Completed Tasks',\r
+ checked: false,\r
+ handler: function(){\r
+ Ext.getCmp('filter').setActiveItem(2);\r
+ }\r
+ }]);\r
+\r
+ menus.add('Help', [{\r
+ text: 'About',\r
+ handler: function(){\r
+ Ext.air.NativeWindowManager.getAboutWindow().activate();\r
+ }\r
+ }]);\r
+\r
+\r
+ var tree = new ListTree({\r
+ actions: actions,\r
+ store: tx.data.lists\r
+ });\r
+\r
+ var root = tree.getRootNode(); \r
+\r
+ var listSm = tree.getSelectionModel();\r
+ \r
+ tx.data.lists.bindTree(tree);\r
+ tx.data.lists.on('update', function(){\r
+ tx.data.tasks.applyGrouping();\r
+ if(grid.titleNode){\r
+ grid.setTitle(grid.titleNode.text);\r
+ }\r
+ });\r
+ \r
+ var tb = new Ext.Toolbar({\r
+ region:'north',\r
+ id:'main-tb',\r
+ height:26,\r
+ items: [{\r
+ xtype:'splitbutton',\r
+ iconCls:'icon-edit',\r
+ text:'New',\r
+ handler: actions.newTask.initialConfig.handler,\r
+ menu: [actions.newTask, actions.newList, actions.newFolder]\r
+ },'-',\r
+ actions.deleteTask,\r
+ actions.complete,\r
+ actions.active,\r
+ '-',\r
+ actions.pasteAsTask,\r
+ '->',{\r
+ xtype:'switch',\r
+ id:'filter',\r
+ activeItem:0,\r
+ items: [{\r
+ tooltip:'All Tasks',\r
+ filter: 'all',\r
+ iconCls:'icon-all',\r
+ menuIndex: 0\r
+ },{\r
+ tooltip:'Active Tasks',\r
+ filter: false,\r
+ iconCls:'icon-active',\r
+ menuIndex: 1\r
+ },{\r
+ tooltip:'Completed Tasks',\r
+ filter: true,\r
+ iconCls:'icon-complete',\r
+ menuIndex: 2\r
+ }],\r
+ listeners: {\r
+ change: function(btn, item){\r
+ tx.data.tasks.applyFilter(item.filter);\r
+ for (var i = 0; i < 3; i++) {\r
+ viewMenu.items[i].checked = item.menuIndex === i;\r
+ }\r
+ },\r
+ delay: 10 // delay gives user instant click feedback before filtering tasks\r
+ }\r
+ }, ' ', ' ', ' ' \r
+ ]\r
+ });\r
+\r
+ var viewport = new Ext.Viewport({\r
+ layout:'border',\r
+ items: [tb, tree, grid]\r
+ });\r
+ \r
+ grid.on('keydown', function(e){\r
+ if(e.getKey() == e.DELETE && !grid.editing){\r
+ actions.deleteTask.execute();\r
+ }\r
+ });\r
+\r
+ tree.el.on('keydown', function(e){\r
+ if(e.getKey() == e.DELETE && !tree.editor.editing){\r
+ actions.deleteList.execute();\r
+ }\r
+ });\r
+\r
+ selections.on('selectionchange', function(sm){\r
+ var disabled = sm.getCount() < 1;\r
+ actions.complete.setDisabled(disabled);\r
+ actions.active.setDisabled(disabled);\r
+ actions.deleteTask.setDisabled(disabled);\r
+ });\r
+\r
+ var taskHeader = new TaskHeader(grid);\r
+\r
+ win.show();\r
+ win.instance.activate();\r
+ \r
+ tx.data.tasks.init();\r
+\r
+ tree.root.select();\r
+\r
+ var loadList = function(listId){\r
+ var node = tree.getNodeById(listId);\r
+ if(node && !node.isSelected()){\r
+ node.select();\r
+ return;\r
+ }\r
+ actions.deleteList.setDisabled(!node || !node.attributes.editable);\r
+ actions.deleteFolder.setDisabled(!node || node.attributes.editable === false || !node.attributes.isFolder);\r
+ if(node){\r
+ if (node.attributes.isFolder) {\r
+ var lists = [];\r
+ node.cascade(function(n){\r
+ if (!n.attributes.isFolder) {\r
+ lists.push(n.attributes.id);\r
+ }\r
+ });\r
+ tx.data.tasks.loadList(lists);\r
+ }\r
+ else {\r
+ tx.data.tasks.loadList(node.id);\r
+ }\r
+ grid.titleNode = node;\r
+ grid.setTitle(node.text);\r
+ grid.setIconClass(node.attributes.iconCls);\r
+ }\r
+ }\r
+\r
+ listSm.on('selectionchange', function(t, node){\r
+ loadList(node ? node.id : null);\r
+ });\r
+ \r
+ root.reload();\r
+ \r
+ if(Ext.state.Manager.get('defaultReminder') === undefined){\r
+ Ext.state.Manager.set('defaultReminder', 9 * 60); // default to 9am\r
+ }\r
+ \r
+ win.on('closing', function(){\r
+ Ext.air.NativeWindowManager.closeAll();\r
+ });\r
+ \r
+ tx.ReminderManager.init();\r
+ \r
+ grid.body.on('dragover', function(e){\r
+ if(e.hasFormat(Ext.air.DragType.TEXT)){\r
+ e.preventDefault();\r
+ }\r
+ });\r
+ \r
+ grid.body.on('drop', function(e){\r
+ if(e.hasFormat(Ext.air.DragType.TEXT)){\r
+ var text = e.getData(Ext.air.DragType.TEXT);\r
+ try{\r
+ // from outlook\r
+ if(text.indexOf("Subject\t") != -1){\r
+ var tasks = text.split("\n");\r
+ for(var i = 1, len = tasks.length; i < len; i++){\r
+ var data = tasks[i].split("\t");\r
+ var list = tx.data.lists.findList(data[2]);\r
+ tx.data.tasks.addTask({\r
+ taskId: Ext.uniqueId(),\r
+ title: Ext.util.Format.htmlEncode(data[0]),\r
+ dueDate: Date.parseDate(data[1], 'D n/j/Y') || '',\r
+ description: '', \r
+ listId: list ? list.id : tx.data.getActiveListId(),\r
+ completed: false, \r
+ reminder: ''\r
+ });\r
+ }\r
+ }else{\r
+ tx.data.tasks.addTask({\r
+ taskId: Ext.uniqueId(),\r
+ title: Ext.util.Format.htmlEncode(text),\r
+ dueDate: new Date(),\r
+ description: '', \r
+ listId: tx.data.getActiveListId(),\r
+ completed: false, \r
+ reminder: ''\r
+ });\r
+ }\r
+ }catch(e){\r
+ air.trace('An error occured trying to import drag drop tasks.');\r
+ }\r
+ }\r
+ });\r
+});\r
+\r
+ \r
+\r
+</pre> \r
+</body>\r
+</html>
\ No newline at end of file