diff --git a/services/src/main/groovy/jd/gui/service/indexer/MetainfServiceFileIndexerProvider.groovy b/services/src/main/groovy/jd/gui/service/indexer/MetainfServiceFileIndexerProvider.groovy index 4c627a8a..c98add11 100644 --- a/services/src/main/groovy/jd/gui/service/indexer/MetainfServiceFileIndexerProvider.groovy +++ b/services/src/main/groovy/jd/gui/service/indexer/MetainfServiceFileIndexerProvider.groovy @@ -29,7 +29,13 @@ class MetainfServiceFileIndexerProvider extends AbstractIndexerProvider { def index = indexes.getIndex('typeReferences') entry.inputStream.text.eachLine { String line -> - index.get(line).add(entry) + def trim = line.trim() + + if (trim && (trim.charAt(0) != '#')) { + def internalTypeName = trim.replace('.', '/') + + index.get(internalTypeName).add(entry) + } } } } diff --git a/services/src/main/groovy/jd/gui/service/treenode/MetainfServiceFileTreeNodeFactoryProvider.groovy b/services/src/main/groovy/jd/gui/service/treenode/MetainfServiceFileTreeNodeFactoryProvider.groovy index 22b23ab4..2cd479a8 100644 --- a/services/src/main/groovy/jd/gui/service/treenode/MetainfServiceFileTreeNodeFactoryProvider.groovy +++ b/services/src/main/groovy/jd/gui/service/treenode/MetainfServiceFileTreeNodeFactoryProvider.groovy @@ -5,9 +5,20 @@ package jd.gui.service.treenode +import jd.gui.api.API +import jd.gui.api.feature.PageCreator +import jd.gui.api.feature.UriGettable +import jd.gui.api.model.Container +import jd.gui.view.component.OneTypeReferenceByLinePage +import jd.gui.view.data.TreeNodeBean + +import javax.swing.ImageIcon +import javax.swing.JComponent +import javax.swing.tree.DefaultMutableTreeNode import java.util.regex.Pattern -class MetainfServiceFileTreeNodeFactoryProvider extends TextFileTreeNodeFactoryProvider { +class MetainfServiceFileTreeNodeFactoryProvider extends FileTreeNodeFactoryProvider { + static final ImageIcon ICON = new ImageIcon(TextFileTreeNodeFactoryProvider.class.classLoader.getResource('images/ascii_obj.png')) /** * @return local + optional external selectors @@ -18,4 +29,20 @@ class MetainfServiceFileTreeNodeFactoryProvider extends TextFileTreeNodeFactoryP * @return external or local path pattern */ Pattern getPathPattern() { externalPathPattern ?: ~/META-INF\/services\/[^\/]+/ } + + public T make(API api, Container.Entry entry) { + int lastSlashIndex = entry.path.lastIndexOf('/') + def name = entry.path.substring(lastSlashIndex+1) + return new TreeNode(entry, new TreeNodeBean(label:name, icon:ICON, tip:"Location: $entry.uri.path")) + } + + static class TreeNode extends FileTreeNodeFactoryProvider.TreeNode implements PageCreator { + TreeNode(Container.Entry entry, Object userObject) { + super(entry, userObject) + } + // --- PageCreator --- // + public T createPage(API api) { + return new OneTypeReferenceByLinePage(api, entry) + } + } } diff --git a/services/src/main/groovy/jd/gui/view/component/OneTypeReferenceByLinePage.groovy b/services/src/main/groovy/jd/gui/view/component/OneTypeReferenceByLinePage.groovy new file mode 100644 index 00000000..019c6ed0 --- /dev/null +++ b/services/src/main/groovy/jd/gui/view/component/OneTypeReferenceByLinePage.groovy @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2008-2015 Emmanuel Dupuy + * This program is made available under the terms of the GPLv3 License. + */ +package jd.gui.view.component + +import jd.gui.api.API +import jd.gui.api.feature.IndexesChangeListener +import jd.gui.api.feature.UriGettable +import jd.gui.api.model.Container +import jd.gui.api.model.Indexes + +import java.awt.Point + +class OneTypeReferenceByLinePage extends TypeReferencePage implements UriGettable, IndexesChangeListener { + protected API api + protected Container.Entry entry + protected Collection collectionOfIndexes + + OneTypeReferenceByLinePage(API api, Container.Entry entry) { + this.api = api + this.entry = entry + // Load content file + def text = entry.inputStream.text.replace('\r\n', '\n').replace('\r', '\n') + // Create hyperlinks + int offset = 0 + + text.eachLine { String line -> + def trim = line.trim() + + if (trim) { + int startIndex = offset + line.indexOf(trim) + int endIndex = startIndex + trim.length() + def internalTypeName = trim.replace('.', '/') + + addHyperlink(new TypeReferencePage.TypeHyperlinkData(startIndex, endIndex, internalTypeName)) + } + + offset += line.length() + 1 + } + // Display + setText(text) + // Show hyperlinks + indexesChanged(api.collectionOfIndexes) + } + + protected boolean isHyperlinkEnabled(HyperlinkPage.HyperlinkData hyperlinkData) { hyperlinkData.enabled } + + protected void openHyperlink(int x, int y, HyperlinkPage.HyperlinkData hyperlinkData) { + if (hyperlinkData.enabled) { + // Save current position in history + def location = textArea.getLocationOnScreen() + int offset = textArea.viewToModel(new Point(x-location.x as int, y-location.y as int)) + def uri = entry.uri + api.addURI(new URI(uri.scheme, uri.authority, uri.path, 'position=' + offset, null)) + + // Open link + def internalTypeName = hyperlinkData.internalTypeName + def entries = collectionOfIndexes?.collect { it.getIndex('typeDeclarations')?.get(internalTypeName) }.flatten().grep { it!=null } + def rootUri = entry.container.root.uri.toString() + def sameContainerEntries = entries?.grep { it.uri.toString().startsWith(rootUri) } + + if (sameContainerEntries) { + api.openURI(x, y, sameContainerEntries, null, hyperlinkData.internalTypeName) + } else if (entries) { + api.openURI(x, y, entries, null, hyperlinkData.internalTypeName) + } + } + } + + // --- UriGettable --- // + URI getUri() { entry.uri } + + // --- ContentSavable --- // + String getFileName() { + def path = entry.path + int index = path.lastIndexOf('/') + return path.substring(index+1) + } + + // --- IndexesChangeListener --- // + void indexesChanged(Collection collectionOfIndexes) { + // Update the list of containers + this.collectionOfIndexes = collectionOfIndexes + // Refresh links + boolean refresh = false + + for (def entry : hyperlinks.entrySet()) { + def data = entry.value + def internalTypeName = data.internalTypeName + boolean enabled = collectionOfIndexes.find { it.getIndex('typeDeclarations')?.get(internalTypeName) } != null + + if (data.enabled != enabled) { + data.enabled = enabled + refresh = true + } + } + + if (refresh) { + textArea.repaint() + } + } +}