diff --git a/pt.iscte.pidesco.feature/.project b/pt.iscte.pidesco.feature/.project new file mode 100644 index 0000000..cf11181 --- /dev/null +++ b/pt.iscte.pidesco.feature/.project @@ -0,0 +1,17 @@ + + + pt.iscte.pidesco.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/pt.iscte.pidesco.feature/build.properties b/pt.iscte.pidesco.feature/build.properties new file mode 100644 index 0000000..64f93a9 --- /dev/null +++ b/pt.iscte.pidesco.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/pt.iscte.pidesco.feature/feature.xml b/pt.iscte.pidesco.feature/feature.xml new file mode 100644 index 0000000..08aaba5 --- /dev/null +++ b/pt.iscte.pidesco.feature/feature.xml @@ -0,0 +1,40 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + diff --git a/pt.iscte.pidesco.javaeditor/.classpath b/pt.iscte.pidesco.javaeditor/.classpath new file mode 100644 index 0000000..e8ea977 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/pt.iscte.pidesco.javaeditor/.project b/pt.iscte.pidesco.javaeditor/.project new file mode 100644 index 0000000..35eb5b1 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/.project @@ -0,0 +1,28 @@ + + + pt.iscte.pidesco.javaeditor + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/pt.iscte.pidesco.javaeditor/.settings/org.eclipse.jdt.core.prefs b/pt.iscte.pidesco.javaeditor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..11f6e46 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/pt.iscte.pidesco.javaeditor/META-INF/MANIFEST.MF b/pt.iscte.pidesco.javaeditor/META-INF/MANIFEST.MF new file mode 100644 index 0000000..efe7f8a --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/META-INF/MANIFEST.MF @@ -0,0 +1,22 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Simple Java Editor +Bundle-SymbolicName: pt.iscte.pidesco.javaeditor;singleton:=true +Bundle-Version: 1.1 +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.ui;bundle-version="0.0.0", + org.eclipse.core.resources;bundle-version="0.0.0", + org.eclipse.ui.console;bundle-version="0.0.0", + org.eclipse.jface.text;bundle-version="0.0.0", + org.eclipse.ui.editors;bundle-version="0.0.0", + org.eclipse.ui.ide;bundle-version="0.0.0", + org.eclipse.core.filesystem;bundle-version="0.0.0", + org.eclipse.jdt;bundle-version="3.10.0", + org.eclipse.jdt.core;bundle-version="3.10.0", + pt.iscte.pidesco.projectbrowser;bundle-version="0.1.0", + pt.iscte.pidesco;bundle-version="0.1.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-Vendor: pt.iscte.dcti +Export-Package: pt.iscte.pidesco.javaeditor.service +Bundle-Activator: pt.iscte.pidesco.javaeditor.internal.JavaEditorActivator +Bundle-ActivationPolicy: lazy diff --git a/pt.iscte.pidesco.javaeditor/build.properties b/pt.iscte.pidesco.javaeditor/build.properties new file mode 100644 index 0000000..d7cedad --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + images/,\ + about.ini diff --git a/pt.iscte.pidesco.javaeditor/images/blackboard.png b/pt.iscte.pidesco.javaeditor/images/blackboard.png new file mode 100644 index 0000000..ebba0d4 Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/blackboard.png differ diff --git a/pt.iscte.pidesco.javaeditor/images/browser.gif b/pt.iscte.pidesco.javaeditor/images/browser.gif new file mode 100644 index 0000000..229c391 Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/browser.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/iscte.png b/pt.iscte.pidesco.javaeditor/images/iscte.png new file mode 100644 index 0000000..a2c3323 Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/iscte.png differ diff --git a/pt.iscte.pidesco.javaeditor/images/javafile.gif b/pt.iscte.pidesco.javaeditor/images/javafile.gif new file mode 100644 index 0000000..200e5ed Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/javafile.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/javaproject.gif b/pt.iscte.pidesco.javaeditor/images/javaproject.gif new file mode 100644 index 0000000..0b27698 Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/javaproject.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/newfile.gif b/pt.iscte.pidesco.javaeditor/images/newfile.gif new file mode 100644 index 0000000..9d05088 Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/newfile.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/newfolder.gif b/pt.iscte.pidesco.javaeditor/images/newfolder.gif new file mode 100644 index 0000000..310eb18 Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/newfolder.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/newproj.gif b/pt.iscte.pidesco.javaeditor/images/newproj.gif new file mode 100644 index 0000000..bc85aaf Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/newproj.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/package_filter.gif b/pt.iscte.pidesco.javaeditor/images/package_filter.gif new file mode 100644 index 0000000..24fce6c Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/package_filter.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/projects.gif b/pt.iscte.pidesco.javaeditor/images/projects.gif new file mode 100644 index 0000000..0b27698 Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/projects.gif differ diff --git a/pt.iscte.pidesco.javaeditor/images/sync.gif b/pt.iscte.pidesco.javaeditor/images/sync.gif new file mode 100644 index 0000000..870934b Binary files /dev/null and b/pt.iscte.pidesco.javaeditor/images/sync.gif differ diff --git a/pt.iscte.pidesco.javaeditor/plugin.xml b/pt.iscte.pidesco.javaeditor/plugin.xml new file mode 100644 index 0000000..2c3fff1 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/plugin.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/PackageFocusFilter.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/PackageFocusFilter.java new file mode 100644 index 0000000..d38fda1 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/PackageFocusFilter.java @@ -0,0 +1,31 @@ +package pt.iscte.pidesco.javaeditor; + +import java.io.File; + +import pt.iscte.pidesco.javaeditor.internal.JavaEditorActivator; +import pt.iscte.pidesco.javaeditor.internal.JavaEditorServicesImpl; +import pt.iscte.pidesco.javaeditor.service.JavaEditorServices; +import pt.iscte.pidesco.projectbrowser.extensibility.ProjectBrowserFilter; +import pt.iscte.pidesco.projectbrowser.model.PackageElement; +import pt.iscte.pidesco.projectbrowser.model.SourceElement; + +public class PackageFocusFilter implements ProjectBrowserFilter { + + private JavaEditorServices services; + + public PackageFocusFilter() { + services = JavaEditorActivator.getInstance().getServices(); + } + + @Override + public boolean include(SourceElement element, PackageElement parent) { + File f = services.getOpenedFile(); + if(element.isPackage() && ((PackageElement) element).hasChild(f, true)) + return true; + else if (element.isClass() && parent.hasChild(f, false)) + return true; + + return false; + } + +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/PackageFocusTool.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/PackageFocusTool.java new file mode 100644 index 0000000..4312830 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/PackageFocusTool.java @@ -0,0 +1,44 @@ +package pt.iscte.pidesco.javaeditor; + +import java.io.File; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +import pt.iscte.pidesco.extensibility.PidescoServices; +import pt.iscte.pidesco.extensibility.PidescoTool; +import pt.iscte.pidesco.javaeditor.internal.JavaEditorActivator; +import pt.iscte.pidesco.javaeditor.service.JavaEditorListener; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserServices; + +public class PackageFocusTool implements PidescoTool { + + private static final String FILTER_ID = "pt.iscte.pidesco.javaeditor.packagefocus"; + + @Override + public void run(boolean selected) { + + BundleContext context = JavaEditorActivator.getInstance().getContext(); + + ServiceReference ref1 = context.getServiceReference(PidescoServices.class); + final PidescoServices services = context.getService(ref1); + + ServiceReference ref2 = context.getServiceReference(ProjectBrowserServices.class); + ProjectBrowserServices browser = context.getService(ref2); + + + if(selected) { + browser.activateFilter(FILTER_ID); + JavaEditorActivator.getInstance().addListener( + new JavaEditorListener.Adapter() { + @Override + public void fileOpened(File file) { + services.runTool(ProjectBrowserServices.REFRESH_TOOL_ID, true); + } + }); + } + else { + browser.deactivateFilter(FILTER_ID); + } + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Common.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Common.java new file mode 100644 index 0000000..20eb3c0 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Common.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.swt.SWT; + +public class Common { + public static IToken createToken(TokenColor color, boolean bold) { + if(bold) + return new Token(new TextAttribute(color.color, null, SWT.BOLD)); + else + return new Token(new TextAttribute(color.color)); + + } +} + diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Configuration.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Configuration.java new file mode 100644 index 0000000..8f713a2 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Configuration.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import java.util.Iterator; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; + + +public class Configuration extends SourceViewerConfiguration { +// private JavaCodeScanner tagScanner; + + public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { + return new String[] { + IDocument.DEFAULT_CONTENT_TYPE, + JavaCodePartitionScanner.JAVA_COMMENT}; + // JavaCodePartitionScanner.JAVA_CODE }; + } + + +// protected JavaCodeScanner getTagScanner() { +// if (tagScanner == null) { +// tagScanner = new JavaCodeScanner(); +// tagScanner.setDefaultReturnToken(Common.createToken(TokenColor.BLACK, false)); +// } +// return tagScanner; +// } + + @Override + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new IAnnotationHover() { + + @Override + public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) { + IDocument doc = sourceViewer.getDocument(); + String ret = ""; + for(Iterator it = sourceViewer.getAnnotationModel().getAnnotationIterator(); it.hasNext(); ) { + Annotation ann = (Annotation) it.next(); + int offset = sourceViewer.getAnnotationModel().getPosition(ann).offset; + try { + // ret += offset + " .. " + doc.getLineOffset(lineNumber) + " .. " + doc.getLineOffset(lineNumber+1); + if(offset >= doc.getLineOffset(lineNumber) && + (lineNumber == doc.getNumberOfLines()-1 || offset < doc.getLineOffset(lineNumber+1))) { + ret += ann.getText(); + // if(it.hasNext()) + // ret += "\n"; + break; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + + + } + return ret; + } + }; + } + + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + PresentationReconciler reconciler = new PresentationReconciler(); + + DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new JavaCommentsPartitionScanner()); + reconciler.setDamager(dr, JavaCodePartitionScanner.JAVA_COMMENT); + reconciler.setRepairer(dr, JavaCodePartitionScanner.JAVA_COMMENT); + + DefaultDamagerRepairer dr2 = new DefaultDamagerRepairer(new JavaCodeScanner()); + reconciler.setDamager(dr2, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setRepairer(dr2, IDocument.DEFAULT_CONTENT_TYPE); + + NonRuleBasedDamagerRepairer ndr = + new NonRuleBasedDamagerRepairer(new TextAttribute(TokenColor.COMMENT.color)); + reconciler.setDamager(ndr, JavaCodePartitionScanner.JAVA_COMMENT); + reconciler.setRepairer(ndr, JavaCodePartitionScanner.JAVA_COMMENT); + + return reconciler; + } + +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/IntLiteralDetector.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/IntLiteralDetector.java new file mode 100644 index 0000000..80fd051 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/IntLiteralDetector.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.jface.text.rules.IWordDetector; + +public class IntLiteralDetector implements IWordDetector { + + public boolean isWordStart(char c) { + return Character.isDigit(c) || c == '-'; + } + + public boolean isWordPart(char c) { + return Character.isDigit(c); + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/IntRule.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/IntRule.java new file mode 100644 index 0000000..4fdfa78 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/IntRule.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; + +public class IntRule implements IRule { + + /** Internal setting for the un-initialized column constraint */ + protected static final int UNDEFINED= -1; + /** The token to be returned when this rule is successful */ + protected IToken fToken; + /** The column constraint */ + protected int fColumn= UNDEFINED; + + /** + * Creates a rule which will return the specified + * token when a numerical sequence is detected. + * + * @param token the token to be returned + */ + public IntRule(IToken token) { + Assert.isNotNull(token); + fToken= token; + } + + /** + * Sets a column constraint for this rule. If set, the rule's token + * will only be returned if the pattern is detected starting at the + * specified column. If the column is smaller then 0, the column + * constraint is considered removed. + * + * @param column the column in which the pattern starts + */ + public void setColumnConstraint(int column) { + if (column < 0) + column= UNDEFINED; + fColumn= column; + } + + /* + * @see IRule#evaluate(ICharacterScanner) + */ + public IToken evaluate(ICharacterScanner scanner) { + int first = scanner.read(); + int c = first; + int i = 1; + if (Character.isDigit(c) || c == '-') { + if (fColumn == UNDEFINED || (fColumn == scanner.getColumn() - 1)) { + do { + c= scanner.read(); + if(i == 1 && first == '-' && !Character.isDigit(c)) { + scanner.unread(); + scanner.unread(); + return Token.UNDEFINED; + } + i++; + } while (Character.isDigit(c)); + scanner.unread(); + return fToken; + } + } + + scanner.unread(); + return Token.UNDEFINED; + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaClassProvider.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaClassProvider.java new file mode 100644 index 0000000..d8dcb59 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaClassProvider.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.FastPartitioner; +import org.eclipse.ui.editors.text.FileDocumentProvider; + + +public class JavaClassProvider extends FileDocumentProvider { + + protected IDocument createDocument(Object element) throws CoreException { + IDocument document = super.createDocument(element); + if (document != null) { + IDocumentPartitioner partitioner = + new FastPartitioner( + new JavaCodePartitionScanner(), + new String[] { +// JavaCodePartitionScanner.JAVA_CODE, + JavaCodePartitionScanner.JAVA_COMMENT }); + partitioner.connect(document); + document.setDocumentPartitioner(partitioner); + } + return document; + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCodePartitionScanner.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCodePartitionScanner.java new file mode 100644 index 0000000..e8a783b --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCodePartitionScanner.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.Token; + + +public class JavaCodePartitionScanner extends RuleBasedPartitionScanner { + public final static String JAVA_COMMENT = "__java_comment"; +// public final static String JAVA_CODE = "__java_code"; + + public JavaCodePartitionScanner() { + + IToken javaComment = new Token(JAVA_COMMENT); +// IToken javaCode = new Token(JAVA_CODE); + + IPredicateRule[] rules = new IPredicateRule[] { + new MultiLineRule("/*", "*/", javaComment), + new EndOfLineRule("//", javaComment) + }; + + setPredicateRules(rules); + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCodeScanner.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCodeScanner.java new file mode 100644 index 0000000..033ae0c --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCodeScanner.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWhitespaceDetector; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; + + +public class JavaCodeScanner extends RuleBasedScanner { + private final static String[] javaKeyword = + { "abstract", "continue", "for", "new", "switch", "assert", "default", + "goto", "package", "synchronized", "boolean", "do", "if", "private", + "this", "break", "double", "implements", "protected", "throw", + "byte", "else", "import", "public", "throws", "case", "enum", + "instanceof", "return", "transient", "catch", "extends", "int", + "short", "try", "char", "final", "interface", "static", "void", + "class", "finally", "long", "strictfp", "volatile", "const", "float", + "native", "super", "while"}; + + private static IToken comment = Common.createToken(TokenColor.COMMENT, false); + private static IToken javadoc = Common.createToken(TokenColor.COMMENT, true); + private static IToken string = Common.createToken(TokenColor.STRING, false); + private static IToken character = Common.createToken(TokenColor.CHAR, false); + private static IToken keyword = Common.createToken(TokenColor.KEYWORD, true); + private static IToken number = Common.createToken(TokenColor.NUMBER, true); + private static IToken id = Common.createToken(TokenColor.ID, true); + private static IToken trueLit = Common.createToken(TokenColor.TRUE, true); + private static IToken falseLit = Common.createToken(TokenColor.FALSE, true); + private static IToken nullLit = Common.createToken(TokenColor.NULL, true); + private static IToken defaultToken = Common.createToken(TokenColor.BLACK, false); + + public JavaCodeScanner() { + IRule[] rules = new IRule[] { + + new UniqueWordRule(trueLit, "true"), + new UniqueWordRule(falseLit, "false"), + new UniqueWordRule(nullLit, "null"), + + new EndOfLineRule("//", comment), + // new SingleLineRule("\\\\", "", comment), + new SingleLineRule("\"", "\"", string, '\\'), + new SingleLineRule("'", "'", character, '\\'), +// new UniqueWordRule(keyword, javaKeyword), + new KeyWordRule(), + // new MultiLineRule("/**", "*/", javadoc), +// new MultiLineRule("/*", "*/", comment), + + new IntRule(number), + new WhitespaceRule(new IWhitespaceDetector() { + public boolean isWhitespace(char c) { + return Character.isWhitespace(c); + } + }) + }; + setRules(rules); + } + + + + private static class KeyWordRule extends WordRule { + public KeyWordRule() { + super(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + return Character.isJavaIdentifierStart(c); + } + + @Override + public boolean isWordPart(char c) { + return Character.isJavaIdentifierPart(c); + }}, defaultToken); + + for(String word : javaKeyword) + addWord(word, keyword); + } + } + + + private static class UniqueWordRule extends WordRule { + public UniqueWordRule(final IToken token, final String ... words) { + super(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + for(String w : words) + if(w.charAt(0) == c) + return true; + return false; + } + + @Override + public boolean isWordPart(char c) { + return c >= 'a' && c <= 'w'; + }}, defaultToken); + + for(String w : words) + addWord(w, token); + } + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCommentsPartitionScanner.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCommentsPartitionScanner.java new file mode 100644 index 0000000..52b85cd --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaCommentsPartitionScanner.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.WordRule; + +public class JavaCommentsPartitionScanner extends RuleBasedPartitionScanner { + + /** + * Detector for empty comments. + */ + static class EmptyCommentDetector implements IWordDetector { + + /* + * @see IWordDetector#isWordStart + */ + public boolean isWordStart(char c) { + return (c == '/'); + } + + /* + * @see IWordDetector#isWordPart + */ + public boolean isWordPart(char c) { + return (c == '*' || c == '/'); + } + } + + + /** + * Word rule for empty comments. + */ + static class EmptyCommentRule extends WordRule implements IPredicateRule { + + private IToken fSuccessToken; + /** + * Constructor for EmptyCommentRule. + * @param successToken + */ + public EmptyCommentRule(IToken successToken) { + super(new EmptyCommentDetector()); + fSuccessToken= successToken; + addWord("/**/", fSuccessToken); //$NON-NLS-1$ + } + + /* + * @see IPredicateRule#evaluate(ICharacterScanner, boolean) + */ + public IToken evaluate(ICharacterScanner scanner, boolean resume) { + return evaluate(scanner); + } + + /* + * @see IPredicateRule#getSuccessToken() + */ + public IToken getSuccessToken() { + return fSuccessToken; + } + } + + + + /** + * Creates the partitioner and sets up the appropriate rules. + */ + public JavaCommentsPartitionScanner() { + super(); + +// IToken string= Common.createToken(TokenColor.STRING, false); +// IToken character= Common.createToken(TokenColor.CHAR, false); + IToken javaDoc= Common.createToken(TokenColor.COMMENT, true); + IToken multiLineComment= Common.createToken(TokenColor.COMMENT, false); + IToken singleLineComment= Common.createToken(TokenColor.COMMENT, false); + + List rules= new ArrayList(); + + // Add rule for single line comments. + rules.add(new EndOfLineRule("//", singleLineComment)); //$NON-NLS-1$ + + // Add rule for strings. +// rules.add(new SingleLineRule("\"", "\"", string, '\\')); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add rule for character constants. +// rules.add(new SingleLineRule("'", "'", character, '\\')); //$NON-NLS-2$ //$NON-NLS-1$ + + // Add special case word rule. + EmptyCommentRule wordRule= new EmptyCommentRule(multiLineComment); + rules.add(wordRule); + + // Add rules for multi-line comments and javadoc. + rules.add(new MultiLineRule("/**", "*/", javaDoc)); //$NON-NLS-1$ //$NON-NLS-2$ + rules.add(new MultiLineRule("/*", "*/", multiLineComment)); //$NON-NLS-1$ //$NON-NLS-2$ + + IPredicateRule[] result= new IPredicateRule[rules.size()]; + rules.toArray(result); + setPredicateRules(result); + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaEditorActivator.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaEditorActivator.java new file mode 100644 index 0000000..bcaff05 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaEditorActivator.java @@ -0,0 +1,182 @@ +package pt.iscte.pidesco.javaeditor.internal; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IPartListener2; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartReference; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.FileStoreEditorInput; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.BundleListener; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; + +import pt.iscte.pidesco.javaeditor.service.JavaEditorListener; +import pt.iscte.pidesco.javaeditor.service.JavaEditorServices; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserListener; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserServices; + +public class JavaEditorActivator implements BundleActivator, IPartListener2 { + + private static JavaEditorActivator instance; + + private BundleContext context; + + private ProjectBrowserListener listener; + + private Set listeners; + + private ProjectBrowserServices browser; + + private JavaEditorServices services; + + + private ISelectionListener selectionListener; + + + public static JavaEditorActivator getInstance() { + return instance; + } + + public JavaEditorServices getServices() { + return services; + } + + public JavaEditorActivator() { + listeners = new HashSet(); + } + + public void addListener(JavaEditorListener l) { + listeners.add(l); + } + + public void removeListener(JavaEditorListener l) { + listeners.remove(l); + } + + public void notityOpenFile(File file) { + for(JavaEditorListener l : listeners) + l.fileOpened(file); + } + + public void notityClosedFile(File file) { + for(JavaEditorListener l : listeners) + l.fileClosed(file); + } + + public void notitySavedFile(File file) { + for(JavaEditorListener l : listeners) + l.fileSaved(file); + } + + public void notifySelectionChanged(File file, String text, int offset, int length) { + for(JavaEditorListener l : listeners) + l.selectionChanged(file, text, offset, length); + } + + @Override + public void start(final BundleContext context) throws Exception { + instance = this; + this.context = context; + final ServiceReference ref = context.getServiceReference(ProjectBrowserServices.class); + browser = context.getService(ref); + services = new JavaEditorServicesImpl(); + listener = new OpenEditorListener(services); + browser.addListener(listener); + context.registerService(JavaEditorServices.class, services, null); + } + + @Override + public void stop(BundleContext context) throws Exception { + instance = null; + this.context = null; + } + + public BundleContext getContext() { + return context; + } + + private File getFile(IWorkbenchPartReference partRef) { + IEditorPart part = (IEditorPart) partRef.getPart(true); + IEditorInput input = part.getEditorInput(); + String path = ((FileStoreEditorInput) input).getURI().getPath(); + File f = new File(path); + return f; + } + + @Override + public void partActivated(IWorkbenchPartReference partRef) { + if(selectionListener == null) { + selectionListener = new ISelectionListener() { + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if(part instanceof IEditorPart && ((IEditorPart) part).getEditorSite().getId().equals(SimpleJavaEditor.EDITOR_ID)) { + IEditorPart editor = (IEditorPart) part; + IEditorInput input = editor.getEditorInput(); + String path = ((FileStoreEditorInput) input).getURI().getPath(); + File f = new File(path); + TextSelection s = (TextSelection) selection; + notifySelectionChanged(f, s.getText(), s.getOffset(), s.getLength()); + } + } + }; + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addSelectionListener(selectionListener); + } + } + + @Override + public void partBroughtToTop(IWorkbenchPartReference partRef) { + if(partRef.getId().equals(SimpleJavaEditor.EDITOR_ID)) + notityOpenFile(getFile(partRef)); + } + + @Override + public void partClosed(IWorkbenchPartReference partRef) { + if(partRef.getId().equals(SimpleJavaEditor.EDITOR_ID)) + notityClosedFile(getFile(partRef)); + } + + @Override + public void partDeactivated(IWorkbenchPartReference partRef) { + // TODO Auto-generated method stub + + } + + @Override + public void partOpened(IWorkbenchPartReference partRef) { + // TODO Auto-generated method stub + + } + + @Override + public void partHidden(IWorkbenchPartReference partRef) { + // TODO Auto-generated method stub + + } + + @Override + public void partVisible(IWorkbenchPartReference partRef) { + // TODO Auto-generated method stub + + } + + @Override + public void partInputChanged(IWorkbenchPartReference partRef) { + // TODO Auto-generated method stub + + } + + +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaEditorServicesImpl.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaEditorServicesImpl.java new file mode 100644 index 0000000..5e2c1d9 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/JavaEditorServicesImpl.java @@ -0,0 +1,271 @@ +package pt.iscte.pidesco.javaeditor.internal; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Map; +import java.util.Scanner; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTParser; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.FileStoreEditorInput; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +import pt.iscte.pidesco.javaeditor.service.AnnotationType; +import pt.iscte.pidesco.javaeditor.service.JavaEditorListener; +import pt.iscte.pidesco.javaeditor.service.JavaEditorServices; + +public class JavaEditorServicesImpl implements JavaEditorServices { + + @Override + public File getOpenedFile() { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IEditorPart part = page.getActiveEditor(); + if(part != null) { + IEditorInput input = part.getEditorInput(); + if(input instanceof FileStoreEditorInput) { + String path = ((FileStoreEditorInput) input).getURI().getPath(); + return new File(path); + } + } + return null; + } + + + @Override + public void openFile(File file) { + Assert.isNotNull(file, "file cannot be null"); + Assert.isTrue(file.exists(), "file does not exist"); + Assert.isTrue(!file.isDirectory(), "file is a directory"); + + if(file.exists() && file.isFile()) { + IFileStore fileStore = EFS.getLocalFileSystem().getStore(file.toURI()); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + IDE.openEditorOnFileStore(page, fileStore); + JavaEditorActivator.getInstance().notityOpenFile(file); + } catch (PartInitException e) { + } + } + else { + throw new RuntimeException("File not found"); + } + } + + @Override + public void selectText(File file, int offset, int length) { + Assert.isNotNull(file, "file cannot be null"); + + ITextEditor editor = openEditor(file); + editor.selectAndReveal(offset, length); + } + + + private ITextEditor openEditor(File file) { + Assert.isNotNull(file, "file cannot be null"); + + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IFileStore fileStore = EFS.getLocalFileSystem().getStore(file.toURI()); + ITextEditor editor = null; + try { + editor = (ITextEditor) IDE.openEditorOnFileStore(page, fileStore); + } catch (PartInitException e) { + e.printStackTrace(); + } + return editor; + } + + @Override + public void insertLine(File file, String text, int line) { + Assert.isNotNull(file, "file cannot be null"); + Assert.isNotNull(text, "text cannot be null"); + + ITextEditor editor = openEditor(file); + IDocumentProvider dp = editor.getDocumentProvider(); + IDocument doc = dp.getDocument(editor.getEditorInput()); + ISelectionProvider selProvider = editor.getSite().getSelectionProvider(); + try { + int offset = doc.getLineInformation(line).getOffset(); + doc.replace(offset, 0, text + "\n"); + selProvider.setSelection(new TextSelection(offset + text.length(), 0)); + } + catch (BadLocationException e) { + throw new RuntimeException("invalid line: " + line); + } + } + + @Override + public void insertText(File file, String text, int offset, int length) { + Assert.isNotNull(file, "file cannot be null"); + Assert.isNotNull(text, "text cannot be null"); + + ITextEditor editor = openEditor(file); + IDocumentProvider dp = editor.getDocumentProvider(); + IDocument doc = dp.getDocument(editor.getEditorInput()); + + try { + doc.replace(offset, length, text); + } catch (BadLocationException e) { + throw new RuntimeException("invalid offset/length: " + offset + "/" + length + " (max offset = " + doc.getLength() + ")"); + } + } + + @Override + public void setText(File file, String text) { + Assert.isNotNull(file, "file cannot be null"); + Assert.isNotNull(text, "text cannot be null"); + + ITextEditor editor = openEditor(file); + IDocumentProvider dp = editor.getDocumentProvider(); + IDocument doc = dp.getDocument(editor.getEditorInput()); + + doc.set(text); + } + + + @Override + public ITextSelection getTextSelected(File file){ + Assert.isNotNull(file, "file cannot be null"); + + ITextEditor editor = openEditor(file); + IDocumentProvider dp = editor.getDocumentProvider(); + IDocument doc = dp.getDocument(editor.getEditorInput()); + + return ((ITextSelection) editor.getSelectionProvider().getSelection()); + } + + + @Override + public void saveFile(File file){ + Assert.isNotNull(file, "file cannot be null"); + + ITextEditor editor = openEditor(file); + editor.doSave(new NullProgressMonitor()); + } + + + @Override + public void insertTextAtCursor(String text) { + Assert.isNotNull(text, "text cannot be null"); + + File file = getOpenedFile(); + if(file == null) + throw new RuntimeException("no file is opened"); + + ITextEditor editor = openEditor(file); + IDocumentProvider dp = editor.getDocumentProvider(); + IDocument doc = dp.getDocument(editor.getEditorInput()); + ISelectionProvider selProvider = editor.getSite().getSelectionProvider(); + ITextSelection textSelection = (ITextSelection) selProvider.getSelection(); + final int offset = textSelection.getOffset(); + try { + doc.replace(offset, 0, text); + selProvider.setSelection(new TextSelection(offset + text.length(), 0)); + + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + @Override + public int getCursorPosition() { + File file = getOpenedFile(); + if(file == null) + throw new RuntimeException("no file is opened"); + + ITextEditor editor = openEditor(file); + ISelectionProvider selProvider = editor.getSite().getSelectionProvider(); + ITextSelection textSelection = (ITextSelection) selProvider.getSelection(); + return textSelection.getOffset(); + } + + + + @Override + public IProblem[] parseFile(File file, ASTVisitor visitor) { + Assert.isNotNull(file, "file cannot be null"); + ASTParser parser = ASTParser.newParser(AST.JLS8); + Map options = JavaCore.getOptions(); + JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options); + parser.setCompilerOptions(options); + String src = readSource(file); + parser.setSource(src.toCharArray()); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + CompilationUnit cu = (CompilationUnit) parser.createAST(null); + cu.accept(visitor); + return cu.getProblems(); + } + + + private String readSource(File file) { + StringBuilder src = new StringBuilder(); + try { + Scanner scanner = new Scanner(file); + while(scanner.hasNextLine()) + src.append(scanner.nextLine()).append('\n'); + scanner.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return src.toString(); + } + + + + @Override + public void addAnnotation(File file, AnnotationType type, String text, int offset, int length) { + Assert.isNotNull(file, "file cannot be null"); + + openFile(file); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IEditorPart part = page.getActiveEditor(); + IEditorInput input = part.getEditorInput(); + IAnnotationModel amodel = ((ITextEditor) part).getDocumentProvider().getAnnotationModel(input); + Annotation ann = new Annotation(false); + ann.setText(text); + ann.setType(type.ID); + amodel.addAnnotation(ann, new Position(offset, length)); + } + + + @Override + public void addListener(JavaEditorListener listener) { + Assert.isNotNull(listener, "argument cannot be null"); + JavaEditorActivator.getInstance().addListener(listener); + } + + + @Override + public void removeListener(JavaEditorListener listener) { + Assert.isNotNull(listener, "argument cannot be null"); + JavaEditorActivator.getInstance().removeListener(listener); + } + + + + + +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/NonRuleBasedDamagerRepairer.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/NonRuleBasedDamagerRepairer.java new file mode 100644 index 0000000..d323205 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/NonRuleBasedDamagerRepairer.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.presentation.IPresentationDamager; +import org.eclipse.jface.text.presentation.IPresentationRepairer; +import org.eclipse.swt.custom.StyleRange; + +public class NonRuleBasedDamagerRepairer + implements IPresentationDamager, IPresentationRepairer { + + /** The document this object works on */ + protected IDocument fDocument; + /** The default text attribute if non is returned as data by the current token */ + protected TextAttribute fDefaultTextAttribute; + + /** + * Constructor for NonRuleBasedDamagerRepairer. + */ + public NonRuleBasedDamagerRepairer(TextAttribute defaultTextAttribute) { + Assert.isNotNull(defaultTextAttribute); + + fDefaultTextAttribute = defaultTextAttribute; + } + + /** + * @see IPresentationRepairer#setDocument(IDocument) + */ + public void setDocument(IDocument document) { + fDocument = document; + } + + /** + * Returns the end offset of the line that contains the specified offset or + * if the offset is inside a line delimiter, the end offset of the next line. + * + * @param offset the offset whose line end offset must be computed + * @return the line end offset for the given offset + * @exception BadLocationException if offset is invalid in the current document + */ + protected int endOfLineOf(int offset) throws BadLocationException { + + IRegion info = fDocument.getLineInformationOfOffset(offset); + if (offset <= info.getOffset() + info.getLength()) + return info.getOffset() + info.getLength(); + + int line = fDocument.getLineOfOffset(offset); + try { + info = fDocument.getLineInformation(line + 1); + return info.getOffset() + info.getLength(); + } catch (BadLocationException x) { + return fDocument.getLength(); + } + } + + /** + * @see IPresentationDamager#getDamageRegion(ITypedRegion, DocumentEvent, boolean) + */ + public IRegion getDamageRegion( + ITypedRegion partition, + DocumentEvent event, + boolean documentPartitioningChanged) { + if (!documentPartitioningChanged) { + try { + + IRegion info = + fDocument.getLineInformationOfOffset(event.getOffset()); + int start = Math.max(partition.getOffset(), info.getOffset()); + + int end = + event.getOffset() + + (event.getText() == null + ? event.getLength() + : event.getText().length()); + + if (info.getOffset() <= end + && end <= info.getOffset() + info.getLength()) { + // optimize the case of the same line + end = info.getOffset() + info.getLength(); + } else + end = endOfLineOf(end); + + end = + Math.min( + partition.getOffset() + partition.getLength(), + end); + return new Region(start, end - start); + + } catch (BadLocationException x) { + } + } + + return partition; + } + + /** + * @see IPresentationRepairer#createPresentation(TextPresentation, ITypedRegion) + */ + public void createPresentation( + TextPresentation presentation, + ITypedRegion region) { + addRange( + presentation, + region.getOffset(), + region.getLength(), + fDefaultTextAttribute); + } + + /** + * Adds style information to the given text presentation. + * + * @param presentation the text presentation to be extended + * @param offset the offset of the range to be styled + * @param length the length of the range to be styled + * @param attr the attribute describing the style of the range to be styled + */ + protected void addRange( + TextPresentation presentation, + int offset, + int length, + TextAttribute attr) { + if (attr != null) + presentation.addStyleRange( + new StyleRange( + offset, + length, + attr.getForeground(), + attr.getBackground(), + attr.getStyle())); + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/OpenEditorListener.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/OpenEditorListener.java new file mode 100644 index 0000000..f1d8685 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/OpenEditorListener.java @@ -0,0 +1,26 @@ +package pt.iscte.pidesco.javaeditor.internal; + +import java.io.File; + +import pt.iscte.pidesco.javaeditor.service.JavaEditorServices; +import pt.iscte.pidesco.projectbrowser.model.ClassElement; +import pt.iscte.pidesco.projectbrowser.model.SourceElement; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserListener; + +public class OpenEditorListener extends ProjectBrowserListener.Adapter { + + private JavaEditorServices services; + + public OpenEditorListener(JavaEditorServices services) { + this.services = services; + } + + @Override + public void doubleClick(SourceElement element) { + if(element instanceof ClassElement) { + File f = ((ClassElement) element).getFile(); + services.openFile(f); + } + } + +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/SimpleJavaEditor.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/SimpleJavaEditor.java new file mode 100644 index 0000000..a00ac24 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/SimpleJavaEditor.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + + +//import static org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.PRINT_MARGIN; +//import static org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.PRINT_MARGIN_COLOR; +//import static org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.PRINT_MARGIN_COLUMN; + +import java.io.File; +import java.util.Iterator; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.IRegion; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPropertyListener; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.ide.FileStoreEditorInput; +import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; + +import pt.iscte.pidesco.javaeditor.service.AnnotationType; +import pt.iscte.pidesco.javaeditor.service.JavaEditorServices; + + +public class SimpleJavaEditor extends TextEditor { + + public static final String EDITOR_ID = "pt.iscte.pidesco.javaeditor"; + + private JavaEditorServices services; + + public SimpleJavaEditor() { + setSourceViewerConfiguration(new Configuration()); + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + window.getActivePage().addPartListener(JavaEditorActivator.getInstance()); + showOverviewRuler(); + services = JavaEditorActivator.getInstance().getServices(); + } + + @Override + protected ISourceViewer createSourceViewer(Composite parent, + IVerticalRuler ruler, int styles) { + ISourceViewer sourceViewer= super.createSourceViewer(parent, ruler, styles); + + fSourceViewerDecorationSupport= new SourceViewerDecorationSupport(sourceViewer, fOverviewRuler, fAnnotationAccess, getSharedColors()); + super.configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport); + return sourceViewer; + } + + @Override + protected void doSetInput(IEditorInput input) throws CoreException { + super.doSetInput(input); + compile(); + } + + @Override + public void doSave(IProgressMonitor progressMonitor) { + super.doSave(progressMonitor); + compile(); + } + + @Override + protected void editorSaved() { + super.editorSaved(); + JavaEditorActivator.getInstance().notitySavedFile(getFile()); + } + + private void compile() { + clearAnnotations(); + File f = getFile(); + for(IProblem p : services.parseFile(f, new ASTVisitor(){})) { + int offset = p.getSourceStart(); + int length = p.getSourceEnd() - p.getSourceStart() + 1; + services.addAnnotation(f, AnnotationType.ERROR, p.getMessage(), offset, length); + } + } + + private File getFile() { + FileStoreEditorInput fs = (FileStoreEditorInput) getEditorInput(); + File f = new File(fs.getURI().getPath()); + return f; + } + + private void clearAnnotations() { + IAnnotationModel amodel = getDocumentProvider().getAnnotationModel(getEditorInput()); + Iterator it = amodel.getAnnotationIterator(); + while(it.hasNext()) { + Annotation a = (Annotation) it.next(); + amodel.removeAnnotation(a); + } + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Startup.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Startup.java new file mode 100644 index 0000000..e95c0e9 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/Startup.java @@ -0,0 +1,20 @@ +package pt.iscte.pidesco.javaeditor.internal; +import org.eclipse.ui.IStartup; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleException; +import org.osgi.framework.FrameworkUtil; + + +public class Startup implements IStartup { + + @Override + public void earlyStartup() { + Bundle b = FrameworkUtil.getBundle(Startup.class); + try { + b.start(); + } catch (BundleException e) { + e.printStackTrace(); + } + } + +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/TokenColor.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/TokenColor.java new file mode 100644 index 0000000..bb04c66 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/TokenColor.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +public enum TokenColor { + BLACK(0, 0, 0), + STRING(0, 0, 255), + CHAR(0, 128, 128), + KEYWORD(128, 0, 128), + NUMBER(0, 0, 255), + COMMENT(128, 128, 128), + ID(255, 0, 0), + TRUE(0, 128, 0), + FALSE(255, 0, 0), + NULL(255, 0, 239); + + public final Color color; + + private TokenColor(int r, int g, int b) { + color = new Color(Display.getDefault(), new RGB(r, g, b)); + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/WhitespaceDetector.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/WhitespaceDetector.java new file mode 100644 index 0000000..c0d3ecc --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/internal/WhitespaceDetector.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2014 Andre L. Santos. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre L Santos - developer + ******************************************************************************/ +package pt.iscte.pidesco.javaeditor.internal; + +import org.eclipse.jface.text.rules.IWhitespaceDetector; + +public class WhitespaceDetector implements IWhitespaceDetector { + + public boolean isWhitespace(char c) { + return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/AnnotationType.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/AnnotationType.java new file mode 100644 index 0000000..ad04649 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/AnnotationType.java @@ -0,0 +1,19 @@ +package pt.iscte.pidesco.javaeditor.service; + +/** + * Set of annotation types that can be used to annotate the java editor code. + */ +public enum AnnotationType { + ERROR("org.eclipse.ui.workbench.texteditor.error"), + WARNING("org.eclipse.ui.workbench.texteditor.warning"), + INFO("org.eclipse.ui.workbench.texteditor.info"); + + /** + * Id of the annotation (Eclipse-specific) + */ + public final String ID; + + private AnnotationType(String id) { + this.ID = id; + } + } \ No newline at end of file diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/JavaEditorListener.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/JavaEditorListener.java new file mode 100644 index 0000000..dec4a12 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/JavaEditorListener.java @@ -0,0 +1,62 @@ +package pt.iscte.pidesco.javaeditor.service; + +import java.io.File; + +/** + * Represents a listener for events in the Java Editor + */ +public interface JavaEditorListener { + + /** + * File open event. + * @param file (non-null) reference to the opened file + */ + void fileOpened(File file); + + /** + * File save event. + * @param file (non-null) reference to the saved file + */ + void fileSaved(File file); + + /** + * File close event. + * @param file (non-null) reference to the closed file + */ + void fileClosed(File file); + + /** + * File selection changed event. + * @param file (non-null) reference to the file + * @param text selected text + * @param offset offset of the selection (index of the first selected character) + * @param length length of the selection + */ + void selectionChanged(File file, String text, int offset, int length); + + /** + * Listener adapter that for each event does nothing. + */ + public class Adapter implements JavaEditorListener { + + @Override + public void fileOpened(File file) { + + } + + @Override + public void fileSaved(File file) { + + } + + @Override + public void fileClosed(File file) { + + } + + @Override + public void selectionChanged(File file, String text, int offset, int length) { + + } + } +} diff --git a/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/JavaEditorServices.java b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/JavaEditorServices.java new file mode 100644 index 0000000..fd69ec5 --- /dev/null +++ b/pt.iscte.pidesco.javaeditor/src/pt/iscte/pidesco/javaeditor/service/JavaEditorServices.java @@ -0,0 +1,122 @@ +package pt.iscte.pidesco.javaeditor.service; + +import java.io.File; + +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jface.text.ITextSelection; + +/** + * Services offered by the Java Editor component. + */ +public interface JavaEditorServices { + + /** + * Get the file that is opened (on top) in the editor. + * @return a reference to the opened file, or null if no file is opened + */ + File getOpenedFile(); + + /** + * Opens a file in the editor. + * @param file (non-null) file to open + * @return + */ + void openFile(File file); + + + /** + * Saves the state of the current file + * @param file (non-null) file to open + * @return + */ + + void saveFile(File file); + + + /** + * Sets the text of a file in the editor. + * @param file (non-null) file to open + * @param text to insert on file + * @return + */ + + void setText(File file, String text); + + /** + * Get the selected text of a file in the editor. + * @param file (non-null) file to open + * @return an instance of ITextSelection + */ + + ITextSelection getTextSelected(File file); + + + /** + * Selects text in the editor. + * @param file (non-null) file where to select text + * @param offset offset of the selection (index of the first character) + * @param length length of the selection + */ + void selectText(File file, int offset, int length); + + /** + * Inserts a line in the editor. + * @param file (non-null) file where to insert the line + * @param text (non-null) line text + * @param line index of the line where to insert the new line + */ + void insertLine(File file, String text, int line); + + /** + * Inserts text in the editor at a certain location. + * @param file (non-null) file where to insert the text + * @param text (non-null) text to insert + * @param offset offset of the insertion (index of the first character) + * @param length length of the selection (zero if no text is to be replaced) + */ + void insertText(File file, String text, int offset, int length); + + /** + * Inserts text in the cursor location of the opened editor. + * @param text text to insert + */ + void insertTextAtCursor(String text); + + /** + * Returns the cursor position in editor (offset) + * Requires having an open editor. + * @return an integer equal or greater than zero + */ + int getCursorPosition(); + + /** + * Parses a Java file using a AST visitor. + * @param file (non-null) file to parse + * @param visitor (non-null) visitor + * @return (non-null) an array of problems with the parsing (zero-length if none) + */ + IProblem[] parseFile(File file, ASTVisitor visitor); + + /** + * Adds an annotation to a file. + * @param file (non-null) file where to add the annotation + * @param type (non-null) annotation type (error, warning, or information) + * @param text (non-null) annotation text + * @param offset offset of the text related to the annotation + * @param length selection of the text related to the annotation + */ + void addAnnotation(File file, AnnotationType type, String text, int offset, int length); + + /** + * Adds a Java Editor listener. If the listener already exists, does nothing. + * @param listener (non-null) reference to a listener. + */ + void addListener(JavaEditorListener listener); + + /** + * Removes a Java Editor listener. If the listener is not registered, does nothing. + * @param listener (non-null) reference to a listener. + */ + void removeListener(JavaEditorListener listener); +} \ No newline at end of file diff --git a/pt.iscte.pidesco.projectbrowser/.classpath b/pt.iscte.pidesco.projectbrowser/.classpath new file mode 100644 index 0000000..e8ea977 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/pt.iscte.pidesco.projectbrowser/.project b/pt.iscte.pidesco.projectbrowser/.project new file mode 100644 index 0000000..2c66278 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/.project @@ -0,0 +1,28 @@ + + + pt.iscte.pidesco.projectbrowser + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/pt.iscte.pidesco.projectbrowser/.settings/org.eclipse.jdt.core.prefs b/pt.iscte.pidesco.projectbrowser/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..f42de36 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/pt.iscte.pidesco.projectbrowser/META-INF/MANIFEST.MF b/pt.iscte.pidesco.projectbrowser/META-INF/MANIFEST.MF new file mode 100644 index 0000000..2bd349a --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Project Browser +Bundle-SymbolicName: pt.iscte.pidesco.projectbrowser;singleton:=true +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Require-Bundle: org.eclipse.ui;bundle-version="3.106.0", + org.eclipse.core.runtime;bundle-version="3.10.0", + org.eclipse.core.filesystem;bundle-version="1.4.100", + org.eclipse.ui.ide;bundle-version="3.10.1", + org.eclipse.core.resources, + pt.iscte.pidesco;bundle-version="0.1.0" +Export-Package: pt.iscte.pidesco.projectbrowser.extensibility, + pt.iscte.pidesco.projectbrowser.model, + pt.iscte.pidesco.projectbrowser.service +Bundle-Activator: pt.iscte.pidesco.projectbrowser.internal.ProjectBrowserActivator +Bundle-ActivationPolicy: lazy +Bundle-Version: 0.1 diff --git a/pt.iscte.pidesco.projectbrowser/build.properties b/pt.iscte.pidesco.projectbrowser/build.properties new file mode 100644 index 0000000..9cc7b38 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + images/ diff --git a/pt.iscte.pidesco.projectbrowser/images/class.gif b/pt.iscte.pidesco.projectbrowser/images/class.gif new file mode 100644 index 0000000..e191e1d Binary files /dev/null and b/pt.iscte.pidesco.projectbrowser/images/class.gif differ diff --git a/pt.iscte.pidesco.projectbrowser/images/package.gif b/pt.iscte.pidesco.projectbrowser/images/package.gif new file mode 100644 index 0000000..131c28d Binary files /dev/null and b/pt.iscte.pidesco.projectbrowser/images/package.gif differ diff --git a/pt.iscte.pidesco.projectbrowser/images/proj.gif b/pt.iscte.pidesco.projectbrowser/images/proj.gif new file mode 100644 index 0000000..0b27698 Binary files /dev/null and b/pt.iscte.pidesco.projectbrowser/images/proj.gif differ diff --git a/pt.iscte.pidesco.projectbrowser/images/refresh.gif b/pt.iscte.pidesco.projectbrowser/images/refresh.gif new file mode 100644 index 0000000..32b655e Binary files /dev/null and b/pt.iscte.pidesco.projectbrowser/images/refresh.gif differ diff --git a/pt.iscte.pidesco.projectbrowser/plugin.xml b/pt.iscte.pidesco.projectbrowser/plugin.xml new file mode 100644 index 0000000..9007a05 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/plugin.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + diff --git a/pt.iscte.pidesco.projectbrowser/schema/pt.iscte.pidesco.filter.exsd b/pt.iscte.pidesco.projectbrowser/schema/pt.iscte.pidesco.filter.exsd new file mode 100644 index 0000000..2d1775d --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/schema/pt.iscte.pidesco.filter.exsd @@ -0,0 +1,106 @@ + + + + + + + + + This extension point is to define filters that can be activated/deactivated in the Project Browser view. + + + + + + + + + + + + + + + + + + + + + + + + Filter id, which is used to activation/deactivation. + + + + + + + + + + Human-readable name for the filter. + + + + + + + + + + + + + + + Filter class for deciding which elements of the source tree to include or not. + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + Filters are activated/deactivated using the operation: +ProjectBrowserServices.activateFilter(filterId) + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/extensibility/ProjectBrowserFilter.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/extensibility/ProjectBrowserFilter.java new file mode 100644 index 0000000..f2c1409 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/extensibility/ProjectBrowserFilter.java @@ -0,0 +1,19 @@ +package pt.iscte.pidesco.projectbrowser.extensibility; + + +import pt.iscte.pidesco.projectbrowser.model.PackageElement; +import pt.iscte.pidesco.projectbrowser.model.SourceElement; + +/** + * Represents a filter that can be activated/deactivated in the Project Browser. + */ +public interface ProjectBrowserFilter { + + /** + * Include the element? + * @param element Element to include or not + * @param parent Parent package of the element + * @return true if the element should be included, false otherwise + */ + boolean include(SourceElement element, PackageElement parent); +} diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/Filter.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/Filter.java new file mode 100644 index 0000000..6742d42 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/Filter.java @@ -0,0 +1,13 @@ +package pt.iscte.pidesco.projectbrowser.internal; + +import java.io.File; + +public interface Filter { + + /** + * Filter to determine if a file should be included in the scan + * @param fileName non-null reference to the file + * @return true if the file is to be included in the scan, false otherwise + */ + boolean accept(File file); +} diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserActivator.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserActivator.java new file mode 100644 index 0000000..8e8cb21 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserActivator.java @@ -0,0 +1,49 @@ +package pt.iscte.pidesco.projectbrowser.internal; + +import java.util.HashSet; +import java.util.Set; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserListener; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserServices; + +public class ProjectBrowserActivator implements BundleActivator { + + private static ProjectBrowserActivator instance; + private Set listeners; + private ServiceRegistration service; + + @Override + public void start(BundleContext context) throws Exception { + instance = this; + listeners = new HashSet(); + service = context.registerService(ProjectBrowserServices.class, new ProjectBrowserServicesImpl(), null); + } + + public void stop(BundleContext context) throws Exception { + instance = null; + service.unregister(); + listeners.clear(); + } + + public static ProjectBrowserActivator getInstance() { + return instance; + } + + public Set getListeners() { + return listeners; + } + + public void addListener(ProjectBrowserListener l) { + listeners.add(l); + } + + public void removeListener(ProjectBrowserListener l) { + listeners.remove(l); + } + + +} diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserServicesImpl.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserServicesImpl.java new file mode 100644 index 0000000..d614142 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserServicesImpl.java @@ -0,0 +1,33 @@ +package pt.iscte.pidesco.projectbrowser.internal; + +import pt.iscte.pidesco.projectbrowser.model.PackageElement; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserListener; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserServices; + +public class ProjectBrowserServicesImpl implements ProjectBrowserServices { + + public PackageElement getRootPackage() { + return ProjectBrowserView.getInstance().getRootPackage(); + } + + public void refreshTree() { + ProjectBrowserView.getInstance().refresh(); + } + + public void activateFilter(String id) { + ProjectBrowserView.getInstance().activateFilter(id); + } + + public void deactivateFilter(String id) { + ProjectBrowserView.getInstance().deactivateFilter(id); + } + + public void addListener(ProjectBrowserListener listener) { + ProjectBrowserActivator.getInstance().addListener(listener); + } + + public void removeListener(ProjectBrowserListener listener) { + ProjectBrowserActivator.getInstance().removeListener(listener); + } + +} diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserView.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserView.java new file mode 100644 index 0000000..422c8f0 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/ProjectBrowserView.java @@ -0,0 +1,267 @@ +package pt.iscte.pidesco.projectbrowser.internal; + +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; + +import pt.iscte.pidesco.extensibility.PidescoServices; +import pt.iscte.pidesco.extensibility.PidescoView; +import pt.iscte.pidesco.projectbrowser.extensibility.ProjectBrowserFilter; +import pt.iscte.pidesco.projectbrowser.model.ClassElement; +import pt.iscte.pidesco.projectbrowser.model.PackageElement; +import pt.iscte.pidesco.projectbrowser.model.SourceElement; +import pt.iscte.pidesco.projectbrowser.service.ProjectBrowserListener; + +public class ProjectBrowserView implements PidescoView { + + private static final String VIEW_ID = "pt.iscte.pidesco.projectbrowser.tree"; + + private static final String EXT_POINT_FILTER = "pt.iscte.pidesco.projectbrowser.filter"; + + private static ProjectBrowserView instance; + + private TreeViewer tree; + private PackageElement invisibleRoot; + + private File rootPath; + + private Image packageIcon; + private Image classIcon; + + private Map filtersMap; + private Set activeFilters; + + private static PidescoServices services; + + public ProjectBrowserView() { + filtersMap = new HashMap(); + activeFilters = new HashSet(); + loadFilters(); + + BundleContext context = FrameworkUtil.getBundle(ProjectBrowserListener.class).getBundleContext(); + ServiceReference ref = context.getServiceReference(PidescoServices.class); + services = context.getService(ref); + } + + private void loadFilters() { + IExtensionRegistry reg = Platform.getExtensionRegistry(); + for(IExtension ext : reg.getExtensionPoint(EXT_POINT_FILTER).getExtensions()) { + + ProjectBrowserFilter f = null; + try { + f = (ProjectBrowserFilter) ext.getConfigurationElements()[0].createExecutableExtension("class"); + } catch (Exception e) { + e.printStackTrace(); + } + if(f != null) + filtersMap.put(ext.getUniqueIdentifier(), new Filter(f)); + } + } + + public PackageElement getRootPackage() { + return invisibleRoot; + } + + public void activateFilter(String id) { + if(filtersMap.containsKey(id)) { + activeFilters.add(id); + tree.addFilter(filtersMap.get(id)); + tree.expandAll(); + } + else { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Filter not found", "Filter with id=" + id + " not found"); + } + } + + public void deactivateFilter(String id) { + if(filtersMap.containsKey(id)) { + activeFilters.remove(id); + tree.removeFilter(filtersMap.get(id)); + tree.expandAll(); + } + else { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Filter not found", "Filter with id=" + id + " not found"); + } + } + + @Override + public void createContents(Composite viewArea, Map images) { + instance = this; + rootPath = new File(ResourcesPlugin.getWorkspace().getRoot().getLocation().toString()); + packageIcon = images.get("package.gif"); + classIcon = images.get("class.gif"); + tree = new TreeViewer(viewArea, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + tree.setContentProvider(new ViewContentProvider()); + tree.setLabelProvider(new ViewLabelProvider()); + + addDoubleClickListener(); + addSelectionListener(); + refresh(); + } + + public void refresh() { + Object[] expanded = tree.getExpandedElements(); + + invisibleRoot = scan(rootPath); + tree.setInput(invisibleRoot); + + if(!activeFilters.isEmpty()) + tree.expandAll(); + else + for(Object o : expanded) + tree.expandToLevel(o, TreeViewer.ALL_LEVELS); + } + + + public static ProjectBrowserView getInstance() { + if(instance == null) + services.openView(VIEW_ID); + + return instance; + } + + + + private static class Filter extends ViewerFilter { + private final ProjectBrowserFilter filter; + + public Filter(ProjectBrowserFilter filter) { + this.filter = filter; + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + PackageElement parent = parentElement == null ? null : (PackageElement) parentElement; + SourceElement child = (SourceElement) element; + return filter.include(child, parent); + } + } + + + + private static class ViewContentProvider implements IStructuredContentProvider, ITreeContentProvider { + + private static final Object[] EMPTY = new Object[0]; + + public void inputChanged(Viewer v, Object oldInput, Object newInput) { + + } + + public void dispose() { + + } + + public Object[] getElements(Object parent) { + return getChildren(parent); + + } + + public Object getParent(Object child) { + return ((SourceElement)child).getParent(); + } + + public Object[] getChildren(Object parent) { + if (parent instanceof PackageElement) + return ((PackageElement)parent).getChildren().toArray(); + else + return EMPTY; + } + + public boolean hasChildren(Object parent) { + return parent instanceof PackageElement && ((PackageElement)parent).hasChildren(); + } + + } + + + private static PackageElement scan(File root) { + PackageElement pack = new PackageElement(null, "", root); + for(File child : root.listFiles()) { + if(!child.getName().startsWith(".")) + scanRec(child, pack); + } + return pack; + } + + private static void scanRec(File f, PackageElement p) { + if(f.isFile() && f.getName().endsWith(".java")) { + new ClassElement(p, f); + } + else if(f.isDirectory()) { + PackageElement childPack = new PackageElement(p, f.getName(), f); + for(File child : f.listFiles()) { + scanRec(child, childPack); + } + } + } + + + class ViewLabelProvider extends LabelProvider { + + public String getText(Object obj) { + return obj.toString(); + } + public Image getImage(Object obj) { + return ((SourceElement) obj).isPackage() ? packageIcon : classIcon; + } + } + + + + private void addDoubleClickListener() { + tree.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + IStructuredSelection s = (IStructuredSelection) tree.getSelection(); + if(s.size() == 1) { + SourceElement e = (SourceElement) s.getFirstElement(); + for(ProjectBrowserListener l : ProjectBrowserActivator.getInstance().getListeners()) { + l.doubleClick(e); + } + } + } + }); + } + + private void addSelectionListener() { + tree.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + List list = Collections.unmodifiableList(selection.toList()); + for(ProjectBrowserListener l : ProjectBrowserActivator.getInstance().getListeners()) { + l.selectionChanged(list); + } + } + }); + } + + +} diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/RefreshTool.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/RefreshTool.java new file mode 100644 index 0000000..b049ded --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/internal/RefreshTool.java @@ -0,0 +1,13 @@ +package pt.iscte.pidesco.projectbrowser.internal; + + +import pt.iscte.pidesco.extensibility.PidescoTool; + +public class RefreshTool implements PidescoTool { + + @Override + public void run(boolean selected) { + ProjectBrowserView.getInstance().refresh(); + } + +} diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/ClassElement.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/ClassElement.java new file mode 100644 index 0000000..6be1107 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/ClassElement.java @@ -0,0 +1,16 @@ +package pt.iscte.pidesco.projectbrowser.model; + +import java.io.File; + +/** + * Represents a class as a source element. + */ +public final class ClassElement extends SourceElement { + + public ClassElement(PackageElement parent, File file) { + super(parent, file.getName(), file); + if(parent == null) + throw new NullPointerException("A class source element must have a parent (package)"); + } + +} \ No newline at end of file diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/PackageElement.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/PackageElement.java new file mode 100644 index 0000000..b820b14 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/PackageElement.java @@ -0,0 +1,165 @@ +package pt.iscte.pidesco.projectbrowser.model; + +import java.io.File; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.eclipse.core.runtime.Assert; + +/** + * Represents a package as a source element. + * A package can be iterated as a collection of SourceElement (its children). + */ +public final class PackageElement extends SourceElement implements Iterable { + private final SortedSet children; + + private static class PackageFirstSorter implements Comparator { + @Override + public int compare(SourceElement a, SourceElement b) { + if(a.isPackage() && b.isClass()) + return -1; + else if(a.isClass() && b.isPackage()) + return 1; + else + return a.getName().compareTo(b.getName()); + } + } + + /** + * Creates a pacakge element, given an optional parent, a name, and a file. + * @param parent parent package (if null, this is a root package) + * @param name (non-null) string representing the element name + * @param file (non-null) file that the element represents + */ + public PackageElement(PackageElement parent, String name, File file) { + super(parent, name, file); + children = new TreeSet(new PackageFirstSorter()); + } + + void addChild(SourceElement child) { + children.add(child); + } + + /** + * Returns the package children (classes and other packages). + * The children are sorted according to the following: + * - packages appear first as the primary sorting criterion + * - the second sorting criterion is the alphabetical order of the chilren names + * @return (non-null) sorted set of child elements + */ + public SortedSet getChildren() { + return Collections.unmodifiableSortedSet(children); + } + + /** + * Does the package has children? + * @return true if yes, false otherwise + */ + public boolean hasChildren() { + return children.size() > 0; + } + + /** + * Is this package a child (possibly indirect) of a given package? + * @param parent package to check if it is a parent + * @return true if yes, false otherwise + */ + public boolean isChildOf(PackageElement parent) { + Assert.isNotNull(parent, "argument cannot be null"); + + if(getParent() == null) + return false; + else if(getParent().equals(parent)) + return true; + else + return getParent().isChildOf(parent); + } + + /** + * Does this package contains a child associated with a given file? + * The search iterates over the children, optionally performing a deep search recursively. + * @param file file to search for + * @param deepSearch if true a deep search is performed, if false a shallow search is performed instead (only direct children are checked) + * @return true if yes, false otherwise + */ + public boolean hasChild(File file, boolean deepSearch) { + Assert.isNotNull(file, "file cannot be null"); + + for(SourceElement s : children) { + if(s.getFile().equals(file)) + return true; + else if(deepSearch && s.isPackage() && ((PackageElement) s).hasChild(file, deepSearch)) + return true; + } + return false; + } + + @Override + public Iterator iterator() { + return getChildren().iterator(); + } + + + /** + * Traverses this package and its children using a + * @param visitor + */ + public void traverse(Visitor visitor) { + Assert.isNotNull(visitor, "argument cannot be null"); + + for(SourceElement e : this) + traverse(e, visitor); + } + + private static void traverse(SourceElement e, Visitor visitor) { + if(e.isClass()) { + visitor.visitClass((ClassElement) e); + } + else { + if(visitor.visitPackage((PackageElement) e)) { + for(SourceElement c : ((PackageElement) e).getChildren()) + traverse(c, visitor); + } + } + } + + + /** + * Visitor for traversing package hierarchies. + */ + public interface Visitor { + + /** + * Invoked whenever a package is visited + * @param packageElement visited package + * @return true if the traversal should proceed to the children of the package, false otherwise + */ + boolean visitPackage(PackageElement packageElement); + + /** + * Invoked whenever a class is visited + * @param classElement visited class + */ + void visitClass(ClassElement classElement); + + /** + * Visitor adapter that does nothing, and always proceeds to the package children. + */ + public class Adapter implements Visitor { + + @Override + public boolean visitPackage(PackageElement p) { + return true; + } + + @Override + public void visitClass(ClassElement c) { + + } + } + } + +} \ No newline at end of file diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/SourceElement.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/SourceElement.java new file mode 100644 index 0000000..c6db74e --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/model/SourceElement.java @@ -0,0 +1,97 @@ +package pt.iscte.pidesco.projectbrowser.model; + +import java.io.File; + +import org.eclipse.core.runtime.Assert; + +/** + * Represents a source element that is associated with a file (class) or directory (package). + */ +public abstract class SourceElement { + private final PackageElement parent; + private final String name; + private final File file; + + SourceElement(PackageElement parent, String name, File file) { + Assert.isNotNull(name, "name cannot be null"); + Assert.isNotNull(file, "file cannot be null"); + Assert.isTrue(file.exists(), "file does not exist"); + + this.parent = parent; + this.name = name; + this.file = file; + + if(parent != null) + parent.addChild(this); + } + + /** + * Element name. + * @return (non-null) string + */ + public String getName() { + return name; + } + + /** + * Element file. + * @return (non-null) reference to the file + */ + public File getFile() { + return file; + } + + /** + * Is this element the root (implicitly package)? + * @return true if yes, false otherwise + */ + public boolean isRoot() { + return parent == null; + } + + /** + * Is this element a package? + * @return true if yes, false otherwise + */ + public boolean isPackage() { + return this instanceof PackageElement; + } + + /** + * Is this element a class? + * @return true if yes, false otherwise + */ + public boolean isClass() { + return this instanceof ClassElement; + } + + /** + * Parent package. + * @return the package that contains this element, or null if this element is the root. + */ + public PackageElement getParent() { + return parent; + } + + public String toString() { + return getName(); + } + + + /** + * Two source elements are equal if they have the same file (i.e. same path of the file). + */ + @Override + public final boolean equals(Object obj) { + return obj instanceof SourceElement && ((SourceElement) obj).file.equals(file); + } + + /** + * The hashcode of a source element is based on the absolute path of its file. + */ + @Override + public final int hashCode() { + return file.getAbsolutePath().hashCode(); + } + +} \ No newline at end of file diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/service/ProjectBrowserListener.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/service/ProjectBrowserListener.java new file mode 100644 index 0000000..94ad8ac --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/service/ProjectBrowserListener.java @@ -0,0 +1,47 @@ +package pt.iscte.pidesco.projectbrowser.service; + +import java.util.Collection; + +import pt.iscte.pidesco.projectbrowser.model.SourceElement; + +/** + * Represents a listener to Project Browser events. + */ +public interface ProjectBrowserListener { + + /** + * Invoked whenever a mouse double-click is performed on a source element of the tree. + * @param element (non-null) element under the double-click + */ + void doubleClick(SourceElement element); + + /** + * Invoked whenever the selection of elements in the tree changes. + * @param selection (non-null) collection of elements of the new selection, which may be empty + */ + void selectionChanged(Collection selection); + + + /** + * Interface adapter for convenience. Default implementations do nothing. + */ + public class Adapter implements ProjectBrowserListener { + + /** + * Does nothing. + */ + @Override + public void doubleClick(SourceElement element) { + + } + + /** + * Does nothing. + */ + @Override + public void selectionChanged(Collection selection) { + + } + } + +} diff --git a/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/service/ProjectBrowserServices.java b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/service/ProjectBrowserServices.java new file mode 100644 index 0000000..27aca44 --- /dev/null +++ b/pt.iscte.pidesco.projectbrowser/src/pt/iscte/pidesco/projectbrowser/service/ProjectBrowserServices.java @@ -0,0 +1,45 @@ +package pt.iscte.pidesco.projectbrowser.service; + +import pt.iscte.pidesco.projectbrowser.model.PackageElement; + +/** + * Service containing the operations offered by the Project Browser view. + */ +public interface ProjectBrowserServices { + + /** + * Id of the refresh tool + */ + public static final String REFRESH_TOOL_ID = "pt.iscte.pidesco.projectbrowser.refresh"; + + /** + * Obtain the root of the tree. + * @return non-null reference + */ + PackageElement getRootPackage(); + + /** + * Activate filter + * @param filterId (non-null) id of the filter to activate + */ + void activateFilter(String filterId); + + /** + * Deactivate filter + * @param filterId (non-null) id of the filter to deactivate + */ + void deactivateFilter(String filterId); + + /** + * Add a project browser listener. If listener already added, does nothing. + * @param listener (non-null) reference to the listener + */ + void addListener(ProjectBrowserListener listener); + + /** + * Remove a project browser listener. If listener does not exist, does nothing. + * @param listener (non-null) reference to the listener + */ + void removeListener(ProjectBrowserListener listener); + +} diff --git a/pt.iscte.pidesco/.classpath b/pt.iscte.pidesco/.classpath new file mode 100644 index 0000000..e8ea977 --- /dev/null +++ b/pt.iscte.pidesco/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/pt.iscte.pidesco/.project b/pt.iscte.pidesco/.project new file mode 100644 index 0000000..43d71e6 --- /dev/null +++ b/pt.iscte.pidesco/.project @@ -0,0 +1,28 @@ + + + pt.iscte.pidesco + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/pt.iscte.pidesco/.settings/org.eclipse.jdt.core.prefs b/pt.iscte.pidesco/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..d17b672 --- /dev/null +++ b/pt.iscte.pidesco/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/pt.iscte.pidesco/META-INF/MANIFEST.MF b/pt.iscte.pidesco/META-INF/MANIFEST.MF new file mode 100644 index 0000000..2fcc726 --- /dev/null +++ b/pt.iscte.pidesco/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Pidesco Core (RCP Application) +Bundle-SymbolicName: pt.iscte.pidesco;singleton:=true +Bundle-Version: 0.1 +Bundle-Activator: pt.iscte.pidesco.internal.PidescoActivator +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.ui +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-ActivationPolicy: lazy +Export-Package: pt.iscte.pidesco.extensibility diff --git a/pt.iscte.pidesco/build.properties b/pt.iscte.pidesco/build.properties new file mode 100644 index 0000000..e522427 --- /dev/null +++ b/pt.iscte.pidesco/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + . + diff --git a/pt.iscte.pidesco/plugin.xml b/pt.iscte.pidesco/plugin.xml new file mode 100644 index 0000000..d2b4da2 --- /dev/null +++ b/pt.iscte.pidesco/plugin.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pt.iscte.pidesco/schema/pt.iscte.pidesco.tool.exsd b/pt.iscte.pidesco/schema/pt.iscte.pidesco.tool.exsd new file mode 100644 index 0000000..5105d1f --- /dev/null +++ b/pt.iscte.pidesco/schema/pt.iscte.pidesco.tool.exsd @@ -0,0 +1,136 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + Tool id. Use a single token (e.g., "myview") + + + + + + + + + + Human-readable name of the tool. It will be used when no icon is available. + + + + + + + + + + + + + + + A class that provides the tool behavior. + + + + + + + + + + Is the tool to be used in active/inactive mode (toggle button)? Set to true if yes, false otherwise (default). + + + + + + + Tool icon, used in the tool bars. + + + + + + + The id of the view where the tool icon will be placed. + + + + + + + + + + Tool description to be used in tooltips. + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/pt.iscte.pidesco/schema/pt.iscte.pidesco.view.exsd b/pt.iscte.pidesco/schema/pt.iscte.pidesco.view.exsd new file mode 100644 index 0000000..30f1475 --- /dev/null +++ b/pt.iscte.pidesco/schema/pt.iscte.pidesco.view.exsd @@ -0,0 +1,104 @@ + + + + + + + + + Extension point for providing a Pidesco view. + + + + + + + + + + + + + + + + + + + + + + + + View id. Use a single token (e.g., "myview"). + + + + + + + + + + Human-readable name of the view. It will be used in the tab title text. + + + + + + + + + + + + + + + A class that provides the view contents. + + + + + + + + + + An optional icon associated with the view. The icon will be used in the view tab and application menu. Write a filename of an image (preferrebly GIF or PNG, e.g. "icon.png") that is contained in a folder named "images" of the contributor plugin. + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + + Pidesco views must implement the interface pt.iscte.pidesco.extensibility.PidescoView + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoExtensionPoint.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoExtensionPoint.java new file mode 100644 index 0000000..5799dd7 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoExtensionPoint.java @@ -0,0 +1,22 @@ +package pt.iscte.pidesco.extensibility; + +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; + +import pt.iscte.pidesco.internal.PidescoActivator; + +public enum PidescoExtensionPoint { + VIEW, + TOOL; + + private IExtensionRegistry reg = Platform.getExtensionRegistry(); + + public String getId() { + return PidescoActivator.PLUGIN_ID + "." + name().toLowerCase(); + } + + public IExtension[] getExtensions() { + return reg.getExtensionPoint(getId()).getExtensions(); + } + } \ No newline at end of file diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoServices.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoServices.java new file mode 100644 index 0000000..9521ec1 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoServices.java @@ -0,0 +1,58 @@ +package pt.iscte.pidesco.extensibility; + +import java.util.List; + +import org.eclipse.swt.graphics.Image; + + +/** + * Service containing operations offered by the Pidesco infrastructure. + */ +public interface PidescoServices { + + /** + * Name of the images folder from which plugin images will be indexed. + */ + public static final String IMAGES_FOLDER = "images"; + + /** + * View id of a Pidesco view (common to all views, which will have a secondary id) + */ + public static final String VIEW_ID = "pt.iscte.pidesco.view"; + + /** + * Opens Pidesco view. + * @param viewId view id + */ + void openView(String viewId); + + + /** + * Returns the active view id. + * @return (non-null) + */ + String getActiveView(); + + + /** + * Resets the view placement. + * @param viewLocations (non-null) list: view locations that depend on others + * should appear at a list position that is after their dependent view locations + */ + void layout(List viewLocations); + + /** + * Obtains image from plugin, assuming that the image is contained in the "images" folder. + * @param pluginId plugin id + * @param fileName name of the image file + * @return the image, or null if cannot be found + */ + Image getImageFromPlugin(String pluginId, String fileName); + + /** + * + * @param toolId tool id + */ + void runTool(String toolId, boolean activate); + +} \ No newline at end of file diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoTool.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoTool.java new file mode 100644 index 0000000..2f260b4 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoTool.java @@ -0,0 +1,16 @@ +package pt.iscte.pidesco.extensibility; + +/** + * Represents a Pidesco tool that can be attached to a view. + * - A concrete tool may optionally consider to be in active/inactive mode (toggle button). + * - There must exist a zero-argument constructor + * - Objects should be stateless, i.e. should have no instance attributes + */ +public interface PidescoTool { + + /** + * Runs the tool. Parameter may be ignored if the tool executes always in the same way. + * @param activate true if the tool was turned into active mode (toggle button selected), false otherwise. + */ + void run(boolean activate); +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoView.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoView.java new file mode 100644 index 0000000..0998a4e --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/PidescoView.java @@ -0,0 +1,21 @@ +package pt.iscte.pidesco.extensibility; + +import java.util.Map; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; + +/** + * Represents a Pidesco view. + * Images that are contained in a folder named "images" located at the root of the plugin can accessed with + * a key equal to the filename (e.g., "icon.png"). + * - There must exist a zero-argument constructor + */ +public interface PidescoView { + + /** + * @param viewArea (not-null) composite where the contents of the view should be added (by default, it is configured with the FillLayout) + * @paran imageMap (not-null) map indexing the images contained in the "images" folder of the plugin + */ + void createContents(Composite viewArea, Map imageMap); +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/ViewLocation.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/ViewLocation.java new file mode 100644 index 0000000..3f1d789 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/extensibility/ViewLocation.java @@ -0,0 +1,81 @@ +package pt.iscte.pidesco.extensibility; + +import org.eclipse.core.runtime.Assert; + +/** + * Describes the location of a view. + */ +public final class ViewLocation { + + /** + * View position with respect to another relative view + */ + public enum Position { + TOP, BOTTOM, LEFT, RIGHT; + } + + private final String viewId; + private final String relativeViewId; + private final Position position; + private final double ratio; + + /** + * Creates a location relative to an existing view. + * @param viewId (non-null) view id + * @param relativeViewId view id to which the view position is relative to; if null, the view is relative to the editor area + * @param position position to the relative view + * @param ratio percentage of the available space to fill in; value must be within ]0.0, 1.0[ + */ + public ViewLocation(String viewId, String relativeViewId, Position position, double ratio) { + Assert.isNotNull(viewId, "view id cannot be null"); + Assert.isNotNull(position, "position cannot be null"); + Assert.isTrue(ratio > 0.0 && ratio < 1.0, "ratio must be in the range ]0.0, 1.0["); + + this.viewId = viewId; + this.relativeViewId = relativeViewId; + this.position = position; + this.ratio = ratio; + } + + /** + * Creates a location relative to the editor area. + * @param viewId (non-null) view id + * @param position position to the relative view + * @param ratio percentage of the available space to fill in; value must be within ]0.0, 1.0[ + */ + public ViewLocation(String viewId, Position position, double ratio) { + this(viewId, null, position, ratio); + } + + /** + * Returns the view id + * @return (non-null) + */ + public String getViewId() { + return viewId; + } + + /** + * Returns the relative view id + * @return may be null, meaning that the relative view is the editor area + */ + public String getRelativeViewId() { + return relativeViewId; + } + + /** + * Returns the position to which the view is place in relation with the relative view + * @return (non-null) + */ + public Position getPosition() { + return position; + } + + /** + * Returns the ratio of available space that the view fills in. + * @return value in the range ]0.0, 1.0[ + */ + public double getRatio() { + return ratio; + } +} \ No newline at end of file diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/AbstractPidescoView.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/AbstractPidescoView.java new file mode 100644 index 0000000..1a1a0fe --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/AbstractPidescoView.java @@ -0,0 +1,147 @@ +package pt.iscte.pidesco.internal; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.ISizeProvider; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.part.ViewPart; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleException; + +import pt.iscte.pidesco.extensibility.PidescoExtensionPoint; +import pt.iscte.pidesco.extensibility.PidescoServices; +import pt.iscte.pidesco.extensibility.PidescoTool; +import pt.iscte.pidesco.internal.PidescoActivator.ViewComponent; + +public class AbstractPidescoView extends ViewPart implements ISizeProvider { + + private static String IMAGES_FLODER_PATH = PidescoServices.IMAGES_FOLDER + "/"; + + private ViewComponent vcomponent; + private Composite parent; + + @Override + public void init(IViewSite site) throws PartInitException { + super.init(site); + vcomponent = PidescoActivator.getInstance().getComponent(site.getSecondaryId()); + IActionBars bars = getViewSite().getActionBars(); + fillLocalToolBar(bars.getToolBarManager()); + } + + @Override + public void createPartControl(Composite parent) { + this.parent = parent; + setPartName(vcomponent.viewTitle); + if(vcomponent.icon != null) + setTitleImage(vcomponent.icon.createImage()); + setTitleToolTip("Contributor: " + vcomponent.pluginId); + parent.setLayout(new FillLayout()); + Map imagesMap = Collections.unmodifiableMap(buildImageMap()); + vcomponent.createContents(parent, imagesMap); + } + + @Override + public void setFocus() { + parent.setFocus(); + } + + + private Map buildImageMap() { + Map imagesMap = new HashMap(); + Bundle bundle = Platform.getBundle(vcomponent.pluginId); + Enumeration imgs = bundle.getEntryPaths(IMAGES_FLODER_PATH); + if(imgs != null) { + while(imgs.hasMoreElements()) { + String path = imgs.nextElement(); + String key = path.substring(IMAGES_FLODER_PATH.length()); + try { + ImageDescriptor desc = PidescoActivator.imageDescriptorFromPlugin(vcomponent.pluginId, path); + if(desc != null) { + imagesMap.put(key, desc.createImage()); + } + } + catch(SWTException e) { + + } + } + } + return imagesMap; + } + + + + private void fillLocalToolBar(IToolBarManager manager) { + for(IExtension ext : PidescoExtensionPoint.TOOL.getExtensions()) { + IConfigurationElement c = ext.getConfigurationElements()[0]; + + if(c.getAttribute("view").equals(vcomponent.viewId)) { + String contributor = ext.getContributor().getName(); + final String toolName = ext.getLabel(); + try { + final PidescoTool tool = (PidescoTool) c.createExecutableExtension("class"); + boolean toggle = Boolean.parseBoolean(c.getAttribute("hasState")); + final Action action = new Action(toolName, toggle ? IAction.AS_CHECK_BOX : IAction.AS_PUSH_BUTTON) { + public void run() { + tool.run(isChecked()); + } + }; + + action.setText(toolName); + action.setToolTipText(c.getAttribute("description") + "\n" + "Contributor: " + contributor); + String iconPath = IMAGES_FLODER_PATH + c.getAttribute("icon"); + ImageDescriptor icon = PidescoActivator.imageDescriptorFromPlugin(contributor, iconPath); + if(icon != null) + action.setImageDescriptor(icon); + + manager.add(action); + } + catch (CoreException e) { + e.printStackTrace(); + continue; + } + } + } + } + + @Override + public void dispose() { + super.dispose(); + try { + Platform.getBundle(vcomponent.pluginId).stop(); + } catch (BundleException e) { + e.printStackTrace(); + } + + } + + @Override + public int getSizeFlags(boolean width) { + return SWT.MIN; + } + + @Override + public int computePreferredSize(boolean width, int availableParallel, + int availablePerpendicular, int preferredResult) { + System.out.println(availableParallel + " " + availablePerpendicular); + return 200; + } + +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/Application.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/Application.java new file mode 100644 index 0000000..f21fd7f --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/Application.java @@ -0,0 +1,39 @@ +package pt.iscte.pidesco.internal; + +import org.eclipse.equinox.app.IApplication; +import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + +/** + * This class controls all aspects of the application's execution + */ +public class Application implements IApplication { + + public Object start(IApplicationContext context) { + Display display = PlatformUI.createDisplay(); + try { + int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor()); + if (returnCode == PlatformUI.RETURN_RESTART) { + return IApplication.EXIT_RESTART; + } + return IApplication.EXIT_OK; + } finally { + display.dispose(); + } + } + + public void stop() { + if (!PlatformUI.isWorkbenchRunning()) + return; + final IWorkbench workbench = PlatformUI.getWorkbench(); + final Display display = workbench.getDisplay(); + display.syncExec(new Runnable() { + public void run() { + if (!display.isDisposed()) + workbench.close(); + } + }); + } +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationActionBarAdvisor.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationActionBarAdvisor.java new file mode 100644 index 0000000..74a70ab --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationActionBarAdvisor.java @@ -0,0 +1,61 @@ +package pt.iscte.pidesco.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; + +import pt.iscte.pidesco.extensibility.PidescoExtensionPoint; +import pt.iscte.pidesco.internal.PidescoActivator.ViewComponent; + +public class ApplicationActionBarAdvisor extends ActionBarAdvisor { + + public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) { + super(configurer); + } + + protected void fillMenuBar(IMenuManager menuBar) { + MenuManager viewsMenu = new MenuManager("&Views", "views"); + menuBar.add(viewsMenu); + List components = new ArrayList(PidescoActivator.getInstance().getComponents()); + Collections.sort(components); + + for(final ViewComponent vc : components) + viewsMenu.add(new Action() { + @Override + public String getText() { + return vc.viewTitle; + } + + @Override + public String getId() { + return vc.pluginId + "." + vc.viewId; + } + + @Override + public ImageDescriptor getImageDescriptor() { + return vc.icon == null ? super.getImageDescriptor() : vc.icon; + } + + @Override + public void run() { + try { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + page.showView(PidescoExtensionPoint.VIEW.getId(), vc.getSecondaryId(), IWorkbenchPage.VIEW_ACTIVATE); + } catch (PartInitException e) { + e.printStackTrace(); + } + } + + }); + } +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationWorkbenchAdvisor.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationWorkbenchAdvisor.java new file mode 100644 index 0000000..8be9ee3 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationWorkbenchAdvisor.java @@ -0,0 +1,24 @@ +package pt.iscte.pidesco.internal; + +import org.eclipse.ui.application.IWorkbenchConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchAdvisor; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { + + private static final String PERSPECTIVE_ID = "pt.iscte.pidesco.perspective"; + + public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { + return new ApplicationWorkbenchWindowAdvisor(configurer); + } + + public void initialize(IWorkbenchConfigurer configurer) { + super.initialize(configurer); + configurer.setSaveAndRestore(true); + } + + public String getInitialWindowPerspectiveId() { + return PERSPECTIVE_ID; + } +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationWorkbenchWindowAdvisor.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationWorkbenchWindowAdvisor.java new file mode 100644 index 0000000..422fdac --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/ApplicationWorkbenchWindowAdvisor.java @@ -0,0 +1,26 @@ +package pt.iscte.pidesco.internal; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { + + public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { + super(configurer); + } + + public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) { + return new ApplicationActionBarAdvisor(configurer); + } + + public void preWindowOpen() { + IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); + configurer.setInitialSize(new Point(1200, 800)); + configurer.setShowCoolBar(false); + configurer.setShowStatusLine(true); + configurer.setShowPerspectiveBar(false); + } +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/Perspective.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/Perspective.java new file mode 100644 index 0000000..99357f3 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/Perspective.java @@ -0,0 +1,43 @@ +package pt.iscte.pidesco.internal; + +import java.util.List; + +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +import pt.iscte.pidesco.extensibility.PidescoServices; +import pt.iscte.pidesco.extensibility.ViewLocation; + +public class Perspective implements IPerspectiveFactory { + + + @Override + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(true); + List locations = PidescoActivator.getInstance().getViewLocations(); + + for(ViewLocation loc : locations) { + String view = PidescoServices.VIEW_ID + ":" + loc.getViewId(); + String relative = loc.getRelativeViewId(); + if(relative == null) + relative = IPageLayout.ID_EDITOR_AREA; + else + relative = PidescoServices.VIEW_ID + ":" + relative; + +// layout.addView(view, match(loc.getPosition()), new Float(loc.getRatio()), relative); + layout.addStandaloneView(view, true, match(loc.getPosition()), new Float(loc.getRatio()), relative); + } + // List = PidescoActivator.getInstance().getLayout(); + // playout. + } + + private static int match(ViewLocation.Position p) { + switch(p) { + case TOP: return IPageLayout.TOP; + case BOTTOM: return IPageLayout.BOTTOM; + case LEFT: return IPageLayout.LEFT; + case RIGHT: return IPageLayout.RIGHT; + default: return 0; + } + } +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/PidescoActivator.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/PidescoActivator.java new file mode 100644 index 0000000..49cdf19 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/PidescoActivator.java @@ -0,0 +1,186 @@ +package pt.iscte.pidesco.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.FrameworkUtil; + +import pt.iscte.pidesco.extensibility.PidescoExtensionPoint; +import pt.iscte.pidesco.extensibility.PidescoServices; +import pt.iscte.pidesco.extensibility.PidescoView; +import pt.iscte.pidesco.extensibility.ViewLocation; + +public class PidescoActivator extends AbstractUIPlugin { + + public static final String PLUGIN_ID; + + static { + PLUGIN_ID = FrameworkUtil.getBundle(PidescoActivator.class).getSymbolicName(); + } + + // singleton instance + private static PidescoActivator plugin; + + public static PidescoActivator getInstance() { + return plugin; + } + + private PidescoServices services; + private Map components; + + static class ViewComponent implements Comparable, PidescoView { + final PidescoView component; + final String pluginId; + final String viewId; + final String viewTitle; + final ImageDescriptor icon; + + ViewComponent(PidescoView component, String pluginId, String viewId, String viewTitle, ImageDescriptor icon) { + this.component = component; + this.pluginId = pluginId; + this.viewId = viewId; + this.viewTitle = viewTitle; + this.icon = icon; + } + + static String secondaryId(String pluginId, String viewId) { + return pluginId + "." + viewId; + } + + String getSecondaryId() { + return viewId; + } + + + @Override + public int compareTo(ViewComponent o) { + return viewTitle.compareTo(o.viewTitle); + } + + @Override + public void createContents(Composite viewArea, Map reg) { + try { + Platform.getBundle(pluginId).start(); + } catch (BundleException e) { + e.printStackTrace(); + } + component.createContents(viewArea, reg); + } + } + + + + private void loadPlugins() throws CoreException { + components = new HashMap(); + + for(IExtension viewExtension : PidescoExtensionPoint.VIEW.getExtensions()) { + String pluginId = viewExtension.getContributor().getName(); + String viewId = viewExtension.getUniqueIdentifier(); + String viewTitle = viewExtension.getLabel(); + + IConfigurationElement comp = viewExtension.getConfigurationElements()[0]; + PidescoView c = (PidescoView) comp.createExecutableExtension("class"); + String iconPath = PidescoServicesImpl.IMAGES_FOLDER + "/" + comp.getAttribute("icon"); + ImageDescriptor icon = null; + if(iconPath != null && !iconPath.isEmpty()) { + try { + icon = imageDescriptorFromPlugin(pluginId, iconPath); + } + catch(RuntimeException e) { + logPluginError(pluginId, "could not load view icon '" + iconPath + "'"); + } + } + + ViewComponent vc = new ViewComponent(c, pluginId, viewId, viewTitle, icon); + components.put(viewId, vc); + } + } + + + void logPluginError(String pluginId, String message) { + System.err.println(pluginId + ": " + message); + } + + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + services = new PidescoServicesImpl(context); + context.registerService(PidescoServices.class, services, null); + loadPlugins(); + } + + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + + ViewComponent getComponent(String viewId) { + return components.get(viewId); + } + + + + public static ImageDescriptor getImageDescriptor(String path) { + return getImageDescriptor(PLUGIN_ID, path); + } + + public static ImageDescriptor getImageDescriptor(String pluginId, String path) { + return imageDescriptorFromPlugin(pluginId, path); + } + + public Collection getComponents() { + return Collections.unmodifiableCollection(components.values()); + } + + + public PidescoServices getService() { + return services; + } + + + private List viewLocations; + + void setLayout(List viewLocations) { + this.viewLocations = viewLocations; + } + + + List getViewLocations() { + if(viewLocations == null) + return Collections.emptyList(); + else + return viewLocations; + } + +// private String activeViewId; +// +// public String getActiveViewId() { +// return activeViewId; +// } + +// @Override +// public void partActivated(IWorkbenchPartReference partRef) { +// if(partRef instanceof IViewReference) +// activeViewId = ((IViewReference) partRef).getSecondaryId(); +// else if(partRef instanceof IEditorReference) +// activeViewId = ((IEditorReference) partRef).getId(); +// System.out.println("activated: " + activeViewId); +// } + + + +} diff --git a/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/PidescoServicesImpl.java b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/PidescoServicesImpl.java new file mode 100644 index 0000000..a05c678 --- /dev/null +++ b/pt.iscte.pidesco/src/pt/iscte/pidesco/internal/PidescoServicesImpl.java @@ -0,0 +1,102 @@ +package pt.iscte.pidesco.internal; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.osgi.framework.BundleContext; + +import pt.iscte.pidesco.extensibility.PidescoExtensionPoint; +import pt.iscte.pidesco.extensibility.PidescoServices; +import pt.iscte.pidesco.extensibility.PidescoTool; +import pt.iscte.pidesco.extensibility.ViewLocation; + +public class PidescoServicesImpl implements PidescoServices { + + private Map tools; + + PidescoServicesImpl(BundleContext context) { + tools = new HashMap(); + + for(IExtension ext : PidescoExtensionPoint.TOOL.getExtensions()) { + try { + PidescoTool tool = (PidescoTool) ext.getConfigurationElements()[0].createExecutableExtension("class"); + tools.put(ext.getUniqueIdentifier(), tool); + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void openView(String viewId) { + Assert.isNotNull(viewId, "view id cannot be null"); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + page.showView(PidescoServices.VIEW_ID, viewId, IWorkbenchPage.VIEW_ACTIVATE); + } catch (PartInitException e) { + e.printStackTrace(); + } + } + +// @Override +// public void closeView(String viewId) { +// Assert.isNotNull(viewId, "view id cannot be null"); +// IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); +// IViewPart view = page.findView(viewId); +// Assert.isNotNull(view, "view not found"); +// page.hideView(view); +// } + + + + @Override + public String getActiveView() { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IWorkbenchPart activePart = page.getActivePart(); + if(activePart != null) { + if(activePart instanceof IViewPart) + return ((IViewPart) activePart).getViewSite().getSecondaryId(); + else if(activePart instanceof IEditorPart) + return ((IEditorPart) activePart).getEditorSite().getId(); + } + return null; + } + + @Override + public Image getImageFromPlugin(String pluginId, String fileName) { + Assert.isNotNull(pluginId, "plugin id cannot be null"); + Assert.isNotNull(fileName, "file name cannot be null"); + + ImageDescriptor imgDesc = PidescoActivator.getImageDescriptor(pluginId, IMAGES_FOLDER + "/" + fileName); + return imgDesc == null ? null : imgDesc.createImage(); + } + + + @Override + public void runTool(String toolId, boolean activate) { + Assert.isNotNull(toolId, "tool id cannot be null"); + Assert.isTrue(tools.containsKey(toolId), "toolId '" + toolId + "' does not exist"); + tools.get(toolId).run(activate); + + } + + @Override + public void layout(List viewLocations) { + PidescoActivator.getInstance().setLayout(viewLocations); + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().resetPerspective(); + } + + +}