diff --git a/gui/griffon-app/conf/Config.groovy b/gui/griffon-app/conf/Config.groovy index a1495f1a..6f751b89 100644 --- a/gui/griffon-app/conf/Config.groovy +++ b/gui/griffon-app/conf/Config.groovy @@ -156,4 +156,9 @@ mvcGroups { view = 'com.muwire.gui.CollectionsToolView' controller = 'com.muwire.gui.CollectionsToolController' } + 'collection-tab' { + model = 'com.muwire.gui.CollectionTabModel' + view = 'com.muwire.gui.CollectionTabView' + controller = 'com.muwire.gui.CollectionTabController' + } } diff --git a/gui/griffon-app/controllers/com/muwire/gui/CollectionTabController.groovy b/gui/griffon-app/controllers/com/muwire/gui/CollectionTabController.groovy new file mode 100644 index 00000000..1775d68d --- /dev/null +++ b/gui/griffon-app/controllers/com/muwire/gui/CollectionTabController.groovy @@ -0,0 +1,18 @@ +package com.muwire.gui + +import griffon.core.artifact.GriffonController +import griffon.core.controller.ControllerAction +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor +import javax.annotation.Nonnull + +@ArtifactProviderFor(GriffonController) +class CollectionTabController { + @MVCMember @Nonnull + CollectionTabModel model + + @ControllerAction + void click() { + model.clickCount++ + } +} \ No newline at end of file diff --git a/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy b/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy index 99587c42..09f4ffc2 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy @@ -163,4 +163,18 @@ class SearchTabController { params['core'] = core mvcGroup.createMVCGroup("fetch-certificates", params) } + + @ControllerAction + void viewCollections() { + UIResultEvent event = view.getSelectedResult() + if (event == null || event.collections.isEmpty()) + return + + def params = [:] + params['fileName'] = event.name + params['eventBus'] = mvcGroup.parentGroup.model.core.eventBus + params['collections'] = event.collections.collect() + params['uuid'] = UUID.randomUUID() + mvcGroup.createMVCGroup("collection-tab", params) + } } \ No newline at end of file diff --git a/gui/griffon-app/i18n/messages.properties b/gui/griffon-app/i18n/messages.properties index f2b4b32a..42767f76 100644 --- a/gui/griffon-app/i18n/messages.properties +++ b/gui/griffon-app/i18n/messages.properties @@ -237,6 +237,8 @@ PLEASE_SELECT_ONE_FILE_DETAILS=Please select only one file to view it's details PLEASE_SELECT_ONE_FILE_FOLDER=Please select only one file to open it's containing folder COPY_PASTE_SERVER_ADDRESS=Copy/paste the address of the server here INVALID_SERVER_ADDRESS=Invalid server address + + ## Search tab GROUP_BY=Group by @@ -253,6 +255,7 @@ DISTRUST=Distrust DIRECT_SOURCES=Direct Sources POSSIBLE_SOURCES=Possible Sources DOWNLOAD_SEQUENTIALLY=Download sequentially +VIEW_COLLECTIONS=View Collections # results table (group by file) CHAT_HOSTS=Chat Hosts diff --git a/gui/griffon-app/models/com/muwire/gui/CollectionTabModel.groovy b/gui/griffon-app/models/com/muwire/gui/CollectionTabModel.groovy new file mode 100644 index 00000000..ac0486c4 --- /dev/null +++ b/gui/griffon-app/models/com/muwire/gui/CollectionTabModel.groovy @@ -0,0 +1,37 @@ +package com.muwire.gui + +import com.muwire.core.EventBus +import com.muwire.core.collections.CollectionFetchedEvent +import com.muwire.core.collections.FileCollection +import com.muwire.core.collections.FileCollectionItem + +import griffon.core.artifact.GriffonModel +import griffon.transform.Observable +import griffon.metadata.ArtifactProviderFor + +@ArtifactProviderFor(GriffonModel) +class CollectionTabModel { + String fileName + EventBus eventBus + List collections + List items + @Observable String comment + UUID uuid + + void mvcGroupInit(Map args) { + eventBus.register(CollectionFetchedEvent.class, this) + } + + void mvcGroupDestroy() { + eventBus.unregister(CollectionFetchedEvent.class, this) + } + + void onCollectionFetchedEvent(CollectionFetchedEvent e) { + if (uuid != e.uuid) + return + runInsideUIAsync { + collections.add(e.collection) + // TODO: refresh tables + } + } +} \ No newline at end of file diff --git a/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy b/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy index 810bf37f..ae717dd4 100644 --- a/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy +++ b/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy @@ -87,6 +87,7 @@ class MainFrameModel { def results = new ConcurrentHashMap<>() def browses = new ConcurrentHashSet() + def collections = new ConcurrentHashSet() def downloads = [] def uploads = [] boolean treeVisible = true diff --git a/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy b/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy index 2ad0a2ee..0a5d8faf 100644 --- a/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy +++ b/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy @@ -26,6 +26,7 @@ class SearchTabModel { @Observable boolean viewCertificatesActionEnabled @Observable boolean chatActionEnabled @Observable boolean subscribeActionEnabled + @Observable boolean viewCollectionsActionEnabled @Observable boolean groupedByFile Core core diff --git a/gui/griffon-app/views/com/muwire/gui/CollectionTabView.groovy b/gui/griffon-app/views/com/muwire/gui/CollectionTabView.groovy new file mode 100644 index 00000000..cdc34b9a --- /dev/null +++ b/gui/griffon-app/views/com/muwire/gui/CollectionTabView.groovy @@ -0,0 +1,58 @@ +package com.muwire.gui + +import griffon.core.artifact.GriffonView +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor +import javax.swing.SwingConstants + +import java.awt.BorderLayout + +import javax.annotation.Nonnull + +@ArtifactProviderFor(GriffonView) +class CollectionTabView { + @MVCMember @Nonnull + FactoryBuilderSupport builder + @MVCMember @Nonnull + CollectionTabModel model + + def parent + def p + + void initUI() { + p = builder.panel {} + } + + void mvcGroupInit(Map args) { + def mainFrameGroup = application.mvcGroupManager.findGroup("MainFrame") + mainFrameGroup.model.collections.add(model.uuid.toString()) + parent = mainFrameGroup.view.builder.getVariable("result-tabs") + parent.addTab(model.uuid.toString(), p) + + int index = parent.indexOfComponent(p) + parent.setSelectedIndex(index) + + def tabPanel + builder.with { + tabPanel = panel { + borderLayout() + panel { + label(text : model.fileName, constraints : BorderLayout.CENTER) + } + button(icon : imageIcon("/close_tab.png"), preferredSize : [20,20], constraints : BorderLayout.EAST, // TODO: in osx is probably WEST + actionPerformed : closeTab ) + } + } + + parent.setTabComponentAt(index, tabPanel) + } + + def closeTab = { + def mainFrameGroup = application.mvcGroupManager.findGroup("MainFrame") + mainFrameGroup.model.collections.remove(model.uuid.toString()) + + int index = parent.indexOfTab(model.uuid.toString()) + parent.removeTabAt(index) + mvcGroup.destroy() + } +} \ No newline at end of file diff --git a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy index 8998ab6f..e563b6d8 100644 --- a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy @@ -1542,7 +1542,7 @@ class MainFrameView { for (int i = 0; i < count; i++) settings.openTabs.add(tabbedPane.getTitleAt(i)) settings.openTabs.removeAll(model.browses) - + settings.openTabs.removeAll(model.collections) JFrame mainFrame = builder.getVariable("main-frame") settings.mainFrameX = mainFrame.getSize().width diff --git a/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy b/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy index 0c074166..81e65a83 100644 --- a/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy @@ -118,8 +118,9 @@ class SearchTabView { button(text : trans("DOWNLOAD"), enabled : bind {model.downloadActionEnabled}, constraints : gbc(gridx : 1, gridy:0), downloadAction) button(text : trans("VIEW_COMMENT"), enabled : bind {model.viewCommentActionEnabled}, constraints : gbc(gridx:2, gridy:0), showCommentAction) button(text : trans("VIEW_CERTIFICATES"), enabled : bind {model.viewCertificatesActionEnabled}, constraints : gbc(gridx:3, gridy:0), viewCertificatesAction) - label(text : trans("DOWNLOAD_SEQUENTIALLY"), constraints : gbc(gridx: 4, gridy: 0, weightx : 80, anchor : GridBagConstraints.LINE_END)) - sequentialDownloadCheckbox = checkBox(constraints : gbc(gridx : 5, gridy: 0, anchor : GridBagConstraints.LINE_END), + button(text : trans("VIEW_COLLECTIONS"), enabled : bind {model.viewCollectionsActionEnabled}, constraints : gbc(gridx:4, gridy:0), viewCollectionsAction) + label(text : trans("DOWNLOAD_SEQUENTIALLY"), constraints : gbc(gridx: 5, gridy: 0, weightx : 80, anchor : GridBagConstraints.LINE_END)) + sequentialDownloadCheckbox = checkBox(constraints : gbc(gridx : 6, gridy: 0, anchor : GridBagConstraints.LINE_END), selected : false, enabled : bind {model.downloadActionEnabled}) } } @@ -220,11 +221,13 @@ class SearchTabView { panel (constraints : BorderLayout.SOUTH) { gridLayout(rows : 1, cols : 2) panel (border : etchedBorder()) { - button(text : trans("BROWSE_HOST"), enabled : bind {model.browseActionEnabled}, browseAction) - button(text : trans("SUBSCRIBE"), enabled : bind {model.subscribeActionEnabled}, subscribeAction) - button(text : trans("CHAT"), enabled : bind{model.chatActionEnabled}, chatAction) - button(text : trans("VIEW_COMMENT"), enabled : bind {model.viewCommentActionEnabled}, showCommentAction) - button(text : trans("VIEW_CERTIFICATES"), enabled : bind {model.viewCertificatesActionEnabled}, viewCertificatesAction) + gridBagLayout() + button(text : trans("BROWSE_HOST"), enabled : bind {model.browseActionEnabled}, constraints : gbc(gridx : 0, gridy : 0), browseAction) + button(text : trans("SUBSCRIBE"), enabled : bind {model.subscribeActionEnabled}, constraints : gbc(gridx : 1, gridy : 0), subscribeAction) + button(text : trans("CHAT"), enabled : bind{model.chatActionEnabled}, constraints : gbc(gridx : 2, gridy : 0), chatAction) + button(text : trans("VIEW_COMMENT"), enabled : bind {model.viewCommentActionEnabled}, constraints : gbc(gridx : 3, gridy : 0), showCommentAction) + button(text : trans("VIEW_CERTIFICATES"), enabled : bind {model.viewCertificatesActionEnabled}, constraints : gbc(gridx : 4, gridy : 0), viewCertificatesAction) + button(text : trans("VIEW_COLLECTIONS"), enabled : bind {model.viewCollectionsActionEnabled}, constraints : gbc(gridx : 5, gridy : 0), viewCollectionsAction) } panel (border : etchedBorder()) { button(text : trans("TRUST_VERB"), enabled: bind {model.trustButtonsEnabled }, trustAction) @@ -331,10 +334,12 @@ class SearchTabView { model.viewCommentActionEnabled = false model.viewCertificatesActionEnabled = false model.subscribeActionEnabled = false + model.viewCollectionsActionEnabled = false return } else { model.viewCommentActionEnabled = result.comment != null model.viewCertificatesActionEnabled = result.certificates > 0 + model.viewCollectionsActionEnabled = !result.collections.isEmpty() } }) @@ -378,6 +383,7 @@ class SearchTabView { model.browseActionEnabled = false model.chatActionEnabled = false model.viewCertificatesActionEnabled = false + model.viewCollectionsActionEnabled = false return } model.downloadActionEnabled = true @@ -413,6 +419,7 @@ class SearchTabView { model.chatActionEnabled = false model.subscribeActionEnabled = false model.viewCertificatesActionEnabled = false + model.viewCollectionsActionEnabled = false model.trustButtonsEnabled = false model.viewCommentActionEnabled = false return @@ -424,6 +431,7 @@ class SearchTabView { model.trustButtonsEnabled = true model.viewCommentActionEnabled = e.comment != null model.viewCertificatesActionEnabled = e.certificates > 0 + model.viewCollectionsActionEnabled = !e.collections.isEmpty() }) if (settings.groupByFile) @@ -471,6 +479,13 @@ class SearchTabView { viewCerts.addActionListener({mvcGroup.controller.viewCertificates()}) menu.add(viewCerts) } + + // view collections if any + if (model.viewCollectionsActionEnabled) { + JMenuItem viewCols = new JMenuItem(trans("VIEW_COLLECTIONS")) + viewCols.addActionListener({mvcGroup.controller.viewCollections()}) + menu.add(viewCols) + } } if (showMenu) menu.show(e.getComponent(), e.getX(), e.getY())