diff --git a/.hgignore b/.hgignore index b0b9510..012d7d9 100644 --- a/.hgignore +++ b/.hgignore @@ -1,2 +1,4 @@ build/ \..*sw[op] +dist/ +staging/ diff --git a/pit-swing/griffon-app/conf/Application.groovy b/pit-swing/griffon-app/conf/Application.groovy index ab29ae1..94ccff0 100644 --- a/pit-swing/griffon-app/conf/Application.groovy +++ b/pit-swing/griffon-app/conf/Application.groovy @@ -1,6 +1,6 @@ application { title='PitSwing' - startupGroups = ['pit-swing'] + startupGroups = ['PIT'] // Should Griffon exit when no Griffon created frames are showing? autoShutdown = true @@ -12,15 +12,8 @@ mvcGroups { // MVC Group for "com.jdbernard.pit.swing.PIT" 'PIT' { model = 'com.jdbernard.pit.swing.PITModel' - controller = 'com.jdbernard.pit.swing.PITController' view = 'com.jdbernard.pit.swing.PITView' - } - - // MVC Group for "pit-swing" - 'pit-swing' { - model = 'PitSwingModel' - controller = 'PitSwingController' - view = 'PitSwingView' + controller = 'com.jdbernard.pit.swing.PITController' } } diff --git a/pit-swing/griffon-app/controllers/com/jdbernard/pit/swing/PITController.groovy b/pit-swing/griffon-app/controllers/com/jdbernard/pit/swing/PITController.groovy index 1b1eebf..4456eae 100644 --- a/pit-swing/griffon-app/controllers/com/jdbernard/pit/swing/PITController.groovy +++ b/pit-swing/griffon-app/controllers/com/jdbernard/pit/swing/PITController.groovy @@ -1,16 +1,18 @@ package com.jdbernard.pit.swing +import com.jdbernard.pit.FileProject + class PITController { // these will be injected by Griffon def model def view void mvcGroupInit(Map args) { - // this method is called after model and view are injected + model.rootProject = new FileProject(new File('.')) } /* def action = { evt = null -> } */ -} \ No newline at end of file +} diff --git a/pit-swing/griffon-app/resources/bug.png b/pit-swing/griffon-app/resources/bug.png new file mode 100755 index 0000000..2d5fb90 Binary files /dev/null and b/pit-swing/griffon-app/resources/bug.png differ diff --git a/pit-swing/griffon-app/resources/closed.png b/pit-swing/griffon-app/resources/closed.png new file mode 100755 index 0000000..a9925a0 Binary files /dev/null and b/pit-swing/griffon-app/resources/closed.png differ diff --git a/pit-swing/griffon-app/resources/feature.png b/pit-swing/griffon-app/resources/feature.png new file mode 100755 index 0000000..b88c857 Binary files /dev/null and b/pit-swing/griffon-app/resources/feature.png differ diff --git a/pit-swing/griffon-app/resources/folder.png b/pit-swing/griffon-app/resources/folder.png new file mode 100755 index 0000000..784e8fa Binary files /dev/null and b/pit-swing/griffon-app/resources/folder.png differ diff --git a/pit-swing/griffon-app/resources/task.png b/pit-swing/griffon-app/resources/task.png new file mode 100755 index 0000000..7851cf3 Binary files /dev/null and b/pit-swing/griffon-app/resources/task.png differ diff --git a/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy b/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy index 3eeda81..48ee612 100644 --- a/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy +++ b/pit-swing/griffon-app/views/com/jdbernard/pit/swing/PITView.groovy @@ -1,7 +1,49 @@ package com.jdbernard.pit.swing +import com.jdbernard.pit.Category +import com.jdbernard.pit.Issue +import com.jdbernard.pit.Project +import com.jdbernard.pit.FileProject +import javax.swing.DefaultListModel +import javax.swing.JFileChooser +import javax.swing.JSplitPane +import javax.swing.ListSelectionModel +import javax.swing.tree.DefaultMutableTreeNode +import javax.swing.tree.DefaultTreeCellRenderer +import javax.swing.tree.DefaultTreeModel +import javax.swing.tree.TreeSelectionModel import net.miginfocom.swing.MigLayout +// VIEW-Specific data +projectListModels = [:] + +categoryIcons = [(Category.BUG): imageIcon('/bug.png'), + (Category.CLOSED): imageIcon('/closed.png'), + (Category.FEATURE): imageIcon('/feature.png'), + (Category.TASK): imageIcon('/task.png')] + +openDialog = fileChooser(fileSelectionMode: JFileChooser.DIRECTORIES_ONLY) + +// event methods +displayProject = { evt = null -> + def project= evt?.newLeadSelectionPath?.lastPathComponent?.userObject + issueTextArea.text = "" + if (!project) return + + if (!projectListModels[(project.name)]) { + def model = new DefaultListModel() + project.eachIssue { model.addElement(it) } + projectListModels[(project.name)] = model + } + + issueList.setModel(projectListModels[(project.name)]) +} + +displayIssue = { evt = null -> + if (issueList.selectedValue) + issueTextArea.text = issueList.selectedValue.text +} + frame = application(title:'Personal Issue Tracker', locationRelativeTo: null, //size:[320,480], @@ -13,8 +55,65 @@ frame = application(title:'Personal Issue Tracker', imageIcon('/griffon-icon-32x32.png').image, imageIcon('/griffon-icon-16x16.png').image] ) { - // MENU GOES HERE - panel(layout: new MigLayout('insets 5 5 5 5')) { - scrollPane() + + borderLayout() + + // main menu + menuBar() { + menu("File") { + menuItem('Open...', actionPerformed: { + def projectDir + if (openDialog.showOpenDialog(frame) != + JFileChooser.APPROVE_OPTION) return + + projectDir = openDialog.selectedFile + model.rootProject = new FileProject(projectDir) + }) + } + } + + // main split view + splitPane(orientation: JSplitPane.HORIZONTAL_SPLIT, + dividerLocation: 200) { + + // tree view of projects + scrollPane(constraints: "left") { + treeCellRenderer = new DefaultTreeCellRenderer() + treeCellRenderer.leafIcon = treeCellRenderer.closedIcon + + projectTree = tree(cellRenderer: treeCellRenderer, + model: bind(source: model, sourceProperty: 'rootProject', + sourceValue: { + if (model.rootProject) { + projectTree.rootVisible = model.rootProject.issues.size() + new DefaultTreeModel(makeNodes(model.rootProject)) + } else new DefaultTreeModel() + }), + valueChanged: displayProject) + projectTree.selectionModel.selectionMode = + TreeSelectionModel.SINGLE_TREE_SELECTION + } + + // split between issue list and issue details + splitPane(orientation: JSplitPane.VERTICAL_SPLIT, + dividerLocation: 200, constraints: "") { + + scrollPane(constraints: "top") { + issueList = list( + cellRenderer: new IssueListCellRenderer( + issueIcons: categoryIcons), + selectionMode: ListSelectionModel.SINGLE_SELECTION, + valueChanged: displayIssue) + } + scrollPane(constraints: "bottom") { + issueTextArea = textArea() + } + } } } + +def makeNodes(Project project) { + def rootNode = new DefaultMutableTreeNode(project) + project.eachProject { rootNode.add(makeNodes(it)) } + return rootNode +} diff --git a/pit-swing/session.vim b/pit-swing/session.vim index 3f03cf0..e3a1906 100644 --- a/pit-swing/session.vim +++ b/pit-swing/session.vim @@ -32,9 +32,14 @@ if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' let s:wipebuf = bufnr('%') endif set shortmess=aoO -badd +7 griffon-app/models/com/jdbernard/pit/swing/PITModel.groovy -badd +0 griffon-app/controllers/com/jdbernard/pit/swing/PITController.groovy +badd +1 griffon-app/models/com/jdbernard/pit/swing/PITModel.groovy +badd +1 griffon-app/controllers/com/jdbernard/pit/swing/PITController.groovy badd +18 griffon-app/views/com/jdbernard/pit/swing/PITView.groovy +badd +0 src/com/jdbernard/pit/IssueTreeCellRenderer.groovy +badd +3 griffon-app/conf/Application.groovy +badd +0 griffon-app/conf/Config.groovy +badd +3 src/com/jdbernard/pit/swing/IssueListCellRenderer.groovy +badd +3 src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy args griffon-app/models/com/jdbernard/pit/swing/PITModel.groovy edit griffon-app/models/com/jdbernard/pit/swing/PITModel.groovy set splitbelow splitright @@ -50,9 +55,9 @@ set nosplitbelow set nosplitright wincmd t set winheight=1 winwidth=1 -exe '1resize ' . ((&lines * 19 + 40) / 81) +exe '1resize ' . ((&lines * 13 + 30) / 60) exe 'vert 1resize ' . ((&columns * 91 + 91) / 182) -exe '2resize ' . ((&lines * 59 + 40) / 81) +exe '2resize ' . ((&lines * 43 + 30) / 60) exe 'vert 2resize ' . ((&columns * 91 + 91) / 182) exe 'vert 3resize ' . ((&columns * 90 + 91) / 182) argglobal @@ -151,7 +156,7 @@ setlocal nowinfixwidth setlocal wrap setlocal wrapmargin=0 silent! normal! zE -let s:l = 1 - ((0 * winheight(0) + 9) / 19) +let s:l = 1 - ((0 * winheight(0) + 6) / 13) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt @@ -159,7 +164,7 @@ normal! zt normal! 030l wincmd w argglobal -edit griffon-app/models/com/jdbernard/pit/swing/PITModel.groovy +edit griffon-app/views/com/jdbernard/pit/swing/PITView.groovy setlocal keymap= setlocal noarabic setlocal autoindent @@ -255,12 +260,12 @@ setlocal nowinfixwidth setlocal wrap setlocal wrapmargin=0 silent! normal! zE -let s:l = 1 - ((0 * winheight(0) + 29) / 59) +let s:l = 40 - ((39 * winheight(0) + 21) / 43) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt -1 -normal! 030l +40 +normal! 0 wincmd w argglobal edit griffon-app/controllers/com/jdbernard/pit/swing/PITController.groovy @@ -359,17 +364,353 @@ setlocal nowinfixwidth setlocal wrap setlocal wrapmargin=0 silent! normal! zE -let s:l = 1 - ((0 * winheight(0) + 39) / 79) +let s:l = 11 - ((10 * winheight(0) + 28) / 57) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt -1 +11 +normal! 044l +wincmd w +2wincmd w +exe '1resize ' . ((&lines * 13 + 30) / 60) +exe 'vert 1resize ' . ((&columns * 91 + 91) / 182) +exe '2resize ' . ((&lines * 43 + 30) / 60) +exe 'vert 2resize ' . ((&columns * 91 + 91) / 182) +exe 'vert 3resize ' . ((&columns * 90 + 91) / 182) +tabedit griffon-app/conf/Application.groovy +set splitbelow splitright +wincmd _ | wincmd | +vsplit +1wincmd h +wincmd _ | wincmd | +split +1wincmd k +wincmd w +wincmd w +set nosplitbelow +set nosplitright +wincmd t +set winheight=1 winwidth=1 +exe '1resize ' . ((&lines * 28 + 30) / 60) +exe 'vert 1resize ' . ((&columns * 91 + 91) / 182) +exe '2resize ' . ((&lines * 28 + 30) / 60) +exe 'vert 2resize ' . ((&columns * 91 + 91) / 182) +exe 'vert 3resize ' . ((&columns * 90 + 91) / 182) +argglobal +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal balloonexpr= +setlocal nobinary +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinwords=if,else,while,do,for,switch +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=/*%s*/ +setlocal complete=.,w,b,u,t,i +setlocal completefunc= +setlocal nocopyindent +setlocal nocursorcolumn +setlocal nocursorline +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat= +setlocal expandtab +if &filetype != 'groovy' +setlocal filetype=groovy +endif +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=tcq +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal grepprg= +setlocal iminsert=2 +setlocal imsearch=2 +setlocal include= +setlocal includeexpr= +setlocal indentexpr= +setlocal indentkeys=0{,0},:,0#,!^F,o,O,e +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255 +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal nolist +setlocal makeprg= +setlocal matchpairs=(:),{:},[:] +setlocal nomodeline +setlocal modifiable +setlocal nrformats=octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal shiftwidth=4 +setlocal noshortname +setlocal nosmartindent +setlocal softtabstop=0 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal statusline= +setlocal suffixesadd= +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'groovy' +setlocal syntax=groovy +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=0 +setlocal thesaurus= +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let s:l = 16 - ((15 * winheight(0) + 14) / 28) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +16 +normal! 08l +wincmd w +argglobal +edit src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal balloonexpr= +setlocal nobinary +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinwords=if,else,while,do,for,switch +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=/*%s*/ +setlocal complete=.,w,b,u,t,i +setlocal completefunc= +setlocal nocopyindent +setlocal nocursorcolumn +setlocal nocursorline +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat= +setlocal expandtab +if &filetype != 'groovy' +setlocal filetype=groovy +endif +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=tcq +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal grepprg= +setlocal iminsert=2 +setlocal imsearch=2 +setlocal include= +setlocal includeexpr= +setlocal indentexpr= +setlocal indentkeys=0{,0},:,0#,!^F,o,O,e +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255 +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal nolist +setlocal makeprg= +setlocal matchpairs=(:),{:},[:] +setlocal nomodeline +setlocal modifiable +setlocal nrformats=octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal shiftwidth=4 +setlocal noshortname +setlocal nosmartindent +setlocal softtabstop=0 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal statusline= +setlocal suffixesadd= +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'groovy' +setlocal syntax=groovy +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=0 +setlocal thesaurus= +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let s:l = 15 - ((14 * winheight(0) + 14) / 28) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +15 +normal! 023l +wincmd w +argglobal +edit griffon-app/conf/Config.groovy +setlocal keymap= +setlocal noarabic +setlocal autoindent +setlocal balloonexpr= +setlocal nobinary +setlocal bufhidden= +setlocal buflisted +setlocal buftype= +setlocal nocindent +setlocal cinkeys=0{,0},0),:,0#,!^F,o,O,e +setlocal cinoptions= +setlocal cinwords=if,else,while,do,for,switch +setlocal comments=s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:- +setlocal commentstring=/*%s*/ +setlocal complete=.,w,b,u,t,i +setlocal completefunc= +setlocal nocopyindent +setlocal nocursorcolumn +setlocal nocursorline +setlocal define= +setlocal dictionary= +setlocal nodiff +setlocal equalprg= +setlocal errorformat= +setlocal expandtab +if &filetype != 'groovy' +setlocal filetype=groovy +endif +setlocal foldcolumn=0 +setlocal foldenable +setlocal foldexpr=0 +setlocal foldignore=# +setlocal foldlevel=0 +setlocal foldmarker={{{,}}} +setlocal foldmethod=manual +setlocal foldminlines=1 +setlocal foldnestmax=20 +setlocal foldtext=foldtext() +setlocal formatexpr= +setlocal formatoptions=tcq +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s* +setlocal grepprg= +setlocal iminsert=2 +setlocal imsearch=2 +setlocal include= +setlocal includeexpr= +setlocal indentexpr= +setlocal indentkeys=0{,0},:,0#,!^F,o,O,e +setlocal noinfercase +setlocal iskeyword=@,48-57,_,192-255 +setlocal keywordprg= +setlocal nolinebreak +setlocal nolisp +setlocal nolist +setlocal makeprg= +setlocal matchpairs=(:),{:},[:] +setlocal nomodeline +setlocal modifiable +setlocal nrformats=octal,hex +set number +setlocal number +setlocal numberwidth=4 +setlocal omnifunc= +setlocal path= +setlocal nopreserveindent +setlocal nopreviewwindow +setlocal quoteescape=\\ +setlocal noreadonly +setlocal norightleft +setlocal rightleftcmd=search +setlocal noscrollbind +setlocal shiftwidth=4 +setlocal noshortname +setlocal nosmartindent +setlocal softtabstop=0 +setlocal nospell +setlocal spellcapcheck=[.?!]\\_[\\])'\"\ \ ]\\+ +setlocal spellfile= +setlocal spelllang=en +setlocal statusline= +setlocal suffixesadd= +setlocal swapfile +setlocal synmaxcol=3000 +if &syntax != 'groovy' +setlocal syntax=groovy +endif +setlocal tabstop=4 +setlocal tags= +setlocal textwidth=0 +setlocal thesaurus= +setlocal nowinfixheight +setlocal nowinfixwidth +setlocal wrap +setlocal wrapmargin=0 +silent! normal! zE +let s:l = 56 - ((55 * winheight(0) + 28) / 57) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +56 normal! 0 wincmd w 2wincmd w -exe '1resize ' . ((&lines * 19 + 40) / 81) +exe '1resize ' . ((&lines * 28 + 30) / 60) exe 'vert 1resize ' . ((&columns * 91 + 91) / 182) -exe '2resize ' . ((&lines * 59 + 40) / 81) +exe '2resize ' . ((&lines * 28 + 30) / 60) exe 'vert 2resize ' . ((&columns * 91 + 91) / 182) exe 'vert 3resize ' . ((&columns * 90 + 91) / 182) tabnext 1 diff --git a/pit-swing/src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy b/pit-swing/src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy new file mode 100644 index 0000000..5b6c142 --- /dev/null +++ b/pit-swing/src/main/com/jdbernard/pit/swing/IssueListCellRenderer.groovy @@ -0,0 +1,20 @@ +package com.jdbernard.pit.swing + +import java.awt.Component +import javax.swing.Icon +import javax.swing.JList +import javax.swing.DefaultListCellRenderer + +public class IssueListCellRenderer extends DefaultListCellRenderer { + + Map issueIcons + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean selected, boolean hasFocus) { + def component = super.getListCellRendererComponent(list, value, index, + selected, hasFocus) + if (issueIcons[(value.category)]) + component.setIcon(issueIcons[(value.category)]) + return component + } +}