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();
+ }
+
+
+}