new buildconfig plugin
diff --git a/org.eclipse.ajdt.ui.buildconfig/.classpath b/org.eclipse.ajdt.ui.buildconfig/.classpath
new file mode 100644
index 0000000..9bc605c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="ASPECTJRT_LIB"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.ajdt.ui.buildconfig/.cvsignore b/org.eclipse.ajdt.ui.buildconfig/.cvsignore
new file mode 100755
index 0000000..67b544a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/.cvsignore
@@ -0,0 +1,3 @@
+bin
+build
+dist
diff --git a/org.eclipse.ajdt.ui.buildconfig/.project b/org.eclipse.ajdt.ui.buildconfig/.project
new file mode 100644
index 0000000..4556b18
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.ajdt.ui.buildconfig</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.ajdt.core.ajbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.ajdt.ui.buildconfig/META-INF/MANIFEST.MF b/org.eclipse.ajdt.ui.buildconfig/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..81444b3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/META-INF/MANIFEST.MF
@@ -0,0 +1,39 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.ajdt.ui.buildconfig; singleton:=true
+Bundle-Version: 1.3.0.DEVELOPMENT
+Bundle-Localization: plugin
+Bundle-Vendor: %providerName
+Bundle-Activator: org.eclipse.ajdt.ui.buildconfig.BuildConfigPlugin
+Export-Package: org.eclipse.ajdt.internal.buildconfig;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.actions;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.editor;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.editor.model;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.menu;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.propertypage;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.wizards;x-internal:=true,
+ org.eclipse.ajdt.pde.internal.ui.editor;x-internal:=true,
+ org.eclipse.ajdt.pde.internal.ui.editor.context;x-internal:=true,
+ org.eclipse.ajdt.ui.buildconfig
+Require-Bundle: org.aspectj.ajde,
+ org.eclipse.ajdt.core,
+ org.eclipse.core.resources,
+ org.eclipse.core.runtime,
+ org.eclipse.ajdt.ui,
+ org.eclipse.jface,
+ org.eclipse.ui,
+ org.eclipse.jdt.core,
+ org.eclipse.jdt.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.contribution.xref.ui,
+ org.eclipse.pde.core,
+ org.eclipse.ui.forms,
+ org.eclipse.jface.text,
+ org.eclipse.pde.ui,
+ org.eclipse.ui.workbench.texteditor,
+ org.eclipse.ui.editors,
+ org.eclipse.search,
+ org.eclipse.ui.views
+Eclipse-AutoStart: true
+Eclipse-RegisterBuddy: org.eclipse.ajdt.ui
diff --git a/org.eclipse.ajdt.ui.buildconfig/about.html b/org.eclipse.ajdt.ui.buildconfig/about.html
new file mode 100755
index 0000000..1b5fac9
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/about.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>1st March, 2003</p>
+<h3>License</h3>
+<p>Eclipse.org makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Common Public License Version 1.0 ("CPL"). A copy of the CPL is available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>.
+For purposes of the CPL, "Program" will mean the Content.</p>
+
+<h3>Contributions</h3>
+
+<p>If this Content is licensed to you under the terms and conditions of the CPL, any Contributions, as defined in the CPL, uploaded, submitted, or otherwise
+made available to Eclipse.org, members of Eclipse.org and/or the host of Eclipse.org web site, by you that relate to such
+Content are provided under the terms and conditions of the CPL and can be made available to others under the terms of the CPL.</p>
+
+<p>If this Content is licensed to you under license terms and conditions other than the CPL ("Other License"), any modifications, enhancements and/or
+other code and/or documentation ("Modifications") uploaded, submitted, or otherwise made available to Eclipse.org, members of Eclipse.org and/or the
+host of Eclipse.org, by you that relate to such Content are provided under terms and conditions of the Other License and can be made available
+to others under the terms of the Other License. In addition, with regard to Modifications for which you are the copyright holder, you are also
+providing the Modifications under the terms and conditions of the CPL and such Modifications can be made available to others under the terms of
+the CPL.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/build.ajproperties b/org.eclipse.ajdt.ui.buildconfig/build.ajproperties
new file mode 100644
index 0000000..7db383d
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/build.ajproperties
@@ -0,0 +1,2 @@
+src.includes = src/
+src.excludes = src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java
diff --git a/org.eclipse.ajdt.ui.buildconfig/build.properties b/org.eclipse.ajdt.ui.buildconfig/build.properties
new file mode 100644
index 0000000..9bb04e1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+bin.includes = META-INF/,\
+ .
+src.includes = src/
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/buildconfig_file.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/buildconfig_file.gif
new file mode 100755
index 0000000..1de898e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/buildconfig_file.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/exclusion_filter_attrib.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/exclusion_filter_attrib.gif
new file mode 100644
index 0000000..92bce14
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/exclusion_filter_attrib.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/inclusion_filter_attrib.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/inclusion_filter_attrib.gif
new file mode 100644
index 0000000..ca17a44
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/inclusion_filter_attrib.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/new_build_config_wizard.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/new_build_config_wizard.gif
new file mode 100755
index 0000000..aeb0236
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/new_build_config_wizard.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/plugin.properties b/org.eclipse.ajdt.ui.buildconfig/plugin.properties
new file mode 100644
index 0000000..7133595
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/plugin.properties
@@ -0,0 +1,28 @@
+######################################################################
+#Copyright (c) 2005 IBM Corporation and others.
+#All rights reserved. This program and the accompanying materials
+#are made available under the terms of the Common Public License v1.0
+#which accompanies this distribution, and is available at
+#http://www.eclipse.org/legal/cpl-v10.html
+#Contributors:
+#Matt Chapman - initial version to separate out build configuration
+# support from the UI plugin
+#...
+######################################################################
+pluginName=AspectJ Development Tools Build Config support
+providerName=Eclipse.org
+
+# Build configuration
+# -------------------
+activateConfig=&Activate Build Configuration
+saveAsAJProperties=&Save as .ajproperties File
+saveAsLst=&Save as .lst File
+BuildConfigDecorator.label=AspectJ Build Configuration and Advice Indicator
+BuildConfigDecorator.description=Decorates packages and source files to indicate whether or not they are included in the active build configuration, and decorates the active configuration file.
+excludeFromBuildConfig=&Exclude from active build configuration
+includeInActiveBuildConfig=&Include in active build configuration
+
+buildConfigFile=Build Configuration
+buildConfigDescription=Create a new AspectJ build configuration
+
+org.eclipse.ajdt.ui.tools=Aspect&J Tools
diff --git a/org.eclipse.ajdt.ui.buildconfig/plugin.xml b/org.eclipse.ajdt.ui.buildconfig/plugin.xml
new file mode 100644
index 0000000..df46922
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/plugin.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+
+<plugin>
+
+ <extension
+ point="org.eclipse.ui.popupMenus">
+ <objectContribution
+ objectClass="org.eclipse.jdt.core.IJavaElement"
+ id="Build Configurator Plugin.objectContribution2">
+ <menu
+ label="%org.eclipse.ajdt.ui.tools"
+ id="org.eclipse.ajdt.ui.feature.tools">
+ <separator
+ name="group0">
+ </separator>
+ <separator
+ name="group1">
+ </separator>
+ <separator
+ name="group2">
+ </separator>
+ </menu>
+ <action
+ label="%excludeFromBuildConfig"
+ class="org.eclipse.ajdt.internal.buildconfig.actions.ExcludeAction"
+ menubarPath="org.eclipse.ajdt.ui.feature.tools/group0"
+ icon="icons/buildconfig/exclusion_filter_attrib.gif"
+ id="exclude">
+ </action>
+ <visibility>
+ <and>
+ <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+ <or>
+ <objectClass name="org.eclipse.jdt.core.ICompilationUnit"/>
+ <objectClass name="org.eclipse.jdt.core.IPackageFragment"/>
+ </or>
+ </and>
+ </visibility>
+ </objectContribution>
+ <objectContribution
+ objectClass="org.eclipse.jdt.core.IJavaElement"
+ id="Build Configurator Plugin.objectContribution1">
+ <menu
+ label="%org.eclipse.ajdt.ui.tools"
+ id="org.eclipse.ajdt.ui.feature.tools">
+ <separator
+ name="group0">
+ </separator>
+ <separator
+ name="group1">
+ </separator>
+ <separator
+ name="group2">
+ </separator>
+ </menu>
+ <action
+ label="%includeInActiveBuildConfig"
+ class="org.eclipse.ajdt.internal.buildconfig.actions.IncludeAction"
+ menubarPath="org.eclipse.ajdt.ui.feature.tools/group0"
+ icon="icons/buildconfig/inclusion_filter_attrib.gif"
+ id="include">
+ </action>
+ <visibility>
+ <and>
+ <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+ <or>
+ <objectClass name="org.eclipse.jdt.core.ICompilationUnit"/>
+ <objectClass name="org.eclipse.jdt.core.IPackageFragment"/>
+ </or>
+ </and>
+ </visibility>
+ </objectContribution>
+ <objectContribution
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.lst"
+ id="buildfilecontributions">
+ <visibility>
+ <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+ </visibility>
+ <menu
+ label="%org.eclipse.ajdt.ui.tools"
+ id="org.eclipse.ajdt.ui.feature.tools">
+ <separator
+ name="group0">
+ </separator>
+ <separator
+ name="group1">
+ </separator>
+ <separator
+ name="group2">
+ </separator>
+ </menu>
+ <action
+ label="%saveAsAJProperties"
+ class="org.eclipse.ajdt.internal.buildconfig.actions.ImportAction"
+ menubarPath="org.eclipse.ajdt.ui.feature.tools/group1"
+ id="buildselectorpopup">
+ </action>
+ </objectContribution>
+
+ <objectContribution
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.ajproperties"
+ id="ajproperties">
+ <visibility>
+ <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+ </visibility>
+ <menu
+ label="%org.eclipse.ajdt.ui.tools"
+ id="org.eclipse.ajdt.ui.feature.tools">
+ <separator
+ name="group0">
+ </separator>
+ <separator
+ name="group1">
+ </separator>
+ <separator
+ name="group2">
+ </separator>
+ </menu>
+ <action
+ label="%activateConfig"
+ class="org.eclipse.ajdt.internal.buildconfig.actions.ActivateAction"
+ menubarPath="org.eclipse.ajdt.ui.feature.tools/group0"
+ id="ajpropertiespopup">
+ </action>
+ <action
+ label="%saveAsLst"
+ class="org.eclipse.ajdt.internal.buildconfig.actions.ExportAction"
+ menubarPath="org.eclipse.ajdt.ui.feature.tools/group1"
+ id="org.eclipse.ajdt.buildconfigurator.exportAction"/>
+ </objectContribution>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.decorators">
+ <decorator
+ lightweight="false"
+ label="%BuildConfigDecorator.label"
+ class="org.eclipse.ajdt.internal.buildconfig.ImageDecorator"
+ state="true"
+ id="org.eclipse.ajdt.buildconfig.decorator">
+ <description>
+ %BuildConfigDecorator.description
+ </description>
+ <enablement>
+ <objectClass
+ name="java.lang.Object">
+ </objectClass>
+ </enablement>
+ <description>
+ </description>
+ </decorator>
+ </extension>
+
+ <extension
+ id="editors"
+ point="org.eclipse.ui.editors">
+ <editor
+ name="%ajPropertiesEditor"
+ icon="icons/buildconfig/buildconfig_file.gif"
+ extensions="ajproperties"
+ contributorClass="org.eclipse.ajdt.internal.buildconfig.editor.BuildEditorContributor"
+ class="org.eclipse.ajdt.internal.buildconfig.editor.BuildEditor"
+ id="AJPropertiesEditor">
+ </editor>
+ </extension>
+
+ <!--
+ <extension
+ point="org.eclipse.ui.propertyPages">
+ <page
+ objectClass="org.eclipse.core.resources.IProject"
+ adaptable="true"
+ name="%javaBuildPath"
+ class="org.eclipse.ajdt.internal.buildconfig.propertypage.BCPropertyPage"
+ id="org.eclipse.ajdt.ui.ConfiguratorPage">
+ <filter
+ name="projectNature"
+ value="org.eclipse.ajdt.ui.ajnature">
+ </filter>
+ </page>
+ </extension>
+ -->
+
+ <extension point="org.eclipse.ui.newWizards">
+ <!-- Define wizard for creating new build configurations -->
+ <wizard
+ name="%buildConfigFile"
+ icon="icons/buildconfig/new_build_config_wizard.gif"
+ category="org.eclipse.ajdt.wizards"
+ class="org.eclipse.ajdt.internal.buildconfig.wizards.BuildConfigurationFileWizard"
+ finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
+ id="ajbuildconfigwizard">
+ <description>
+ %buildConfigDescription
+ </description>
+ </wizard>
+ </extension>
+
+ <extension point="org.eclipse.ui.startup">
+ </extension>
+
+</plugin>
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceChangeListener.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceChangeListener.java
new file mode 100644
index 0000000..870fcb8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceChangeListener.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.io.File;
+
+import org.aspectj.ajdt.internal.core.builder.IncrementalStateManager;
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.core.model.AJModel;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * @author Luzius Meisser
+ *
+ * Listens to resource changes and:
+ *
+ * -informs BuildConfigurator if a project gets closed or deleted -lets
+ * BCResourceDeltaVisitor visit the delta otherwise
+ *
+ */
+public class BCResourceChangeListener implements IResourceChangeListener {
+ private BCResourceDeltaVisitor myDeltaVisitor;
+
+ private IBuildConfigurator myBCor;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+ */
+ public BCResourceChangeListener() {
+ myDeltaVisitor = new BCResourceDeltaVisitor();
+ myBCor = DefaultBuildConfigurator.getBuildConfigurator();
+ }
+
+ public void resourceChanged(IResourceChangeEvent event) {
+ if ((event.getType() == IResourceChangeEvent.PRE_CLOSE)
+ || (event.getType() == IResourceChangeEvent.PRE_DELETE)) {
+ IResource res = event.getResource();
+ if (res.getType() == IResource.PROJECT) {
+ IProject project = (IProject) res;
+ ((BuildConfigurator)myBCor).closeProject(project);
+ boolean delete = (event.getType() == IResourceChangeEvent.PRE_DELETE);
+ String lstFileName = AspectJPlugin.getBuildConfigurationFile(project);
+ File lstFile = new File(lstFileName);
+ if (delete && lstFile.exists()) {
+ lstFile.delete();
+ }
+ AJModel.getInstance().clearMap(project, delete);
+ IncrementalStateManager
+ .removeIncrementalStateInformationFor(AspectJPlugin
+ .getBuildConfigurationFile(project));
+ }
+ } else if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
+ // avoid processing deltas for non-AspectJ projects,
+ IResourceDelta delta = event.getDelta();
+ if (delta != null) {
+ IResourceDelta[] cd = delta.getAffectedChildren();
+ if (cd == null) {
+ try {
+ delta.accept(myDeltaVisitor);
+ } catch (CoreException e) {
+ }
+ } else {
+ for (int i = 0; i < cd.length; i++) {
+ try {
+ IResource res = cd[i].getResource();
+ if (res == null) {
+ cd[i].accept(myDeltaVisitor);
+ } else {
+ IProject proj = res.getProject();
+ // if we don't know the project, or it is
+ // no longer accessible, we'd better process
+ // the delta. Otherwise we only process it
+ // if it is an AspectJ project.
+ if ((proj == null) || !proj.isAccessible()
+ || AspectJPlugin.isAJProject(proj)) {
+ cd[i].accept(myDeltaVisitor);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceDeltaVisitor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceDeltaVisitor.java
new file mode 100644
index 0000000..b4e48df
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceDeltaVisitor.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.bc.BuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+
+/**
+ * @author Luzius Meisser
+ *
+ * This ResourceDeltaVisitor initiates the appropriate measures if it finds
+ * removed folders or changes in project descriptions.
+ *
+ * If a folder gets deleted, BuildConfigurations that used this folder as source
+ * need to be changed. If a project description changes, we have to let the
+ * BuildConfigurator check if its aj nature was removed.
+ *
+ */
+public class BCResourceDeltaVisitor implements IResourceDeltaVisitor {
+ private IBuildConfigurator myBCor;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+ */
+ public BCResourceDeltaVisitor() {
+ myBCor = DefaultBuildConfigurator.getBuildConfigurator();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+ */
+ public boolean visit(IResourceDelta delta) {
+ IResource myRes = delta.getResource();
+ if (myRes.getType() == IResource.FILE) {
+ switch (delta.getKind()) {
+ case IResourceDelta.CHANGED:
+ if (BuildConfiguration.EXTENSION.equals(myRes
+ .getFileExtension())) {
+ new UpdateJob(myBCor, UpdateJob.BUILD_CONFIG_CHANGED, myRes)
+ .schedule();
+ } else if (".classpath".equals(myRes.getName())) { //$NON-NLS-1$
+ new UpdateJob(myBCor, UpdateJob.CLASSPATH_CHANGED, myRes)
+ .schedule();
+ }
+ break;
+ case IResourceDelta.REMOVED:
+ //Build Configuration has been deleted
+ if (BuildConfiguration.EXTENSION.equals(myRes
+ .getFileExtension())) {
+ new UpdateJob(myBCor, UpdateJob.BUILD_CONFIG_REMOVED, myRes)
+ .schedule();
+ }
+ break;
+ case IResourceDelta.ADDED:
+ if ((delta.getFlags() & IResourceDelta.MOVED_FROM) == 0){
+ if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(myRes
+ .getName())) {
+ new UpdateJob(myBCor, UpdateJob.SOURCE_ADDED, myRes)
+ .schedule();
+ }
+ } else {
+ IFile oldLocation = myRes.getWorkspace().getRoot().getFile(delta.getMovedFromPath());
+ if (oldLocation != null){
+ new UpdateJob(myBCor, UpdateJob.FILE_MOVED, myRes, oldLocation).schedule();
+ }
+ }
+ break;
+ }
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCWorkbenchWindowInitializer.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCWorkbenchWindowInitializer.java
new file mode 100644
index 0000000..c7ed71a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCWorkbenchWindowInitializer.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import org.eclipse.ajdt.internal.buildconfig.menu.DynamicBuildConfigurationMenu;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.ui.IStartup;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.internal.WorkbenchWindow;
+
+/**
+ * @author Luzius Meisser
+ *
+ * Adds the menu and our selection listener to all workbench windows.
+ */
+public class BCWorkbenchWindowInitializer implements IWindowListener, IStartup {
+
+ private IBuildConfigurator buildConfigurator;
+ private IWorkbench workbench;
+
+ private static final String BUILD_MENU_ID = "org.eclipse.ajdt.BuildMenu"; //$NON-NLS-1$
+
+ /**
+ */
+ public BCWorkbenchWindowInitializer() {
+ this.workbench = AspectJUIPlugin.getDefault().getWorkbench();
+ buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+
+ workbench.addWindowListener(this);
+ IWorkbenchWindow[] wins = workbench.getWorkbenchWindows();
+ for (int i=0; i<wins.length; i++){
+ this.windowOpened(wins[i]);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowActivated(IWorkbenchWindow window) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowDeactivated(IWorkbenchWindow window) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowClosed(IWorkbenchWindow window) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowOpened(IWorkbenchWindow window) {
+ window.getSelectionService().addSelectionListener((BuildConfigurator)buildConfigurator);
+ IMenuManager imm = ((WorkbenchWindow)window).getMenuManager();
+ imm = imm.findMenuUsingPath("project"); //$NON-NLS-1$
+ // only add the menu if it's not already there
+ IContributionItem buildMenu = imm.find(BUILD_MENU_ID);
+ if (buildMenu == null) {
+ imm.insertAfter("buildProject", new DynamicBuildConfigurationMenu(BUILD_MENU_ID)); //$NON-NLS-1$
+ }
+ }
+
+ public void earlyStartup() {
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfiguration.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfiguration.java
new file mode 100644
index 0000000..300a04e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfiguration.java
@@ -0,0 +1,693 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ * Sian January - updated for new build configuration wizard
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.editor.BuildProperties;
+import org.eclipse.ajdt.internal.ui.ajde.ErrorHandler;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.ide.IDE;
+
+/**
+ * This class represents a Build Configuration. It stores all the Classpath data
+ * and offers functionality to include/exclude files, commit changes and to
+ * create new Build Configurations using sophisticated constructors.
+ */
+public class BuildConfiguration implements IBuildConfiguration, Cloneable,
+ org.eclipse.jdt.internal.core.util.Util.Comparable {
+
+ //because we are using jdts classpath file reader/writer, we cannot
+ //define new entry kinds and have to recycle one we are not using
+ public static final int LST_FILE_LINK = IClasspathEntry.CPE_CONTAINER;
+
+ private String name;
+
+ private BuildProperties propertiesFile;
+
+ private HashSet fileList;
+
+ private IProjectBuildConfigurator pbc;
+
+ private boolean listenToFileChanges = true;
+
+ //creates BuildConfiguration from data and writes according file
+ public BuildConfiguration(String name, IJavaProject jp,
+ IProjectBuildConfigurator pbc) {
+ this.pbc = pbc;
+ this.name = name;
+
+ //check if buildconfigurator has a filelist we should use
+ //(when converting to an aj project, this file list gets
+ //populated using jdts exclusion/inclusion patterns)
+ BuildConfigurator bcg = (BuildConfigurator)DefaultBuildConfigurator.getBuildConfigurator();
+ fileList = bcg.getInitialFileList();
+ if (fileList != null) {
+ propertiesFile = new BuildProperties(getFileFromName(name),
+ minimizeIncludes(fileList));
+ } else {
+ try {
+ IClasspathEntry[] cpes2 = jp.getRawClasspath();
+ if (bcg.haveExclusionPatterns(cpes2)) {
+ fileList = bcg.getFileSetFromCPE(cpes2, jp);
+ propertiesFile = new BuildProperties(getFileFromName(name),
+ minimizeIncludes(fileList));
+ } else {
+ fileList = bcg.getInitialFileList();
+ if (fileList != null) {
+ //maybe filelist is written now
+ //(this check could be prevented using synchronization
+ //but we risk creating deadlock opportunities when
+ // doing so)
+ propertiesFile = new BuildProperties(
+ getFileFromName(name),
+ minimizeIncludes(fileList));
+ } else {
+ List pathes = new ArrayList();
+ for (int i = 0; i < cpes2.length; i++) {
+ if (cpes2[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath p = cpes2[i].getPath();
+ IResource res = jp.getProject().getParent()
+ .findMember(p);
+ if ((res != null) && res.exists())
+ pathes.add(res.getProjectRelativePath());
+ }
+ }
+ propertiesFile = new BuildProperties(
+ getFileFromName(name), pathes);
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+ }
+ }
+
+ public IFile getFile() {
+ return getFileFromName(name);
+ }
+
+ //creates BuildConfiguration from file
+ public BuildConfiguration(IFile existingFile, IProjectBuildConfigurator pbc) {
+ this.pbc = pbc;
+ loadDataFromFile(existingFile);
+ }
+
+ private HashSet getFileList() {
+ if (fileList == null) {
+ HashSet newList = new HashSet(20);
+ newList.addAll(propertiesFile.getFiles(false));
+ fileList = newList;
+ return newList;
+ }
+ return fileList;
+ }
+
+ /**
+ * Creates BuildConfiguration from lst file
+ *
+ * @param lstFile2
+ * @param shell
+ * @param pbc
+ *
+ */
+ public BuildConfiguration(IFile lstFile2, Shell shell,
+ IProjectBuildConfigurator pbc) {
+ this.pbc = pbc;
+ name = lstFile2.getName();
+ name = name.substring(0, name.length() - 4);
+
+
+ String title = UIMessages.BCDialog_SaveLstAsAJProp_title;
+ String msg = UIMessages.BCDialog_SaveLstAsAJProp_message.replaceAll("%src", name); //$NON-NLS-1$
+ InputDialogWithCheck md = new InputDialogWithCheck(shell, title, msg, name + "." //$NON-NLS-1$
+ + BuildConfiguration.EXTENSION, null);
+ md.setBlockOnOpen(true);
+ if ((md.open() == Window.OK) && (md.getValue() != null)) {
+ String fileName = md.getValue();
+ if (!fileName.endsWith("." + BuildConfiguration.EXTENSION)) { //$NON-NLS-1$
+ fileName = fileName + "." + BuildConfiguration.EXTENSION; //$NON-NLS-1$
+ }
+ IFile file = pbc.getJavaProject().getProject().getFile(fileName);
+ name = BuildConfiguration.getNameFromFile(file);
+
+ if (file.exists()) {
+ if (!askUserOverwrite(fileName)) {
+ return;
+ }
+ }
+
+ fileList = new HashSet();
+ addLStFileContentsToFileList(lstFile2);
+ IFile newFile = getFileFromName(name);
+ this.propertiesFile = new BuildProperties(newFile, minimizeIncludes(fileList));
+ pbc.addBuildConfiguration(this);
+ if (md.isActivateChecked()){
+ pbc.setActiveBuildConfiguration(this);
+ }
+ if (md.isOpenInEditorChecked()) {
+ IWorkbenchWindow dwindow = AspectJUIPlugin.getDefault().getActiveWorkbenchWindow();
+ IWorkbenchPage page = dwindow.getActivePage();
+ if (page != null)
+ try {
+ IDE.openEditor(page, newFile, true);
+ }
+ catch (PartInitException pie) {}
+ }
+ }
+ }
+
+ private List minimizeIncludes(HashSet fileList) {
+ //if all files of a folder are included, include folder instead of
+ // files seperately
+ HashSet temp1 = (HashSet) fileList.clone();
+ HashSet temp2 = new HashSet();
+ HashSet temp3;
+ boolean hasChanged = true;
+ Iterator iter = temp1.iterator();
+
+ while (hasChanged) {
+
+ hasChanged = false;
+ iter = temp1.iterator();
+ while (iter.hasNext()) {
+ IResource f = (IResource) iter.next();
+ IContainer cont = f.getParent();
+ if (cont.getType() != IResource.PROJECT) {
+ try {
+ IResource[] mems = cont.members();
+ boolean containsAll = true;
+ for (int i = 0; i < mems.length; i++) {
+ if (!temp1.contains(mems[i])
+ && CoreUtils.ASPECTJ_SOURCE_FILTER
+ .accept(mems[i].getName())) {
+ containsAll = false;
+ break;
+ } else if (!temp1.contains(mems[i])
+ && (mems[i].getType() == IResource.FOLDER)) {
+ containsAll = false;
+ break;
+ }
+ }
+ if (!containsAll) {
+ for (int i = 0; i < mems.length; i++) {
+ if (temp1.remove(mems[i]))
+ temp2.add(mems[i]);
+ }
+ } else {
+ for (int i = 0; i < mems.length; i++) {
+ temp1.remove(mems[i]);
+ }
+ hasChanged = true;
+ temp2.add(cont);
+ }
+ } catch (CoreException e1) {
+ }
+ } else {
+ temp1.remove(f);
+ temp2.add(f);
+ }
+ iter = temp1.iterator();
+ }
+
+ temp3 = temp2;
+ temp2 = temp1;
+ temp1 = temp3;
+ }
+
+ return new ArrayList(temp1);
+ }
+
+ private void addLStFileContentsToFileList(IFile lstFile) {
+ ArrayList files = new ArrayList();
+ ArrayList options = new ArrayList();
+ ArrayList links = new ArrayList();
+
+ try {
+ org.eclipse.ajdt.internal.buildconfig.Util.getLstFileContents(lstFile
+ .getLocation(), files, options, links);
+ } catch (FileNotFoundException e) {
+ return;
+ }
+
+ IProject pro = pbc.getJavaProject().getProject();
+ IPath lstFileFolder = lstFile.getFullPath().removeLastSegments(1);
+ int segs = lstFileFolder.matchingFirstSegments(pro.getFullPath());
+ IPath relPath = lstFileFolder.removeFirstSegments(segs);
+
+ Iterator iter;
+ iter = files.iterator();
+ while (iter.hasNext()) {
+ String filename = (String) iter.next();
+ IFile f = pro.getFile(relPath.append(filename));
+ if (f.exists()) {
+ getFileList().add(f);
+ }
+ }
+
+ //read linked lst files
+ iter = links.iterator();
+ while (iter.hasNext()) {
+ String filename = ((String) iter.next()).substring(1);
+ IFile f = pro.getFile(relPath.append(filename));
+ if (f.exists()) {
+ addLStFileContentsToFileList(f);
+ }
+ }
+ }
+
+ //creates new BuildConfiguration and askes user for name
+ public BuildConfiguration(final IProjectBuildConfigurator pbc, Shell parentShell)
+ throws BuildConfigurationCreationException {
+ this.pbc = pbc;
+
+ String title = UIMessages.BCDialog_SaveBuildConfigurationAs_title;
+ String msg = UIMessages.BCDialog_SaveBuildConfigurationAs_message;
+ String fileName = BuildConfigurator.getFreeFileName(pbc.getJavaProject().getProject());
+
+ IBuildConfiguration origBC = pbc.getActiveBuildConfiguration();
+
+ IInputValidator validator = new IInputValidator() {
+ public String isValid(String input) {
+ IFile[] files = pbc.getConfigurationFiles();
+ for (int i = 0; i < files.length; i++) {
+ IFile file = files[i];
+ if (file.getName().equals(input)
+ || file.getName() //$NON-NLS-1$
+ .equals(input + "." + BuildConfiguration.EXTENSION)) { //$NON-NLS-1$
+ return UIMessages.BCDialog_NameValidator_ExistsError;
+ }
+ }
+ return null;
+ }
+ };
+
+ InputDialogWithCheck md = new InputDialogWithCheck(parentShell, title, msg, fileName,
+ validator);
+ md.setBlockOnOpen(true);
+ if (md.open() == Window.OK) {
+ if (md.getValue() != null) {
+
+ String newName = md.getValue();
+ this.name = newName;
+
+ IFile origFile = origBC.getFile();
+ IFile newFile = this.getFile();
+ if (newFile.exists()) {
+ if (!askUserOverwrite(newFile.getName())) {
+ throw new BuildConfigurationCreationException();
+ }
+ try {
+ newFile.delete(true, null);
+ } catch (CoreException e1) {
+ }
+
+ }
+ try {
+ origFile.copy(newFile.getFullPath(), true, null);
+ this.propertiesFile = new BuildProperties(newFile);
+ } catch (CoreException e) {
+ //could not copy file, try another way to create it
+ this.propertiesFile = new BuildProperties(
+ getFileFromName(name), new ArrayList(getFileList()));
+ }
+ fileList = new HashSet(propertiesFile.getFiles(false));
+ pbc.addBuildConfiguration(this);
+ if (md.isActivateChecked()) {
+ pbc.setActiveBuildConfiguration(this);
+ }
+ if (md.isOpenInEditorChecked()) {
+ IWorkbenchWindow dwindow = AspectJUIPlugin.getDefault().getActiveWorkbenchWindow();
+ IWorkbenchPage page = dwindow.getActivePage();
+ if (page != null)
+ try {
+ IDE.openEditor(page,newFile,true);
+ }
+ catch (PartInitException pie) {}
+ }
+ } else {
+ throw new BuildConfigurationCreationException();
+ }
+ }
+ }
+
+ /**
+ * Creates a build configuration with the given name
+ * @param name
+ * @param pbc
+ */
+ public BuildConfiguration (IFile fileToUse, IProjectBuildConfigurator pbc, boolean makeActive) {
+ this.pbc = pbc;
+ name = getNameFromFile(fileToUse);
+ IProject project = fileToUse.getProject();
+ BuildConfigurator bcg = (BuildConfigurator)DefaultBuildConfigurator.getBuildConfigurator();
+ fileList = bcg.getInitialFileList();
+ if(fileList != null) {
+ propertiesFile = new BuildProperties(
+ fileToUse, new ArrayList(getFileList()));
+ } else {
+ try {
+ IJavaProject jp = JavaCore.create(project);
+ IClasspathEntry[] cpes2 = jp.getRawClasspath();
+ if (bcg.haveExclusionPatterns(cpes2)) {
+ fileList = bcg.getFileSetFromCPE(cpes2, jp);
+ propertiesFile = new BuildProperties(fileToUse,
+ minimizeIncludes(fileList));
+ } else {
+ List pathes = new ArrayList();
+ for (int i = 0; i < cpes2.length; i++) {
+ if (cpes2[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath p = cpes2[i].getPath();
+ IResource res = jp.getProject().getParent()
+ .findMember(p);
+ if ((res != null) && res.exists())
+ pathes.add(res.getProjectRelativePath());
+ }
+ }
+ propertiesFile = new BuildProperties(
+ fileToUse, pathes);
+ }
+ } catch (JavaModelException jme) {}
+ }
+
+ pbc.addBuildConfiguration(this);
+ if (makeActive)
+ pbc.setActiveBuildConfiguration(this);
+
+ }
+
+ IFile getFileFromName(String name) {
+ return pbc.getJavaProject().getProject().getFile(
+ name + "." + BuildConfiguration.EXTENSION); //$NON-NLS-1$
+ }
+
+ static String getNameFromFile(IFile file) {
+ String n = file.getName();
+ return n.substring(0, n.indexOf("." + EXTENSION)); //$NON-NLS-1$
+ }
+
+ public void loadDataFromFile(IFile existingFile) {
+ if (existingFile.exists()) {
+ name = getNameFromFile(existingFile);
+ propertiesFile = new BuildProperties(existingFile);
+ }
+ }
+
+ private String getLstContentFromData() {
+ String files = ""; //$NON-NLS-1$
+ Iterator iter = getFileList().iterator();
+ while (iter.hasNext()) {
+ files = files.concat(((IFile) iter.next()).getProjectRelativePath()
+ .toOSString().concat(System.getProperty("line.separator", "\n"))); //$NON-NLS-1$ //$NON-NLS-2$
+ ;
+ }
+ return files;
+ }
+
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ //adds an exclusion filter for a given file to a given classpathentry[]
+ private boolean excludeFile(IResource file) throws CoreException {
+ listenToFileChanges = false;
+ propertiesFile.exclude(file);
+ listenToFileChanges = true;
+ if (file.getType() == IResource.FILE) {
+ getFileList().remove(file);
+ return true;
+ }
+ return false;
+ }
+
+ public void excludeFiles(List exFiles) throws CoreException {
+ Iterator iter = exFiles.iterator();
+ boolean needsupdate = false;
+ IResource res = null;
+ while (iter.hasNext()) {
+ res = (IResource) iter.next();
+ if (!excludeFile(res))
+ needsupdate = true;
+ }
+ if (needsupdate) {
+ update(false);
+ }
+
+ propertiesFile.writeFile();
+ }
+
+ //adds an exclusion filter for a given file to a given classpathentry[]
+ private boolean includeFile(IResource file) {
+ listenToFileChanges = false;
+ propertiesFile.include(file);
+ listenToFileChanges = true;
+ if (file.getType() == IResource.FILE) {
+ getFileList().add(file);
+ return true;
+ }
+ return false;
+ }
+
+ public void includeFiles(List exFiles) {
+ Iterator iter = exFiles.iterator();
+ boolean needsupdate = false;
+ IResource res = null;
+ while (iter.hasNext()) {
+ res = (IResource) iter.next();
+ if (!includeFile(res))
+ needsupdate = true;
+ }
+ if (needsupdate) {
+ update(false);
+ }
+
+ propertiesFile.writeFile();
+ }
+
+ public boolean isIncluded(IResource file) {
+ //System.out.println("include check");
+ boolean isIncl = getFileList().contains(file);
+ return isIncl;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(org.eclipse.jdt.internal.core.util.Util.Comparable o) {
+ if (o instanceof BuildConfiguration) {
+ return getName().compareToIgnoreCase(
+ ((BuildConfiguration) o).getName());
+ }
+ return 0;
+ }
+
+ /**
+ *
+ */
+ public void update(boolean forceReadingFile) {
+ // mark file list as dirty as it is (probably) about to change
+ AspectJUIPlugin.getDefault().getAjdtProjectProperties()
+ .setProjectSourceFileListKnown(
+ pbc.getJavaProject().getProject(), false);
+
+ if (listenToFileChanges == true) {
+ if (fileList == null) {
+ fileList = new HashSet();
+ } else {
+ fileList.clear();
+ }
+ List l = propertiesFile.getFiles(forceReadingFile);
+ fileList.addAll(l);
+ }
+ }
+
+ // returns a list of java.io.Files containing the selected files
+ public List getIncludedJavaFiles(CoreUtils.FilenameFilter filter) {
+ Iterator iter = getFileList().iterator();
+ ArrayList list = new ArrayList(getFileList().size());
+ while (iter.hasNext()) {
+ IResource res = (IResource) iter.next();
+ if (res.exists() && filter.accept(res.getName()))
+ list.add(new File(res.getLocation().toOSString()));
+ }
+ return list;
+ }
+
+ //returns a list of strings containing the file names
+ public List getIncludedJavaFileNames(CoreUtils.FilenameFilter filter) {
+ Iterator iter = getFileList().iterator();
+ ArrayList list = new ArrayList(getFileList().size());
+ while (iter.hasNext()) {
+ IResource res = (IResource) iter.next();
+ if (res.exists() && filter.accept(res.getName()))
+ list.add(res.getLocation().toOSString());
+ }
+ return list;
+ }
+
+ /**
+ *
+ */
+ public void writeLstFile() {
+ update(false);
+ String lstFileContent = this.getLstContentFromData();
+
+ String title = UIMessages.BCDialog_SaveAJPropAsLst_title;
+ String msg = UIMessages.BCDialog_SaveAJPropAsLst_message.replaceAll("%name", name); //$NON-NLS-1$
+
+ InputDialog md = new InputDialog(null, title, msg, name + ".lst", null); //$NON-NLS-1$
+ md.setBlockOnOpen(true);
+ if ((md.open() == Window.OK) && (md.getValue() != null)) {
+ String fileName = md.getValue();
+ if (!fileName.endsWith(".lst")) { //$NON-NLS-1$
+ fileName = fileName + ".lst"; //$NON-NLS-1$
+ }
+ try {
+ IFile file = pbc.getJavaProject().getProject()
+ .getFile(fileName);
+ if (file.exists()) {
+ if (askUserOverwrite(fileName)) {
+ InputStream inputStream = new ByteArrayInputStream(
+ lstFileContent.getBytes());
+ if (file.isReadOnly()) {
+ ResourcesPlugin.getWorkspace().validateEdit(
+ new IFile[] { file }, null);
+ }
+ file.setContents(inputStream, IResource.FORCE, null);
+ }
+ } else {
+ InputStream inputStream = new ByteArrayInputStream(
+ lstFileContent.getBytes());
+ file.create(inputStream, IResource.FORCE, null);
+ }
+ } catch (CoreException e) {
+ ErrorHandler.handleAJDTError(
+ NLS.bind(UIMessages.buildConfig_exceptionWriting,fileName), e); //$NON-NLS-1$
+ }
+
+ }
+
+ }
+
+ private boolean askUserOverwrite(String fileName) {
+ String[] options = {
+ UIMessages.BCDialog_Overwrite_yes,
+ UIMessages.BCDialog_Overwrite_no };
+ String title = UIMessages.BCDialog_Overwrite_title;
+ String msg = UIMessages.BCDialog_Overwrite_message.replaceAll("%fileName", fileName); //$NON-NLS-1$
+
+ MessageDialog mdiag = new MessageDialog(null, title, null, msg,
+ MessageDialog.QUESTION, options, 1);
+ return (mdiag.open() == 0);
+ }
+
+ /**
+ * @return
+ */
+ public boolean areFilesActive() {
+ return (getFileList().size() != 0);
+ }
+
+ /**
+ *
+ */
+ public void updateSourceFolders(List sourcePathes) {
+ propertiesFile.updateSourceFolders(sourcePathes);
+ fileList = null;
+ }
+
+ private class InputDialogWithCheck extends InputDialog {
+ private Button activateCheckbox;
+ private Button openInEditorCheckbox;
+ private boolean activateSelected;
+ private boolean openInEditorSelected;
+
+ /**
+ * @param parentShell
+ * @param dialogTitle
+ * @param dialogMessage
+ * @param initialValue
+ * @param validator
+ */
+ public InputDialogWithCheck(Shell parentShell, String dialogTitle, String dialogMessage, String initialValue, IInputValidator validator) {
+ super(parentShell, dialogTitle, dialogMessage, initialValue, validator);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ openInEditorCheckbox = new Button(composite, SWT.CHECK);
+ openInEditorCheckbox.setSelection(true);
+ openInEditorCheckbox.setText(UIMessages.BuildConfig_openForEdit);
+ activateCheckbox = new Button(composite, SWT.CHECK);
+ activateCheckbox.setSelection(true);
+ activateCheckbox.setText(UIMessages.BuildConfig_activate);
+ return composite;
+ }
+
+ protected void okPressed() {
+ activateSelected = activateCheckbox.getSelection();
+ openInEditorSelected = openInEditorCheckbox.getSelection();
+ super.okPressed();
+ }
+ /**
+ * Is the checkbox selected?
+ * @return
+ */
+ public boolean isActivateChecked() {
+ return activateSelected;
+ }
+
+ public boolean isOpenInEditorChecked() {
+ return openInEditorSelected;
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurationCreationException.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurationCreationException.java
new file mode 100644
index 0000000..f340db3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurationCreationException.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+/**
+ * @author Luzius Meisser
+ *
+ */
+public class BuildConfigurationCreationException extends Exception {
+
+ private static final long serialVersionUID = 6334629352889509802L;
+
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurator.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurator.java
new file mode 100644
index 0000000..d3f4368
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurator.java
@@ -0,0 +1,402 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.ui.ajde.ErrorHandler;
+import org.eclipse.ajdt.internal.ui.preferences.AspectJPreferences;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.contribution.xref.ui.views.XReferenceView;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.ui.packageview.ClassPathContainer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.progress.UIJob;
+
+/**
+ * @author Luzius Meisser
+ *
+ * This class manages the ProjectBuildConfiguratiors.
+ * It offers functionality to
+ * - get the ProjectBuildConfigurator for a specific Project
+ * - register IBuildConfigurationChangedListeners
+ * - notify these change listeners
+ *
+ * It creates exaclty one ProjectBuildConfigurator per Project
+ * that fulfills the criteria specified in
+ * public boolen canManage(IProject p);
+ *
+ */
+public class BuildConfigurator implements IBuildConfigurator, ISelectionListener {
+ private HashMap projectConfigurators;
+ private Vector changeListeners;
+ private IProject currentProj;
+ private int notificationType;
+ private static DefaultBuildConfigurator buildConfigurator;
+
+ private HashSet fileList;
+ private boolean triedToOpenXRefView;
+ private boolean isOpen;
+
+ public BuildConfigurator() {
+ projectConfigurators = new HashMap();
+ changeListeners = new Vector();
+ notificationType = -1;
+ }
+
+ //guarantuees to return a non-null value
+// public static synchronized DefaultBuildConfigurator getBuildConfigurator(){
+// if (buildConfigurator == null)
+// buildConfigurator = new DefaultBuildConfigurator();
+// return buildConfigurator;
+// }
+
+ public synchronized void selectionChanged(IWorkbenchPart action, ISelection selection) {
+ IResource res;
+ IProject selectedProj;
+ IPreferenceStore store = AspectJUIPlugin.getDefault().getPreferenceStore();
+ if (!triedToOpenXRefView) { // only try this once
+ String workspaceLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
+ if (!store.getBoolean(AspectJPreferences.DONE_AUTO_OPEN_XREF_VIEW + workspaceLocation)
+ && !store.getBoolean(workspaceLocation)) {
+ // open xref view in perspective if we haven't opened the xref view before.
+ Job job = new UIJob(UIMessages.BuildConfigurator_workbench_openXRefView) {
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ try {
+ AspectJUIPlugin.getDefault().getActiveWorkbenchWindow()
+ .getActivePage().showView(XReferenceView.ID);
+ return Status.OK_STATUS;
+ } catch (PartInitException e) {
+ ErrorHandler.handleAJDTError(UIMessages.BuildConfigurator_ErrorOpeningXRefView, e);
+ return Status.OK_STATUS;
+ }
+ }
+ };
+ job.schedule();
+ store.setValue(AspectJPreferences.DONE_AUTO_OPEN_XREF_VIEW + workspaceLocation, true);
+ }
+ triedToOpenXRefView = true;
+
+ }
+ if (action instanceof IEditorPart) {
+ res = (IResource) ((IEditorPart) action).getEditorInput()
+ .getAdapter(IResource.class);
+ if (res != null) {
+ selectedProj = res.getProject();
+ } else {
+ selectedProj = null;
+ }
+ } else {
+ selectedProj = getProjectFromSelection(selection);
+ }
+ if ((selectedProj != currentProj) && (selectedProj != null)) {
+ fileList = null;
+ currentProj = selectedProj;
+// if (canManage(currentProj)){
+//
+// PropertyPageManager.unregisterJDTPropertyPage();
+// } else {
+// if (currentProj.isOpen())
+// PropertyPageManager.registerJDTPropertyPage();
+// }
+ notifyChangeListeners();
+ } else if (selectedProj != null) {
+ // Fix for 79376 - re-activate the build button if a closed project is re-openened
+ boolean justOpened = currentProj.isOpen() && !isOpen;
+ if(justOpened) {
+ notifyChangeListeners();
+ }
+ }
+ // adding null check since saw NPE when fixing bug 90094
+ if (currentProj != null) {
+ isOpen = currentProj.isOpen();
+ }
+ }
+
+ public void notifyChangeListeners() {
+ // this notificationType check is done to break infinite notifyChangeListeners loops
+ // TODO: implement a more elegant notification model
+ if (notificationType == -1) {
+ try {
+ notificationType = 0;
+ ProjectBuildConfigurator pbc = getActiveProjectBuildConfigurator();
+ Iterator iter = changeListeners.iterator();
+ while (iter.hasNext()) {
+ ((IBuildConfigurationChangedListener) iter.next())
+ .buildConfigurationChanged(pbc);
+ }
+ } finally {
+// whatever happens here, we must reset notificationType to -1
+ notificationType = -1;
+ }
+ }
+ }
+
+ private IProject getProjectFromSelection(ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ //get the Project & set text
+ Object first = ((IStructuredSelection) selection).getFirstElement();
+ if (first instanceof IJavaElement)
+ return ((IJavaElement) first).getJavaProject().getProject();
+ if (first instanceof IResource){
+ IResource myRes = (IResource) first;
+ return myRes.getProject();
+ }
+ if (first instanceof ClassPathContainer)
+ return ((ClassPathContainer) first).getJavaProject().getProject();
+ }
+ return null;
+ }
+
+ /**
+ * @return Returns the activeBuildConfigurator or null if none are active
+ */
+ public ProjectBuildConfigurator getActiveProjectBuildConfigurator() {
+ return getProjectBuildConfigurator(currentProj);
+ }
+
+ public Set getProjectBuildConfigurators() {
+ return projectConfigurators.entrySet();
+ }
+
+/**
+ * @return The ProjectBuildConfigurator for the given Project if it is an open aj project or null otherwise
+ */
+ public ProjectBuildConfigurator getProjectBuildConfigurator(IJavaProject proj) {
+ if ((proj != null) && (this.canManage(proj.getProject()))) {
+ ProjectBuildConfigurator pbc = (ProjectBuildConfigurator) projectConfigurators
+ .get(proj.getProject().getName());
+ if (pbc != null)
+ return pbc;
+ return createPBC(proj);
+ }
+ return null;
+ }
+
+ private synchronized ProjectBuildConfigurator createPBC(IJavaProject proj){
+ //check if already there
+ ProjectBuildConfigurator pbc = (ProjectBuildConfigurator) projectConfigurators
+ .get(proj.getProject().getName());
+ if (pbc != null)
+ return pbc;
+ //if not, create:
+ pbc = new ProjectBuildConfigurator(proj);
+ projectConfigurators.put(proj.getProject().getName(), pbc);
+ return pbc;
+ }
+
+ /**
+ * @return The ProjectBuildConfigurator for the given Project if it is an open aj project or null otherwise
+ */
+ public ProjectBuildConfigurator getProjectBuildConfigurator(IProject proj) {
+ return getProjectBuildConfigurator(JavaCore.create(proj));
+ }
+
+ public boolean canManage(IProject proj) {
+ if ((proj == null) || (!proj.isOpen())) {
+ return false;
+ }
+ if (AspectJPlugin.isAJProject(proj)) {
+ return true;
+ }
+ return false;
+ }
+
+ public void addProjectBuildConfigurator(ProjectBuildConfigurator pbc) {
+ projectConfigurators.put(pbc.getJavaProject().getProject().getName(),
+ pbc);
+ }
+ /**
+ * @param bccl
+ */
+ public void addBuildConfigurationChangedListener(
+ IBuildConfigurationChangedListener bccl) {
+ changeListeners.add(bccl);
+ }
+
+ /**
+ * @param bccl
+ */
+ public void removeBuildConfigurationChangedListener(IBuildConfigurationChangedListener bccl) {
+ changeListeners.remove(bccl);
+
+ }
+
+ /**
+ * @param jp
+ */
+ public void closeProject(IProject proj) {
+ fileList = null;
+ ProjectBuildConfigurator pbc = (ProjectBuildConfigurator)projectConfigurators.get(proj.getName());
+ if (pbc != null) {
+ if (proj == currentProj)
+ currentProj = null;
+ projectConfigurators.remove(proj.getName());
+ notifyChangeListeners();
+ }
+ }
+ /**
+ * @param project
+ */
+ public void checkNature(IProject project) {
+ if (projectConfigurators.containsKey(project.getName())){
+ //if aj nature was removed, remove pbc
+ if (!this.canManage(project)){
+ ProjectBuildConfigurator pbc = (ProjectBuildConfigurator)projectConfigurators.get(project.getName());
+ if (pbc != null){
+ closeProject(project);
+ }
+ }
+ } else {
+ //aj nature has been added
+ if (this.canManage(project)){
+ currentProj = project;
+ this.notifyChangeListeners();
+ }
+ }
+
+ }
+
+ /**
+ * @param project
+ */
+ public void restoreJDTState(IProject project) {
+ //PropertyPageManager.registerJDTPropertyPage();
+ this.checkNature(project);
+ }
+ /**
+ * @param project
+ */
+ public void setup(IProject project) {
+ fileList = null;
+ //PropertyPageManager.unregisterJDTPropertyPage();
+ try {
+ IJavaProject jp = JavaCore.create(project);
+ IClasspathEntry[] cpes = jp.getRawClasspath();
+
+ if (haveExclusionPatterns(cpes)){
+ fileList = getFileSetFromCPE(cpes, jp);
+ for (int i=0; i<cpes.length; i++){
+ if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE){
+ cpes[i] = JavaCore.newSourceEntry(cpes[i].getPath());
+ }
+ }
+ jp.setRawClasspath(cpes, null);
+ }
+ } catch (JavaModelException e) {
+ fileList = null;
+ }
+
+ if ((currentProj == null) || (currentProj == project)){
+ currentProj = project;
+ this.notifyChangeListeners();
+ }
+ }
+
+ HashSet getFileSetFromCPE(IClasspathEntry[] cpes, IJavaProject jp){
+ HashSet fileSet = new HashSet(30);
+ for (int i=0; i<cpes.length; i++){
+ if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE){
+ IResource res = jp.getProject().getParent().findMember(cpes[i].getPath());
+ if (res!=null && (res.getType()==IResource.FOLDER || res.getType()==IResource.PROJECT))
+ addAllIncludedMembers(fileSet, (IContainer)res, jp);
+ }
+ }
+ return fileSet;
+ }
+
+ boolean haveExclusionPatterns(IClasspathEntry[] cpes){
+ for (int i=0; i<cpes.length; i++){
+ if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE){
+ if ((cpes[i].getExclusionPatterns().length > 0)
+ || (cpes[i].getInclusionPatterns().length > 0))
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ HashSet getInitialFileList(){
+ return fileList;
+ }
+
+
+ private void addAllIncludedMembers(HashSet l, IContainer con, IJavaProject jp){
+ try {
+ IResource[] reses = con.members();
+ for(int i=0; i<reses.length; i++){
+ if (reses[i] instanceof IContainer){
+ addAllIncludedMembers(l, (IContainer)reses[i], jp);
+ } else {
+ if (jp.isOnClasspath(reses[i]) && CoreUtils.ASPECTJ_SOURCE_FILTER
+ .accept(reses[i].getName())){
+ l.add(reses[i]);
+ }
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ /**
+ * Get a new filename for the given project. Returns the name without the file extension.
+ * @param project
+ * @return a string that is NOT the name of a current build configuration in the project
+ */
+ public static String getFreeFileName(IProject project) {
+ String defaultFileName = UIMessages.BCDialog_SaveBuildConfigurationAs_default;
+
+ int counter = 0;
+ if(project != null) {
+ boolean foundFreeName = false;
+ while (!foundFreeName) {
+ String name = counter==0 ? defaultFileName : defaultFileName+counter;
+ IPath path = project.getFullPath().append(name + "." + BuildConfiguration.EXTENSION); //$NON-NLS-1$
+ if(!AspectJPlugin.getWorkspace().getRoot().getFile(path).exists()) {
+ foundFreeName = true;
+ } else {
+ counter++;
+ }
+ }
+ }
+ return counter==0 ? defaultFileName : defaultFileName+counter;
+ }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/IBuildConfigurationChangedListener.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/IBuildConfigurationChangedListener.java
new file mode 100644
index 0000000..606a48d
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/IBuildConfigurationChangedListener.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+
+/**
+ * To notify listeners when ACTIVE build configuration changed somehow
+ *
+ * @author Luzius Meisser
+ */
+public interface IBuildConfigurationChangedListener {
+ public void buildConfigurationChanged(IProjectBuildConfigurator pbc);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ImageDecorator.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ImageDecorator.java
new file mode 100644
index 0000000..aff4ae3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ImageDecorator.java
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.util.ArrayList;
+
+import org.aspectj.asm.IProgramElement;
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.core.javaelements.AJCompilationUnit;
+import org.eclipse.ajdt.core.javaelements.IAspectJElement;
+import org.eclipse.ajdt.internal.ui.resources.AspectJImages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
+import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry;
+import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
+import org.eclipse.jdt.internal.ui.viewsupport.TreeHierarchyLayoutProblemsDecorator;
+import org.eclipse.jdt.ui.JavaElementImageDescriptor;
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.ui.internal.WorkbenchPlugin;
+import org.eclipse.ui.internal.decorators.DecoratorManager;
+
+/**
+ * @see ILabelDecorator
+ */
+public class ImageDecorator implements ILabelDecorator {
+
+ private ArrayList listeners;
+ private ImageDescriptorRegistry fRegistry;
+ private boolean preventRecursion = false;
+ private TreeHierarchyLayoutProblemsDecorator problemsDecorator;
+ private DecoratorManager decman;
+ private ImageDescriptor halfFilledPackageID;
+ private ImageDescriptor activeConfigFileImage;
+ private IBuildConfigurator buildConfor;
+
+ private AspectJImages iconRegistry = AspectJImages.instance();
+
+ /**
+ *
+ */
+ public ImageDecorator() {
+ listeners = new ArrayList(2);
+ problemsDecorator = new TreeHierarchyLayoutProblemsDecorator();
+ decman = WorkbenchPlugin.getDefault().getDecoratorManager();
+ halfFilledPackageID = AspectJImages.BC_HALF_FILLED_PACKAGE.getImageDescriptor();
+ activeConfigFileImage = AspectJImages.BC_SELECTED_FILE.getImageDescriptor();
+ buildConfor = DefaultBuildConfigurator.getBuildConfigurator();
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ listeners.add(listener);
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * @see ILabelDecorator#decorateImage
+ */
+ public Image decorateImage(Image image, Object element) {
+ if (preventRecursion)
+ return null;
+
+ if (element instanceof ICompilationUnit){
+ ICompilationUnit comp = (ICompilationUnit)element;
+ try {
+ element = comp.getCorrespondingResource();
+ } catch (JavaModelException e) {
+ element = null;
+ }
+ }
+
+ Image img = null;
+ if (element instanceof IFile){
+ IFile file= (IFile) element;
+ if (file.exists() && CoreUtils.ASPECTJ_SOURCE_ONLY_FILTER.accept(file.getName())) {
+ // Fix for 108961 - use different icons for .aj files
+ IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(file.getProject());
+
+ if (pbc == null)
+ return null;
+
+ if (pbc.getActiveBuildConfiguration().isIncluded(file)){
+ Rectangle rect = image.getBounds();
+ img = getImageLabel(getJavaImageDescriptor(AspectJImages.ASPECTJ_FILE.getImageDescriptor(), rect, 0));
+ } else {
+ Rectangle rect = image.getBounds();
+ img = getImageLabel(getJavaImageDescriptor(AspectJImages.EXCLUDED_ASPECTJ_FILE.getImageDescriptor(), rect, 0));
+ }
+ } else if (file.exists() && CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file.getName())){
+ IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(file.getProject());
+
+ if (pbc == null)
+ return null;
+
+ if (pbc.getActiveBuildConfiguration().isIncluded(file)){
+ Rectangle rect = image.getBounds();
+ img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_CUNIT, rect, 0));
+ } else {
+ Rectangle rect = image.getBounds();
+ img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_CUNIT_RESOURCE, rect, 0));
+ }
+ } else {
+ if (BuildConfiguration.EXTENSION.equals(file.getFileExtension())){
+ IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(file.getProject());
+ if (pbc != null){
+ if (file.equals(pbc.getActiveBuildConfiguration().getFile())){
+ img = getImageLabel(getJavaImageDescriptor(activeConfigFileImage, image.getBounds(), 0));
+ }
+ }
+
+ }
+ }
+ } else if (element instanceof IPackageFragment){
+ IPackageFragment pack = (IPackageFragment)element;
+ IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(pack.getJavaProject());
+
+ if (pbc == null)
+ return null;
+
+ IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+
+ try {
+ if (containsIncludedFiles(bc, pack)){
+ if (containsExcludedFiles(bc, pack)){
+ //half filled package
+ img = getImageLabel(getJavaImageDescriptor(halfFilledPackageID, image.getBounds(), 0));
+
+ } else {
+ //if all included files are aj files, override icon
+ //(full package icon needed)
+ if (!pack.containsJavaResources()){
+ img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_PACKAGE, image.getBounds(), 0));
+ }
+ }
+ } else {
+ if (containsExcludedFiles(bc, pack))
+ img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_EMPTY_PACKAGE, image.getBounds(), 0));
+ }
+ } catch (JavaModelException e) {
+ // problems with package, better don't do anything
+ // can be ignored
+ }
+ }
+
+ if (img != null){
+ preventRecursion = true;
+
+ //the Java ProblemsDecorator is not registered in the official
+ //decorator list of eclipse, so we need it to call ourself.
+ //problem: if jdt includes more decorators, we won't know it.
+ img = problemsDecorator.decorateImage(img, element);
+
+ //apply standard decorators (eg cvs)
+ img = decman.decorateImage(img, element);
+ preventRecursion = false;
+ return img;
+ }
+ return null;
+ }
+
+ class MyCompositeImageDesc extends CompositeImageDescriptor {
+ private Image fBaseImage;
+
+ private Point fSize;
+
+ public MyCompositeImageDesc(Image baseImage) {
+ this.fBaseImage = baseImage;
+
+ fSize = new Point(baseImage.getBounds().width,
+ baseImage.getBounds().height);
+ //System.out.println("size=" + size);
+ }
+
+ protected void drawCompositeImage(int width, int height) {
+ // To draw a composite image, the base image should be
+ // drawn first (first layer) and then the overlay image
+ // (second layer)
+
+ // Draw the base image using the base image's image data
+ drawImage(fBaseImage.getImageData(), 0, 0);
+
+ // Method to create the overlay image data
+ // Get the image data from the Image store or by other means
+ ImageData overlayImageData = AspectJImages.ADVICE_OVERLAY.getImageDescriptor().getImageData();
+ //adviceDescriptor.getImageData();
+
+ // Overlaying the icon in the top left corner i.e. x and y
+ // coordinates are both zero
+ int xValue = 0;
+ int yValue = 0;
+ drawImage(overlayImageData, xValue, yValue);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Object.
+ */
+ public boolean equals(Object object) {
+ if (object == null || !MyCompositeImageDesc.class.equals(object.getClass()))
+ return false;
+
+ MyCompositeImageDesc other= (MyCompositeImageDesc)object;
+ return (fBaseImage.equals(other.fBaseImage) && fSize.equals(other.fSize));
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Object.
+ */
+ public int hashCode() {
+ return fBaseImage.hashCode() | fSize.hashCode();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.resource.CompositeImageDescriptor#getSize()
+ */
+ protected Point getSize() {
+ return fSize;
+ }
+ }
+
+ public static boolean containsIncludedFiles(IBuildConfiguration bc, IPackageFragment pack){
+ try {
+ // Bug 88477 - JDT may have refreshed the model
+ IResource res = pack.getResource();
+ if(res instanceof IFolder) {
+ IResource[] children = ((IFolder)res).members();
+ for (int i = 0; i < children.length; i++) {
+ IResource resource = children[i];
+ if (resource instanceof IFile) {
+ IFile file = (IFile)resource;
+ if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file.getName())) {
+ if(bc.isIncluded(file)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ } catch (JavaModelException e) {
+ //assume empty
+ // can be ignored
+ } catch (CoreException e) {
+ }
+ return false;
+ }
+
+ public static boolean containsExcludedFiles(IBuildConfiguration bc, IPackageFragment pack){
+ try {
+ // Bug 88477 - JDT may have refreshed the model
+ IResource res = pack.getResource();
+ if(res instanceof IFolder) {
+ IResource[] children = ((IFolder)res).members();
+ for (int i = 0; i < children.length; i++) {
+ IResource resource = children[i];
+ if (resource instanceof IFile) {
+ IFile file = (IFile)resource;
+ if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file.getName())) {
+ if(!bc.isIncluded(file)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ } catch (JavaModelException e) {
+ //assume empty
+ // can be ignored
+ } catch (CoreException e) {
+ }
+ return false;
+ }
+
+ private Image getImageLabel(ImageDescriptor descriptor){
+ if (descriptor == null)
+ return null;
+ return getRegistry().get(descriptor);
+ }
+
+ private ImageDescriptorRegistry getRegistry() {
+ if (fRegistry == null) {
+ fRegistry= JavaPlugin.getImageDescriptorRegistry();
+ }
+ return fRegistry;
+ }
+
+ public static ImageDescriptor getJavaImageDescriptor(ImageDescriptor descriptor, Rectangle rect, int adorflags) {
+ int flags = (rect.width == 16)?JavaElementImageProvider.SMALL_ICONS:0;
+ Point size= useSmallSize(flags) ? JavaElementImageProvider.SMALL_SIZE : JavaElementImageProvider.BIG_SIZE;
+ return new JavaElementImageDescriptor(descriptor, adorflags, size);
+ }
+
+ private static boolean useSmallSize(int flags) {
+ return (flags & JavaElementImageProvider.SMALL_ICONS) != 0;
+ }
+
+ /**
+ * @see ILabelDecorator#decorateText
+ */
+ public String decorateText(String text, Object element) {
+ if (element instanceof AJCompilationUnit){
+ return text.replaceFirst(".java", ".aj"); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ if (element instanceof IAspectJElement){
+ try {
+ if(((IAspectJElement)element).getJavaProject().getProject().exists()) {
+ IProgramElement.Kind kind = ((IAspectJElement)element).getAJKind();
+ if (!((kind == IProgramElement.Kind.ASPECT) || (kind == IProgramElement.Kind.ADVICE) || (kind == IProgramElement.Kind.POINTCUT) || (kind == IProgramElement.Kind.INTER_TYPE_METHOD) || (kind == IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR))){
+ return text.substring(0, text.length() - 2);
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+ }
+ }
+ return null;
+ }
+
+ private int computeJavaAdornmentFlags(IJavaElement element) {
+ int flags= 0;
+ if (true && element instanceof IMember) {
+ try {
+ IMember member= (IMember) element;
+
+ if (element.getElementType() == IJavaElement.METHOD && ((IMethod)element).isConstructor())
+ flags |= JavaElementImageDescriptor.CONSTRUCTOR;
+
+ int modifiers= member.getFlags();
+ if (Flags.isAbstract(modifiers) && confirmAbstract(member))
+ flags |= JavaElementImageDescriptor.ABSTRACT;
+ if (Flags.isFinal(modifiers) || isInterfaceField(member))
+ flags |= JavaElementImageDescriptor.FINAL;
+ if (Flags.isSynchronized(modifiers) && confirmSynchronized(member))
+ flags |= JavaElementImageDescriptor.SYNCHRONIZED;
+ if (Flags.isStatic(modifiers) || isInterfaceField(member))
+ flags |= JavaElementImageDescriptor.STATIC;
+
+ if (Flags.isDeprecated(modifiers))
+ flags |= JavaElementImageDescriptor.DEPRECATED;
+
+ if (member.getElementType() == IJavaElement.TYPE) {
+ if (JavaModelUtil.hasMainMethod((IType) member)) {
+ flags |= JavaElementImageDescriptor.RUNNABLE;
+ }
+ }
+ } catch (JavaModelException e) {
+ // do nothing. Can't compute runnable adornment or get flags
+ // can be ignored
+ }
+ }
+ return flags;
+ }
+
+ private static boolean confirmAbstract(IMember element) throws JavaModelException {
+ // never show the abstract symbol on interfaces or members in interfaces
+ if (element.getElementType() == IJavaElement.TYPE) {
+ return ((IType) element).isClass();
+ }
+ return element.getDeclaringType().isClass();
+ }
+
+ private static boolean isInterfaceField(IMember element) throws JavaModelException {
+ // always show the final && static symbol on interface fields
+ if (element.getElementType() == IJavaElement.FIELD) {
+ return element.getDeclaringType().isInterface();
+ }
+ return false;
+ }
+
+ private static boolean confirmSynchronized(IJavaElement member) {
+ // Synchronized types are allowed but meaningless.
+ return member.getElementType() != IJavaElement.TYPE;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ProjectBuildConfigurator.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ProjectBuildConfigurator.java
new file mode 100644
index 0000000..dbda779
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ProjectBuildConfigurator.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.ajdt.internal.ui.preferences.AspectJPreferences;
+import org.eclipse.ajdt.internal.utils.AJDTUtils;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaProject;
+
+/**
+ * @author Luzius Meisser
+ *
+ * This class manages the Build Configurations of a project.
+ *
+ */
+public class ProjectBuildConfigurator implements IProjectBuildConfigurator {
+ private HashMap buildconfigs;
+ private IJavaProject javaProject;
+
+ IFile activeBuildConfiguration;
+ private IBuildConfigurator buildConfigurator;
+ private boolean initialized;
+
+ public ProjectBuildConfigurator(IJavaProject project) {
+ this.javaProject = project;
+ buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+ buildconfigs = new HashMap();
+ }
+
+ public void reInit(){
+ initialized = false;
+ }
+
+ private void init(){
+ if (!initialized){
+ readBuildConfigurationsFromFileSystem();
+ activeBuildConfiguration = getStoredBuildConfiguration();
+ initialized = true;
+ }
+ }
+
+ private IFile getStoredBuildConfiguration(){
+ IProject project = javaProject.getProject();
+ String configFile = AspectJPreferences.getActiveBuildConfigurationName(project);
+ if ((configFile==null) || configFile.length()==0) {
+ return null;
+ }
+ return project.getFile(configFile);
+ }
+
+ private void storeActiveBuildConfigurationName(String configName){
+ IProject project = javaProject.getProject();
+ AspectJPreferences.setActiveBuildConfigurationName(project,configName);
+ }
+
+ private void readBuildConfigurationsFromFileSystem() {
+ try {
+ IResource[] files = javaProject.getProject().members(IResource.FILE);
+ for (int i = 0; i < files.length; i++) {
+ if ((files[i].getType() != IResource.FOLDER)
+ && BuildConfiguration.EXTENSION.equals(files[i]
+ .getFileExtension())
+ && files[i].exists()) {
+ BuildConfiguration bc;
+ bc = new BuildConfiguration((IFile) files[i], this);
+ buildconfigs.put(files[i], bc);
+ }
+ }
+ } catch (CoreException e) {
+ //Could not read project members, no BuildConfigurations read
+ }
+ }
+
+ public IBuildConfiguration getActiveBuildConfiguration() {
+ makeSureThereIsAtLeastOneActiveConfiguration();
+ return (BuildConfiguration) buildconfigs.get(activeBuildConfiguration);
+ }
+ public void setActiveBuildConfiguration(IBuildConfiguration bc) {
+ if (buildconfigs.containsKey(bc.getFile())) {
+ if(!bc.getFile().exists()) {
+ buildconfigs.remove(bc.getFile());
+ makeSureThereIsAtLeastOneActiveConfiguration();
+ } else {
+ IFile oldActive = activeBuildConfiguration;
+ activeBuildConfiguration = bc.getFile();
+ storeActiveBuildConfigurationName(bc.getFile().getName());
+ bc.update(false);
+ if (!activeBuildConfiguration.equals(oldActive)){
+ try {
+ requestFullBuild(true);
+ activeBuildConfiguration.touch(null);
+ } catch (CoreException e) {
+ }
+ }
+ }
+ }
+ }
+ public IBuildConfiguration getBuildConfiguration(IFile bcFile) {
+ return (BuildConfiguration) buildconfigs.get(bcFile);
+ }
+
+ private boolean fullbuildrequested;
+
+ public void requestFullBuild(boolean temp){
+ fullbuildrequested = temp;
+ }
+
+ public boolean fullBuildRequested(){
+ return fullbuildrequested;
+ }
+
+ //if active buildconfiguration has changed, updated jdt project entries
+ //should only be called by resource delta visitor, so if you want to update
+ //the build configuration, its better to touch its file than to call this method
+ public void configurationChanged(IBuildConfiguration bc) {
+ if (initialized){
+ if (!buildconfigs.containsKey(bc.getFile())) {
+ buildconfigs.put(bc.getFile(), bc);
+ }
+ if (bc.getFile().equals(activeBuildConfiguration)) {
+
+ //why do we need to do full builds after build configuration changes?
+ //when doing a normal build, .class files of classes that have been excluded
+ //do not get removed from the bin dir so we don't get errors if excluded classes
+ //are needed by others.
+ requestFullBuild(true);
+
+ //update package explorer view
+ AJDTUtils.refreshPackageExplorer();
+ }
+ ((BuildConfigurator)buildConfigurator).notifyChangeListeners();
+ }
+ }
+
+ /**
+ * @return Returns the project.
+ */
+ public IJavaProject getJavaProject() {
+ return javaProject;
+ }
+ /**
+ * @param project
+ * The project to set.
+ */
+ public void setProject(IJavaProject project) {
+ this.javaProject = project;
+ }
+ public IFile[] getConfigurationFiles() {
+ makeSureThereIsAtLeastOneActiveConfiguration();
+ IFile[] z = new IFile[0];
+ return (IFile[]) buildconfigs.keySet().toArray(z);
+ }
+ /**
+ * @return
+ */
+ public Collection getBuildConfigurations() {
+ makeSureThereIsAtLeastOneActiveConfiguration();
+ return buildconfigs.values();
+ }
+ public void addBuildConfiguration(IBuildConfiguration bc) {
+ buildconfigs.put(bc.getFile(), bc);
+ ((BuildConfigurator)buildConfigurator).notifyChangeListeners();
+ }
+
+ /**
+ *
+ */
+ private void makeSureThereIsAtLeastOneActiveConfiguration() {
+ if (!initialized){
+ init();
+ }
+ if (buildconfigs.size() == 0) {
+ BuildConfiguration nbc = new BuildConfiguration(BuildConfiguration.STANDARD_BUILD_CONFIGURATION_NAME, javaProject, this);
+ buildconfigs.put(nbc.getFile(), nbc);
+ }
+ if ((activeBuildConfiguration == null) || !buildconfigs.containsKey(activeBuildConfiguration)) {
+ // choose the active configuration
+ setActiveBuildConfiguration(getDefaultBuildConfiguration());
+ }
+ }
+
+ /**
+ * If there is no preference setting defining which build config should be
+ * active, we need to pick on from the ones available. Choosing one at
+ * random wouldn't be helpful, so for consistency we define the rule to be:
+ * choose build.ajproperties if there is one with that name, otherwise
+ * choose the first one alphabetically (bug 84310)
+ *
+ * @return the chosen build configuration
+ */
+ private IBuildConfiguration getDefaultBuildConfiguration() {
+ if (buildconfigs.size()==1) {
+ // hobsons choice
+ return (BuildConfiguration)buildconfigs.values().iterator().next();
+ }
+ IFile first = null;
+ for (Iterator iter = buildconfigs.keySet().iterator(); iter.hasNext();) {
+ IFile file = (IFile) iter.next();
+ if (file.getName().equals(BuildConfiguration.STANDARD_BUILD_CONFIGURATION_FILE)) {
+ return (BuildConfiguration)buildconfigs.get(file);
+ }
+ if (first==null || (file.getName().compareTo(first.getName()) < 0)) {
+ first = file;
+ }
+ }
+ return (BuildConfiguration)buildconfigs.get(first);
+ }
+
+ /**
+ * Deletes the specified build configuration.
+ * If it was the only one, it creates a standard build configuration.
+ * If it was the active one, the next one gets activated.
+ * @param bc Build Configuration to delete
+ */
+ public void removeBuildConfiguration(IBuildConfiguration bc){
+ if (bc.getFile().equals(activeBuildConfiguration))
+ activeBuildConfiguration = null;
+ buildconfigs.remove(bc.getFile());
+ makeSureThereIsAtLeastOneActiveConfiguration();
+ ((BuildConfigurator)buildConfigurator).notifyChangeListeners();
+ }
+
+ /**
+ * @param buildFile
+ */
+ public void setActiveBuildConfiguration(IFile buildFile) {
+ IBuildConfiguration bc = getBuildConfiguration(buildFile);
+ if (bc == null){
+ bc = new BuildConfiguration(buildFile, this);
+ this.addBuildConfiguration(bc);
+ }
+ setActiveBuildConfiguration(bc);
+ }
+
+ /**
+ * @param file
+ */
+ public void removeBuildConfiguration(IFile file) {
+ IBuildConfiguration bc = getBuildConfiguration(file);
+ if (bc != null)
+ this.removeBuildConfiguration(bc);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java
new file mode 100644
index 0000000..4fd7db4
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ * George Harley - fix for bugzilla 73317
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ui.internal.dialogs.PropertyPageContributorManager;
+import org.eclipse.ui.internal.dialogs.RegistryPageContributor;
+
+/**
+ * @author Luzius Meisser
+ *
+ * This class can be used to register and unregister jdts project property page.
+ */
+public class PropertyPageManager {
+ private static RegistryPageContributor jdtProjectPropertyPage = null;
+ private static RegistryPageContributor jdtJavaProjectPropertyPage = null;
+ private static boolean jdtPropertyPageActive = true;
+ final static String projectID = "org.eclipse.core.resources.IProject"; //$NON-NLS-1$
+ final static String javaProjectID = "org.eclipse.jdt.core.IJavaProject"; //$NON-NLS-1$
+ final static String buildPathsPageID = "org.eclipse.jdt.ui.propertyPages.BuildPathsPropertyPage"; //$NON-NLS-1$
+
+
+ private PropertyPageManager(){}
+
+ public static void unregisterJDTPropertyPage(){
+ if (jdtProjectPropertyPage == null){
+ extractJDTRegistryPageContributors();
+ }
+ if (isJDTPropertyPageActive()){
+ PropertyPageContributorManager ppcm = PropertyPageContributorManager.getManager();
+
+ // Get number of contributors prior to attempting the unregistering.
+ int beforeCount = getBuildPathContributorsCount(ppcm);
+
+ ppcm.unregisterContributor(jdtProjectPropertyPage, projectID);
+ ppcm.unregisterContributor(jdtJavaProjectPropertyPage, javaProjectID);
+
+ // Get number of contributors after attempting the unregistering.
+ int afterCount = getBuildPathContributorsCount(ppcm);
+
+ // If the unregistering was successful then the before and after
+ // counts will differ by 2. If they don't then we got our "IJavaProject"
+ // and "IProject" contributors mixed up. This can happen because when
+ // we set the jdtProjectPropertyPage and jdtJavaProjectPropertyPage
+ // values we (AFAIK) have no way of telling their real objectClass
+ // property value. Re-try the unregistering using the alternative
+ // contributor references.
+ if (afterCount != (beforeCount - 2)) {
+ ppcm.unregisterContributor(jdtProjectPropertyPage, javaProjectID);
+ ppcm.unregisterContributor(jdtJavaProjectPropertyPage, projectID);
+ afterCount = getBuildPathContributorsCount(ppcm);
+ }
+
+ if (afterCount != (beforeCount - 2)) {
+ AJLog.log("Failed to unregister Java Build Path property pages"); //$NON-NLS-1$
+ }
+ else {
+ AJLog.log("Successfully unregistered Java Build Path property pages"); //$NON-NLS-1$
+ }
+
+ jdtPropertyPageActive = false;
+ }
+ }
+
+ /**
+ * @param ppcm
+ * @return
+ */
+ private static int getBuildPathContributorsCount(
+ PropertyPageContributorManager ppcm) {
+ int count = 0;
+ Iterator iter = ppcm.getContributors().iterator();
+ while (iter.hasNext()) {
+ List v = (List) iter.next();
+ Iterator iter2 = v.iterator();
+ while (iter2.hasNext()) {
+ RegistryPageContributor rpc = (RegistryPageContributor) iter2
+ .next();
+ if (rpc.getPageId().equals(buildPathsPageID)) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
+ public static void registerJDTPropertyPage(){
+ if (jdtProjectPropertyPage == null){
+ extractJDTRegistryPageContributors();
+ }
+ if (!isJDTPropertyPageActive()){
+ PropertyPageContributorManager ppcm = PropertyPageContributorManager.getManager();
+ ppcm.registerContributor(jdtProjectPropertyPage, projectID);
+ ppcm.registerContributor(jdtJavaProjectPropertyPage, javaProjectID);
+ jdtPropertyPageActive = true;
+ }
+ }
+
+ private static void extractJDTRegistryPageContributors(){
+ List list = new ArrayList(3);
+ PropertyPageContributorManager ppcm = PropertyPageContributorManager.getManager();
+ Iterator iter = ppcm.getContributors().iterator();
+ while (iter.hasNext()){
+ List v = (List)iter.next();
+ Iterator iter2 = v.iterator();
+ while(iter2.hasNext()){
+ RegistryPageContributor rpc = (RegistryPageContributor)iter2.next();
+ if (rpc.getPageId().equals(buildPathsPageID)){
+ list.add(rpc);
+ }
+ }
+ }
+
+ // There does not seem to be a way of determining the objectClass
+ // attribute of the contributor. That is, we cannot tell which of
+ // the contributors is for the "org.eclipse.jdt.core.IJavaProject"
+ // objectClass and which is for "org.eclipse.core.resources.IProject".
+ // Being able to distinguish them is essential when it comes to
+ // attempting to unregister the contributions.
+ jdtProjectPropertyPage = (RegistryPageContributor)list.get(0);
+ jdtJavaProjectPropertyPage = (RegistryPageContributor)list.get(1);
+ jdtPropertyPageActive = true;
+ }
+
+ public static boolean isJDTPropertyPageActive(){
+ return jdtPropertyPageActive;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/UpdateJob.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/UpdateJob.java
new file mode 100644
index 0000000..fe64a02
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/UpdateJob.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Common Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+public class UpdateJob extends Job {
+ public static final int BUILD_CONFIG_CHANGED = 1;
+
+ public static final int BUILD_CONFIG_REMOVED = 2;
+
+ public static final int CLASSPATH_CHANGED = 3;
+
+ public static final int SOURCE_ADDED = 4;
+
+ public static final int FILE_MOVED = 5;
+
+ private int type;
+
+ private IResource myRes;
+
+ private IResource myRes2;
+
+ private final IBuildConfigurator myBCor;
+
+ /**
+ *
+ */
+ public UpdateJob(IBuildConfigurator myBCor, int type, IResource myRes) {
+ super(UIMessages.UpdateJob_name);
+ setRule(myRes.getProject());
+ setSystem(true);
+ setPriority(Job.SHORT);
+ this.myBCor = myBCor;
+ this.type = type;
+ this.myRes = myRes;
+ }
+
+ public UpdateJob(IBuildConfigurator myBCor, int type, IResource myRes,
+ IResource myRes2) {
+ super(UIMessages.UpdateJob_name);
+ setRule(myRes.getProject());
+ setSystem(true);
+ setPriority(Job.SHORT);
+ this.myBCor = myBCor;
+ this.type = type;
+ this.myRes = myRes;
+ this.myRes2 = myRes2;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IStatus run(IProgressMonitor monitor) {
+ switch (type) {
+ case BUILD_CONFIG_CHANGED:
+ buildConfigChanged();
+ break;
+ case BUILD_CONFIG_REMOVED:
+ buildConfigRemoved();
+ break;
+ case CLASSPATH_CHANGED:
+ classpathChanged();
+ break;
+ case SOURCE_ADDED:
+ sourceAdded();
+ break;
+ case FILE_MOVED:
+ fileMoved();
+ break;
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ *
+ */
+ private void sourceAdded() {
+ IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+ .getProject());
+ if (pbc != null) {
+ IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+ if (bc != null) {
+ if (!bc.isIncluded(myRes))
+ bc.update(false);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private void classpathChanged() {
+ IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+ .getProject());
+ if (pbc != null) {
+ try {
+ IJavaProject jp = JavaCore.create(myRes.getProject());
+ IClasspathEntry[] cpes = jp.getRawClasspath();
+ ArrayList sourcePathes = new ArrayList();
+ for (int i = 0; i < cpes.length; i++) {
+ if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ //make path project relative by
+ // removing first segment
+ sourcePathes.add(cpes[i].getPath().removeFirstSegments(
+ 1));
+ }
+ }
+ Iterator iter = pbc.getBuildConfigurations().iterator();
+ while (iter.hasNext()) {
+ ((BuildConfiguration) iter.next())
+ .updateSourceFolders(sourcePathes);
+ }
+ } catch (JavaModelException e) {
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private void buildConfigRemoved() {
+ IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+ .getProject());
+ if (pbc != null) {
+ ((ProjectBuildConfigurator)pbc).removeBuildConfiguration((IFile) myRes);
+ }
+ }
+
+ /**
+ *
+ */
+ private void buildConfigChanged() {
+ IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+ .getProject());
+ if (pbc != null) {
+ IBuildConfiguration bc = pbc.getBuildConfiguration((IFile) myRes);
+ if (bc != null) {
+ bc.update(true);
+ ((ProjectBuildConfigurator)pbc).configurationChanged(bc);
+ }
+ }
+ }
+
+ private void fileMoved() {
+ if ((myRes2 == null) || (myRes == null))
+ return;
+ if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(myRes2.getName())
+ && CoreUtils.ASPECTJ_SOURCE_FILTER.accept(myRes
+ .getName())) {
+ IProjectBuildConfigurator pbc = myBCor
+ .getProjectBuildConfigurator(myRes.getProject());
+ if (pbc != null) {
+ IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+ // reread build config file to update the include/exclude status
+ bc.update(true);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/Util.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/Util.java
new file mode 100644
index 0000000..e04f732
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/Util.java
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * @author Luzius Meisser
+ *
+ */
+public class Util {
+
+ private static String OS_INDEPENDENT_LINE_SEPARATOR = System
+ .getProperty("line.separator"); //$NON-NLS-1$
+
+
+ // LstSupport
+ /**
+ * Get the path of the file <code>file</code> relative to
+ * the location <code>fromDir</code>.
+ * @param file
+ * @param fromDir
+ * @return relative path in a <code>java.lang.String</code>
+ */
+ public static String getRelativePathString(IPath file, IPath fromDir) {
+ String result = null;
+
+ if (file != null && fromDir != null) {
+ // Check for identical inputs
+ if (file.equals(fromDir)) {
+ result = "."; //$NON-NLS-1$
+ }// end if identical
+ else {
+ List fromList;
+ List fileList;
+ fromList = getPathList(fromDir.toFile());
+ fileList = getPathList(file.toFile());
+ result = matchPathLists(fromList, fileList);
+ }// end else different
+ }// end if inputs are usable
+ return result;
+ }
+
+ /**
+ * Get the path of the file <code>file</code> relative to
+ * the location <code>fromDir</code>.
+ * @param file
+ * @param fromDir
+ * @return relative path in a <code>java.lang.String</code>
+ */
+ public static String getRelativePathString(String file, String fromDir) {
+ String result = null;
+
+ if (file != null && fromDir != null) {
+ return getRelativePathString(new Path(file), new Path(fromDir));
+ }// end if inputs are usable
+ return result;
+ }
+
+ /**
+ *
+ */
+ private static List getPathList(File f) {
+ List l = new ArrayList();
+ File r;
+ try {
+ r = f.getCanonicalFile();
+ while (r != null) {
+ l.add(r.getName());
+ r = r.getParentFile();
+ }
+ } catch (IOException e) {
+ l = null;
+ }
+ return l;
+ }
+
+ /**
+ *
+ */
+ private static String matchPathLists(List fromList, List toList) {
+ int i;
+ int j;
+ String result = ""; //$NON-NLS-1$
+
+ i = fromList.size() - 1;
+ j = toList.size() - 1;
+
+ // First, get rid of the common root
+ while ((i >= 0) && (j >= 0) &&
+ (fromList.get(i).equals(toList.get(j)))) {
+ i--;
+ j--;
+ }// end while still finding common components
+
+ // For each remaining level in the home path add
+ // a double dot (..)
+ for (; i >= 0; i--) {
+ result += ".." + AspectJPlugin.NON_OS_SPECIFIC_SEPARATOR; //$NON-NLS-1$
+ }// end for each remaining level
+
+ // for each level in the file path, add the path
+ for (; j >= 1; j--) {
+ result += toList.get(j) +
+ AspectJPlugin.NON_OS_SPECIFIC_SEPARATOR;
+ }
+
+ // Return the file name
+ result += toList.get(j);
+ return result;
+ }
+
+ /**
+ * If input file contains no links to other lst files then just returns
+ * the IPath to the original file. Otherwise, creates a new file in the
+ * same directory as the original file with the extension ".inlined.lst"
+ * and returns an IPath for the new file. The original .lst file is
+ * left remaining on disk with its original name.
+ * @param lstFile
+ * @return
+ * @throws FileNotFoundException
+ */
+ public static IPath getInlinedLstFile(IPath lstFile)
+ throws FileNotFoundException {
+ IPath result = lstFile;
+
+ if (lstFile != null) {
+ // Quick check that we have a bona fide file to work with
+ if (!lstFile.toFile().exists()) {
+ throw new FileNotFoundException(lstFile.toOSString()
+ + " " + UIMessages.buildConfig_notFound); //$NON-NLS-1$
+ }
+
+ // Quick check to see if file has a line starting with the
+ // link symbol "@". If not, just return the input IPath to
+ // the caller.
+ if (lstFileContainsLinks(lstFile)) {
+ File resultFile = new File(getInlinedFileName(lstFile
+ .toOSString()));
+ try {
+ BufferedWriter bw = new BufferedWriter(new FileWriter(
+ resultFile));
+ writeInlinedLstFileToBuffer(lstFile.toFile(), bw);
+ bw.close();
+ result = new Path(resultFile.getAbsolutePath());
+ } catch (IOException e) {
+ }
+ }// end if a link found
+ }// end if input is usable
+
+ return result;
+ }
+
+ public static String getInlinedFileName(String originalName) {
+ String result = originalName;
+ if (originalName != null) {
+ String tmp1 = originalName.substring(0, originalName
+ .lastIndexOf('.'));
+ String tmp2 = originalName.substring(originalName.lastIndexOf('.'));
+ result = tmp1 + ".inlined" + tmp2; //$NON-NLS-1$
+ }// end if input is usable
+ return result;
+ }
+
+ /**
+ * @param file
+ * @param bos
+ * @throws FileNotFoundException
+ */
+ private static void writeInlinedLstFileToBuffer(File file,
+ BufferedWriter bw) throws FileNotFoundException {
+ // Open up the input file
+ BufferedReader in = new BufferedReader(new FileReader(file));
+ String line = null;
+ try {
+ while ((line = in.readLine()) != null) {
+ line = line.trim();
+ if (!line.startsWith("@")) { //$NON-NLS-1$
+ bw.write(line);
+ bw.newLine();
+ }// end if no lst link reference found on line
+ else {
+ // Get the location of the linked file. If it
+ // exists then recursively call it from here
+ // (passing in the original BufferedWriter).
+ String linkedFilePath = line.substring(1);
+ File linkedFile = new File(linkedFilePath);
+ if (linkedFile.isAbsolute()) {
+ if (linkedFile.exists()) {
+ writeInlinedLstFileToBuffer(linkedFile, bw);
+ }
+ }// end if file linking to is absolute
+ else {
+ // Don't panic. Need to obtain an absolute path
+ // to the linked file.
+ linkedFile = new File(file.getParentFile()
+ .getAbsolutePath()
+ + AspectJPlugin.NON_OS_SPECIFIC_SEPARATOR
+ + linkedFilePath);
+ if (linkedFile.exists()) {
+ writeInlinedLstFileToBuffer(linkedFile, bw);
+ }
+ }// end else linking using relative path
+ }// else line contains a link reference
+ }// end while more lines to read
+ }
+ catch (IOException e) {
+ }
+ }
+
+ /**
+ * @param lstFile
+ * @throws FileNotFoundException
+ */
+ private static boolean lstFileContainsLinks(IPath lstFile)
+ throws FileNotFoundException {
+ boolean result = false;
+ String path = lstFile.toOSString();
+ BufferedReader in = new BufferedReader(new FileReader(path));
+ String line = null;
+ try {
+ while ((line = in.readLine()) != null) {
+ line = line.trim();
+ if (line.startsWith("@")) { //$NON-NLS-1$
+ result = true;
+ break;
+ }// end if lst link reference found
+ }
+ } catch (IOException e) {
+ }
+ return result;
+ }
+
+ /**
+ * @param file
+ * @param files
+ * @param options
+ * @param links
+ * @throws FileNotFoundException
+ */
+ public static void getLstFileContents(
+ IPath file,
+ List files,
+ List options,
+ List links) throws FileNotFoundException {
+ // Check that we have been passed in the necessary
+ // INOUT instances.
+ if (file != null &&
+ files != null &&
+ options != null &&
+ links != null) {
+ String path = file.toOSString();
+ BufferedReader in = new BufferedReader(new FileReader(path));
+ String line = null;
+ try {
+ while ((line = in.readLine()) != null) {
+ line = line.trim();
+ if (line.startsWith("@")) { //$NON-NLS-1$
+ links.add(line);
+ }// end if lst link reference found
+ else if (line.startsWith("-")) { //$NON-NLS-1$
+ // Option. Determine whether or not
+ // the option requires an argument.
+ if (AjcOptionsChecker.optionWithArg(line)) {
+ // Grab the next line
+ String nextLine = in.readLine();
+ if (nextLine != null) {
+ options.add(line
+ + OS_INDEPENDENT_LINE_SEPARATOR
+ + nextLine.trim());
+ }// end if
+ else {
+ // Just add the option anyway
+ options.add(line);
+ }// end else arg expected but none found
+ }// end if argument expected
+ else {
+ options.add(line);
+ }// end else no argument expected
+ }// end else if option found
+ else {
+ // Source file reference ?
+ // Check that the file actually exists
+ // before adding to the files list ??
+ if (!line.equals("")) //$NON-NLS-1$
+ files.add(line);
+ }// end else a possible source file reference found
+ }// while more lines to read
+ } catch (IOException e) {
+ }
+ }// end if valid inputs
+ }
+
+ /**
+ * Helper class
+ */
+ static class AjcOptionsChecker {
+ private static Set optionsWithArgs;
+
+ static {
+ initialiseOptionsWithArgs();
+ }// end static initialisation block
+
+ public static boolean optionWithArg(String option) {
+ boolean result = false;
+ if (optionsWithArgs.contains(option)) {
+ result = true;
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ private static void initialiseOptionsWithArgs() {
+ optionsWithArgs = new HashSet();
+ optionsWithArgs.add("-inpath"); //$NON-NLS-1$
+ optionsWithArgs.add("-injars"); //$NON-NLS-1$
+ optionsWithArgs.add("-aspectpath"); //$NON-NLS-1$
+ optionsWithArgs.add("-outjar"); //$NON-NLS-1$
+ optionsWithArgs.add("-argfile"); //$NON-NLS-1$
+ optionsWithArgs.add("-sourceroots"); //$NON-NLS-1$
+ optionsWithArgs.add("-Xlintfile"); //$NON-NLS-1$
+ optionsWithArgs.add("-cp"); //$NON-NLS-1$
+ optionsWithArgs.add("-classpath"); //$NON-NLS-1$
+ optionsWithArgs.add("-bootclasspath"); //$NON-NLS-1$
+ optionsWithArgs.add("-d"); //$NON-NLS-1$
+ optionsWithArgs.add("-encoding"); //$NON-NLS-1$
+ optionsWithArgs.add("-source"); //$NON-NLS-1$
+ optionsWithArgs.add("-target"); //$NON-NLS-1$
+ optionsWithArgs.add("-log"); //$NON-NLS-1$
+ optionsWithArgs.add("-repeat"); //$NON-NLS-1$
+ optionsWithArgs.add("-inpath"); //$NON-NLS-1$
+ }
+ }// end class AjcOptionsChecker
+
+ // End LstSupport
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ActivateAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ActivateAction.java
new file mode 100644
index 0000000..b47c6a8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ActivateAction.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.BuildProperties;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * This action is triggered from a popup menu on a build configuration
+ * file. It makes the target the current build config file for the project.
+ */
+public class ActivateAction implements IWorkbenchWindowActionDelegate {
+
+ private IFile currentlySelectedBuildFile = null;
+ private IBuildConfigurator buildConfigurator;
+
+ public ActivateAction(){
+ buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+ }
+
+ public static BuildProperties buildP;
+
+ /**
+ * Executed when button clicked or popup menu "Select this build file" clicked
+ */
+ public void run(IAction action) {
+
+ if (currentlySelectedBuildFile != null){
+ IProjectBuildConfigurator pbc = buildConfigurator.getProjectBuildConfigurator(currentlySelectedBuildFile.getProject());
+ if (pbc != null){
+ pbc.setActiveBuildConfiguration(currentlySelectedBuildFile);
+ }
+ }
+ }
+
+ /**
+ * Selection has changed - if we've selected a build file then remember it
+ * as the new project build config.
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ Object first = structuredSelection.getFirstElement();
+ if (first instanceof IFile) {
+ currentlySelectedBuildFile = (IFile) first;
+ }
+ }
+ }
+
+ /**
+ * From IWorkbenchWindowActionDelegate
+ */
+ public void dispose() {}
+
+ /**
+ * From IWorkbenchWindowActionDelegate
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/BuildConfigurationChangeAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/BuildConfigurationChangeAction.java
new file mode 100644
index 0000000..1e488dd
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/BuildConfigurationChangeAction.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.internal.buildconfig.IBuildConfigurationChangedListener;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IActionDelegate;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * @author Luzius Meisser
+ *
+ */
+public abstract class BuildConfigurationChangeAction implements
+ IObjectActionDelegate, IBuildConfigurationChangedListener {
+
+ protected IAction myAction;
+
+ protected IStructuredSelection strucSel;
+
+ protected IBuildConfigurator buildConfigurator;
+
+ protected String actionText;
+
+ /**
+ * Constructor for Action1.
+ */
+ public BuildConfigurationChangeAction() {
+ super();
+ buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+ ((BuildConfigurator)buildConfigurator).addBuildConfigurationChangedListener(this);
+ }
+
+ ArrayList changedBCs;
+
+ /**
+ * @see IActionDelegate#run(IAction)
+ */
+
+ public void run(IAction action) {
+ changedBCs = new ArrayList();
+ Object mySel;
+ IProjectBuildConfigurator pbc = buildConfigurator
+ .getActiveProjectBuildConfigurator();
+
+ if (pbc != null) {
+ IProjectBuildConfigurator resourcepbc;
+ Iterator mySelIter = strucSel.iterator();
+ ArrayList itemsToManipulate = new ArrayList();
+ while (mySelIter.hasNext()) {
+ mySel = mySelIter.next();
+
+ if (mySel instanceof IJavaElement) {
+ try {
+ mySel = ((IJavaElement) mySel)
+ .getCorrespondingResource();
+ } catch (JavaModelException e) {
+ mySel = null;
+ }
+ }
+ if (mySel instanceof IResource) {
+ IResource res = (IResource) mySel;
+ resourcepbc = buildConfigurator
+ .getProjectBuildConfigurator(res.getProject());
+ if (pbc == resourcepbc) {
+ itemsToManipulate.add(res);
+ }
+ }
+ }
+ doMySpecificAction(pbc.getActiveBuildConfiguration(),
+ itemsToManipulate);
+ }
+
+ }
+
+ protected abstract Job getJob(final IBuildConfiguration bc, final List fileList);
+
+ private void doMySpecificAction(IBuildConfiguration bc, List fileList) {
+ Job job = getJob(bc, fileList);
+ job.setPriority(Job.SHORT);
+ job.setRule(bc.getFile().getProject());
+ job.schedule();
+ }
+
+ /**
+ * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+
+ }
+
+ public void buildConfigurationChanged(final IProjectBuildConfigurator pbc) {
+ if (pbc != null) {
+ myAction.setEnabled(true);
+ Job job = new Job(UIMessages.buildConfigurationChangeAction_job_name) {
+ protected IStatus run(IProgressMonitor monitor) {
+ IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+ myAction.setText(actionText.replaceAll("%bcname", bc //$NON-NLS-1$
+ .getName()));
+ return Status.OK_STATUS;
+ }
+ };
+ job.setPriority(Job.SHORT);
+ job.setRule(pbc.getJavaProject().getProject());
+ job.schedule();
+ } else {
+ myAction.setEnabled(false);
+ }
+ }
+
+ abstract boolean isObjectApplicable(Object o);
+
+ protected boolean isApplicable(Object sel) {
+ if (sel instanceof IPackageFragment) {
+ try {
+ IPackageFragment pack = ((IPackageFragment) sel);
+ Object[] children = pack.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ if (isApplicable(children[i]))
+ return true;
+ }
+
+ children = pack.getNonJavaResources();
+ for (int i = 0; i < children.length; i++) {
+ if (isApplicable(children[i]))
+ return true;
+ }
+
+ } catch (CoreException e) {
+ //if this function fails, include/exlude files will fail as
+ // well so deactivate these acitons
+ return false;
+ }
+ } else {
+ return isObjectApplicable(sel);
+ }
+ return false;
+ }
+
+ protected boolean isApplicable(IStructuredSelection ssel) {
+ Iterator mySelIter = ssel.iterator();
+ while (mySelIter.hasNext()) {
+ Object sel = mySelIter.next();
+ if (isApplicable(sel))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @see IActionDelegate#selectionChanged(IAction, ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (myAction == null) {
+ myAction = action;
+ IProjectBuildConfigurator pbc = buildConfigurator
+ .getActiveProjectBuildConfigurator();
+ if (pbc != null) {
+ myAction.setText(actionText.replaceAll("%bcname", pbc //$NON-NLS-1$
+ .getActiveBuildConfiguration().getName()));
+ }
+ }
+ if (selection instanceof IStructuredSelection) {
+ strucSel = (IStructuredSelection) selection;
+ action.setEnabled(isApplicable(strucSel));
+ } else {
+ strucSel = null;
+ action.setEnabled(false);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExcludeAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExcludeAction.java
new file mode 100644
index 0000000..ca7e4a1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExcludeAction.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import java.util.List;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.ui.ajde.ErrorHandler;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.ICompilationUnit;
+
+/**
+ * @author Luzius Meisser
+ *
+ */
+public class ExcludeAction extends BuildConfigurationChangeAction {
+ public ExcludeAction() {
+ super();
+ actionText = UIMessages.BCLabels_ExcludeAction;
+ }
+
+ protected Job getJob(final IBuildConfiguration bc,
+ final List fileList) {
+ return new Job(UIMessages.excludeAction_job_name) {
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ ((BuildConfiguration)bc).excludeFiles(fileList);
+ } catch (CoreException e) {
+ ErrorHandler.handleAJDTError(
+ UIMessages.buildConfig_exceptionIncluding,
+ e);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ajdt.buildconfigurator.popup.actions.BuildConfigurationChangeAction#isApplicable(java.lang.Object)
+ */
+ boolean isObjectApplicable(Object o) {
+ try {
+ if (o instanceof ICompilationUnit) {
+ o = ((ICompilationUnit) o).getCorrespondingResource();
+ }
+ if (o instanceof IFile) {
+ IFile file = (IFile) o;
+ if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file
+ .getName())) {
+ IProjectBuildConfigurator pbc = buildConfigurator
+ .getProjectBuildConfigurator(file.getProject());
+ if (pbc != null)
+ return pbc.getActiveBuildConfiguration().isIncluded(
+ file);
+ }
+ }
+ } catch (CoreException e) {
+ // assume non-aj-project
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExportAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExportAction.java
new file mode 100644
index 0000000..d155ac7
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExportAction.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * This action is triggered from a popup menu on a build configuration
+ * file. It makes the target the current build config file for the project.
+ */
+public class ExportAction implements IWorkbenchWindowActionDelegate {
+
+
+ private IFile currentlySelectedBuildFile = null;
+ private IBuildConfigurator buildConfigurator;
+
+ public ExportAction(){
+ buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+ }
+
+
+ /**
+ * Executed when button clicked or popup menu "Select this build file" clicked
+ */
+ public void run(IAction action) {
+
+ if (currentlySelectedBuildFile != null){
+ IProjectBuildConfigurator pbc = buildConfigurator.getProjectBuildConfigurator(currentlySelectedBuildFile.getProject());
+ if (pbc != null){
+ IBuildConfiguration bc = pbc.getBuildConfiguration(currentlySelectedBuildFile);
+ if (bc != null){
+ ((BuildConfiguration)bc).writeLstFile();
+ }
+ }
+ }
+ }
+
+ /**
+ * Selection has changed - if we've selected a build file then remember it
+ * as the new project build config.
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ Object first = structuredSelection.getFirstElement();
+ if (first instanceof IFile) {
+ currentlySelectedBuildFile = (IFile) first;
+ }
+ }
+ }
+
+ /**
+ * From IWorkbenchWindowActionDelegate
+ */
+ public void dispose() {}
+
+ /**
+ * From IWorkbenchWindowActionDelegate
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ImportAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ImportAction.java
new file mode 100644
index 0000000..e3ed358
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ImportAction.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * This action is triggered from a popup menu on a build configuration
+ * file. It makes the target the current build config file for the project.
+ */
+public class ImportAction implements IWorkbenchWindowActionDelegate {
+
+ private IFile currentlySelectedBuildFile = null;
+ private IBuildConfigurator buildConfigurator;
+
+ public ImportAction(){
+ buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+ }
+
+
+ /**
+ * Executed when button clicked or popup menu "Select this build file" clicked
+ */
+ public void run(IAction action) {
+
+ if (currentlySelectedBuildFile != null){
+ IProjectBuildConfigurator pbc = buildConfigurator.getProjectBuildConfigurator(currentlySelectedBuildFile.getProject());
+ if (pbc != null){
+ Shell shell = AspectJUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell();
+ new BuildConfiguration(currentlySelectedBuildFile, shell, pbc);
+ }
+ }
+ }
+
+ /**
+ * Selection has changed - if we've selected a build file then remember it
+ * as the new project build config.
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ Object first = structuredSelection.getFirstElement();
+ if (first instanceof IFile) {
+ currentlySelectedBuildFile = (IFile) first;
+ }
+ }
+ }
+
+ /**
+ * From IWorkbenchWindowActionDelegate
+ */
+ public void dispose() {}
+
+ /**
+ * From IWorkbenchWindowActionDelegate
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/IncludeAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/IncludeAction.java
new file mode 100644
index 0000000..ead3d78
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/IncludeAction.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import java.util.List;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+/**
+ * @author Luzius Meisser
+ *
+ */
+public class IncludeAction extends BuildConfigurationChangeAction {
+
+ public IncludeAction() {
+ super();
+ actionText = UIMessages.BCLabels_IncludeAction;
+ }
+
+ protected Job getJob(final IBuildConfiguration bc,
+ final List fileList) {
+ return new Job(UIMessages.includeAction_job_name) {
+ protected IStatus run(IProgressMonitor monitor) {
+ ((BuildConfiguration)bc).includeFiles(fileList);
+ return Status.OK_STATUS;
+ }
+ };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ajdt.buildconfigurator.popup.actions.BuildConfigurationChangeAction#isApplicable(java.lang.Object)
+ */
+ boolean isObjectApplicable(Object o) {
+ try {
+ if (o instanceof ICompilationUnit) {
+ o = ((ICompilationUnit) o).getCorrespondingResource();
+ }
+ if (o instanceof IFile) {
+ IFile file = (IFile) o;
+ if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file
+ .getName())) {
+ IProjectBuildConfigurator pbc = buildConfigurator
+ .getProjectBuildConfigurator(file.getProject());
+ if ((pbc!=null) && pbc.getActiveBuildConfiguration().isIncluded(
+ file)) {
+ return false;
+ }
+
+ // the file is not currently included but we only give the
+ // option to include it if it is contained in a source folder
+ IJavaProject jp = JavaCore.create(file.getProject());
+ IClasspathEntry[] cpes = jp.getRawClasspath();
+ IPath fp = file.getFullPath();
+ for (int i = 0; i < cpes.length; i++) {
+ if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath p = cpes[i].getPath();
+ if (p.isPrefixOf(fp)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ } catch (CoreException e) {
+ // assume non-aj-project, do nothing
+ // can be ignored
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildContentsSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildContentsSection.java
new file mode 100644
index 0000000..c53de49
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildContentsSection.java
@@ -0,0 +1,724 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Common Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildModel;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.IModelChangedListener;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+import org.eclipse.ajdt.pde.internal.ui.editor.TableSection;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+public abstract class BuildContentsSection extends TableSection
+ implements
+ IModelChangedListener,
+ IResourceChangeListener,
+ IResourceDeltaVisitor {
+
+ protected CheckboxTreeViewer fTreeViewer;
+ private boolean fDoRefresh = false;
+ protected IProject fProject;
+ protected IBuildModel fBuildModel;
+ protected IResource fOriginalResource, fParentResource;
+ protected boolean isChecked;
+
+ public class TreeContentProvider extends DefaultContentProvider
+ implements
+ ITreeContentProvider {
+
+ public Object[] getFilteredChildren(IContainer parent) {
+ if (parent.exists()) {
+ try{
+ IResource[] res = parent.members();
+ ArrayList children = new ArrayList();
+ for (int i=0; i<res.length; i++){
+ if (res[i] instanceof IFolder){
+ IJavaProject jp =JavaCore.create(res[i].getProject());
+ if (jp != null){
+ addElementsOnClasspath(children, jp, res[i]);
+ }
+ } else {
+ if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(res[i].getName()))
+ children.add(res[i]);
+ }
+
+ }
+ return children.toArray();
+ } catch (CoreException e) {
+ }
+ }
+ return new Object[0];
+ }
+
+ private void addElementsOnClasspath(List list, IJavaProject jp, IResource res){
+ if (jp.isOnClasspath(res)){
+ list.add(res);
+ return;
+ }
+ if (res.getType() == IResource.FOLDER){
+ try {
+ IResource[] mems = ((IFolder)res).members();
+ for (int i=0; i<mems.length; i++){
+ if (mems[i].getType() == IResource.FOLDER)
+ addElementsOnClasspath(list, jp, mems[i]);
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+
+ public Object[] getElements(Object parent) {
+ if (parent instanceof IContainer) {
+ return getFilteredChildren((IContainer)parent);
+ }
+ return new Object[0];
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
+ */
+ public Object[] getChildren(Object parent) {
+ if (parent instanceof IContainer)
+ return getFilteredChildren((IContainer)parent);
+ return new Object[0];
+ }
+
+ public Object[] getFolderChildren(Object parent) {
+ IResource[] members = null;
+ try {
+ if (!(parent instanceof IFolder))
+ return new Object[0];
+ members = ((IFolder) parent).members();
+ ArrayList results = new ArrayList();
+ for (int i = 0; i < members.length; i++) {
+ if ((members[i].getType() == IResource.FOLDER)) {
+ results.add(members[i]);
+ }
+ }
+ return results.toArray();
+ } catch (CoreException e) {
+ }
+ return new Object[0];
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
+ */
+ public Object getParent(Object element) {
+ if (element != null && element instanceof IResource) {
+ return ((IResource) element).getParent();
+ }
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
+ */
+ public boolean hasChildren(Object element) {
+ if (element instanceof IContainer)
+ return getChildren(element).length > 0;
+ return false;
+ }
+ }
+ protected void createViewerPartControl(Composite parent, int style, int span, FormToolkit toolkit) {
+ MenuManager popupMenuManager = new MenuManager();
+ IMenuListener listener = new IMenuListener() {
+ public void menuAboutToShow(IMenuManager mng) {
+ fillContextMenu(mng);
+ }
+ };
+ popupMenuManager.addMenuListener(listener);
+ popupMenuManager.setRemoveAllWhenShown(true);
+ Control control = fTreeViewer.getControl();
+ Menu menu = popupMenuManager.createContextMenu(control);
+ control.setMenu(menu);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#fillContextMenu(org.eclipse.jface.action.IMenuManager)
+ */
+ protected void fillContextMenu(IMenuManager manager) {
+ manager.add(getPage().getPDEEditor().getContributor().getRevertAction());
+ getPage().getPDEEditor().getContributor().contextMenuAboutToShow(
+ manager, false);
+ }
+ private IBuildModel getBuildModel() {
+ InputContext context = getPage().getPDEEditor().getContextManager()
+ .findContext(BuildInputContext.CONTEXT_ID);
+ return (IBuildModel) context.getModel();
+ }
+
+ public BuildContentsSection(PDEFormPage page, Composite parent) {
+ super(page, parent, Section.DESCRIPTION, new String[0]);
+ PDEPlugin.getWorkspace().addResourceChangeListener(this);
+ }
+
+ public void createClient(final Section section, FormToolkit toolkit) {
+ Composite container = createClientContainer(section, 2, toolkit);
+ fBuildModel = getBuildModel();
+ if (fBuildModel.getUnderlyingResource() != null)
+ fProject = fBuildModel.getUnderlyingResource().getProject();
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = layout.marginWidth = 2;
+ container.setLayout(layout);
+ fTreeViewer = new CheckboxTreeViewer(toolkit.createTree(container,
+ SWT.CHECK));
+ fTreeViewer.setContentProvider(new TreeContentProvider());
+ fTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
+ fTreeViewer.setAutoExpandLevel(0);
+ fTreeViewer.addCheckStateListener(new ICheckStateListener() {
+
+ public void checkStateChanged(final CheckStateChangedEvent event) {
+ final Object element = event.getElement();
+ BusyIndicator.showWhile(section.getDisplay(), new Runnable() {
+
+ public void run() {
+ if (element instanceof IFile) {
+ IFile file = (IFile) event.getElement();
+ handleCheckStateChanged(file, event.getChecked());
+ } else if (element instanceof IFolder) {
+ IFolder folder = (IFolder) event.getElement();
+ handleCheckStateChanged(folder, event.getChecked());
+ }
+ }
+ });
+ }
+ });
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = 100;
+ gd.widthHint = 100;
+ fTreeViewer.getTree().setLayoutData(gd);
+ initialize();
+ initializeCheckState();
+ toolkit.paintBordersFor(container);
+ createViewerPartControl(container, SWT.FULL_SELECTION, 2, toolkit);
+ section.setClient(container);
+ }
+
+ public void enableSection(boolean enable) {
+ fTreeViewer.getTree().setEnabled(enable);
+ }
+
+ protected void handleCheckStateChanged(IResource resource, boolean checked) {
+ fOriginalResource = resource;
+ isChecked = checked;
+ boolean wasTopParentChecked = isIncluded(fOriginalResource
+ .getParent());
+ if (!isChecked) {
+ resource = handleAllUnselected(resource, resource.getName());
+ }
+ fParentResource = resource;
+ handleBuildCheckStateChange(wasTopParentChecked);
+ }
+
+ protected IResource handleAllUnselected(IResource resource, String name) {
+ IResource parent = resource.getParent();
+ if (parent == resource.getProject()) {
+ return resource;
+ }
+ try {
+ boolean uncheck = true;
+ IResource[] members = ((IFolder) parent).members();
+ for (int i = 0; i < members.length; i++) {
+ if (isIncluded(members[i])
+ && !members[i].getName().equals(name))
+ uncheck = false;
+ }
+ if (uncheck) {
+ return handleAllUnselected(parent, parent.getName());
+ }
+ return resource;
+ } catch (CoreException e) {
+ return null;
+ }
+ }
+
+ protected void setChildrenGrayed(IResource folder, boolean isGray) {
+ fTreeViewer.setGrayed(folder, isGray);
+ if (((TreeContentProvider) fTreeViewer.getContentProvider())
+ .hasChildren(folder)) {
+ Object[] members = ((TreeContentProvider) fTreeViewer
+ .getContentProvider()).getFolderChildren(folder);
+ for (int i = 0; i < members.length; i++) {
+ setChildrenGrayed((IFolder) members[i], isGray);
+ }
+ }
+ }
+
+ protected void setParentsChecked(IResource resource) {
+ if (resource.getParent() != resource.getProject()) {
+ fTreeViewer.setChecked(resource.getParent(), true);
+ setParentsChecked(resource.getParent());
+ }
+ }
+
+ /**
+ * removes all child resources of the specified folder from build entries
+ *
+ * @param folder -
+ * current folder being modified in tree
+ *
+ * note: does not remove folder itself
+ */
+ protected abstract void deleteFolderChildrenFromEntries(IFolder folder);
+
+ protected void initializeCheckState() {
+ uncheckAll();
+ }
+
+ protected void initializeCheckState(final IBuildEntry includes,
+ final IBuildEntry excludes) {
+ fTreeViewer.getTree().getDisplay().asyncExec(new Runnable() {
+
+ public void run() {
+ if (fTreeViewer.getTree().isDisposed()) return;
+ Vector fileExt = new Vector();
+ String[] inclTokens, exclTokens = new String[0];
+ if (fProject == null || includes == null)
+ return;
+ inclTokens = includes.getTokens();
+ if (excludes != null)
+ exclTokens = excludes.getTokens();
+ Set temp = new TreeSet();
+ for (int i = 0; i < inclTokens.length; i++)
+ temp.add(inclTokens[i]);
+ for (int i = 0; i < exclTokens.length; i++)
+ temp.add(exclTokens[i]);
+ Iterator iter = temp.iterator();
+ while (iter.hasNext()) {
+ String resource = iter.next().toString();
+ boolean isIncluded = includes.contains(resource);
+ if (resource.lastIndexOf(Path.SEPARATOR) == resource
+ .length() - 1) {
+ if (resource.length() == 1) {
+ try {
+ IResource[] members = fProject.members();
+ for (int i = 0; i < members.length; i++) {
+ fTreeViewer.setSubtreeChecked(members[i], isIncluded);
+ }
+ } catch (CoreException e) {
+ }
+ } else {
+ IFolder folder = fProject.getFolder(resource);
+ fTreeViewer.setSubtreeChecked(folder, isIncluded);
+ fTreeViewer.setParentsGrayed(folder, true);
+ if (isIncluded && folder.exists()) {
+ setParentsChecked(folder);
+ fTreeViewer.setGrayed(folder, false);
+ }
+ }
+ } else if (resource.startsWith("*.")) { //$NON-NLS-1$
+ if (isIncluded)
+ fileExt.add(resource.substring(2));
+ } else {
+ IFile file = fProject.getFile(resource);
+ fTreeViewer.setChecked(file, isIncluded);
+ fTreeViewer.setParentsGrayed(file, true);
+ if (isIncluded && file.exists()) {
+ fTreeViewer.setGrayed(file, false);
+ setParentsChecked(file);
+ }
+ }
+ }
+
+ // set initial expanded state
+ try {
+ IResource[] members = fProject.members();
+ for (int i = 0; i < members.length; i++) {
+ fTreeViewer.setExpandedState(members[i],true);
+ }
+ Object[] exp = fTreeViewer.getVisibleExpandedElements();
+ IContentProvider cp = fTreeViewer.getContentProvider();
+ if ((cp instanceof ITreeContentProvider) && (exp.length>0)) {
+ ITreeContentProvider tcp = (ITreeContentProvider)cp;
+ Object obj = exp[0];
+ while (tcp.hasChildren(obj)) {
+ obj = tcp.getChildren(obj)[0];
+ fTreeViewer.setExpandedState(obj,true);
+ }
+ }
+ } catch (CoreException e) {
+ }
+
+ if (fileExt.size() == 0)
+ return;
+ try {
+ IResource[] members = fProject.members();
+ for (int i = 0; i < members.length; i++) {
+ if (!(members[i] instanceof IFolder)
+ && (fileExt.contains(members[i]
+ .getFileExtension()))) {
+ fTreeViewer.setChecked(members[i], includes
+ .contains("*." //$NON-NLS-1$
+ + members[i].getFileExtension()));
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ });
+ }
+
+ protected abstract void handleBuildCheckStateChange(
+ boolean wasTopParentChecked);
+
+ protected void handleCheck(IBuildEntry includes, IBuildEntry excludes,
+ String resourceName, IResource resource,
+ boolean wasTopParentChecked, String PROPERTY_INCLUDES) {
+
+ try {
+ if (includes == null) {
+ includes = fBuildModel.getFactory().createEntry(
+ PROPERTY_INCLUDES);
+ IBuild build = fBuildModel.getBuild();
+ build.add(includes);
+ }
+ if ((!wasTopParentChecked && !includes.contains(resourceName))
+ || isValidIncludeEntry(includes, excludes, resource,
+ resourceName)) {
+ includes.addToken(resourceName);
+ }
+ if (excludes != null && excludes.contains(resourceName))
+ excludes.removeToken(resourceName);
+
+ } catch (CoreException e) {
+ }
+ }
+
+ protected boolean isValidIncludeEntry(IBuildEntry includes,
+ IBuildEntry excludes, IResource resource, String resourceName) {
+ if (excludes == null)
+ return true;
+ IPath resPath = resource.getProjectRelativePath();
+ while (resPath.segmentCount() > 1) {
+ resPath = resPath.removeLastSegments(1);
+ if (includes.contains(resPath.toString() + Path.SEPARATOR))
+ return false;
+ else if (excludes != null
+ && excludes.contains(resPath.toString() + Path.SEPARATOR))
+ return true;
+ }
+ return !excludes.contains(resourceName);
+ }
+
+ private boolean isIncluded(IResource res) {
+
+ if (res.getType() == IResource.PROJECT){
+ IJavaProject jp = JavaCore.create((IProject)res);
+ return jp.isOnClasspath(res);
+ }
+
+ if (fTreeViewer!=null) {
+ return fTreeViewer.getChecked(res);
+ }
+ return false;
+ }
+
+ protected void handleUncheck(IBuildEntry includes, IBuildEntry excludes,
+ String resourceName, IResource resource, String PROPERTY_EXCLUDES) {
+
+ try {
+ if (isIncluded(resource.getParent())) {
+ if (excludes == null) {
+ excludes = fBuildModel.getFactory().createEntry(
+ PROPERTY_EXCLUDES);
+ IBuild build = fBuildModel.getBuild();
+ build.add(excludes);
+ }
+ if (!excludes.contains(resourceName)
+ && (includes != null
+ ? !includes.contains(resourceName)
+ : true))
+ excludes.addToken(resourceName);
+ }
+ if (includes != null) {
+ if (includes.contains(resourceName))
+ includes.removeToken(resourceName);
+ if(resource.getParent() instanceof IProject) {
+ // If we're removing a source folder add it to the excludes
+ // list (part of the fix for bug 102493)
+ if (excludes == null) {
+ excludes = fBuildModel.getFactory().createEntry(
+ PROPERTY_EXCLUDES);
+ IBuild build = fBuildModel.getBuild();
+ build.add(excludes);
+ }
+ if (!excludes.contains(resourceName)
+ && (includes != null
+ ? !includes.contains(resourceName)
+ : true))
+ excludes.addToken(resourceName);
+ }
+ if (includes.contains("*." + resource.getFileExtension())) { //$NON-NLS-1$
+ IResource[] members = fProject.members();
+ for (int i = 0; i < members.length; i++) {
+ if (!(members[i] instanceof IFolder)
+ && !members[i].getName().equals(
+ resource.getName())
+ && (resource.getFileExtension()
+ .equals(members[i].getFileExtension()))) {
+ includes.addToken(members[i].getName());
+ }
+ IBuildEntry[] libraries = BuildUtil
+ .getBuildLibraries(fBuildModel.getBuild()
+ .getBuildEntries());
+ if (resource.getFileExtension().equals("jar") //$NON-NLS-1$
+ && libraries.length != 0) {
+ for (int j = 0; j < libraries.length; j++) {
+ String libName = libraries[j].getName()
+ .substring(7);
+ IPath path = fProject.getFile(libName)
+ .getProjectRelativePath();
+ if (path.segmentCount() == 1
+ && !includes.contains(libName)
+ && !libName.equals(resource.getName()))
+ includes.addToken(libName);
+ }
+ }
+ }
+ includes.removeToken("*." + resource.getFileExtension()); //$NON-NLS-1$
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ protected String getResourceFolderName(String resourceName) {
+ return resourceName + Path.SEPARATOR;
+ }
+
+ /**
+ * @param resource -
+ * file/folder being modified in tree
+ * @param resourceName -
+ * name file/folder
+ * @return relative path of folder if resource is folder, otherwise, return
+ * resourceName
+ */
+ protected String handleResourceFolder(IResource resource,
+ String resourceName) {
+ if (resource instanceof IFolder) {
+ deleteFolderChildrenFromEntries((IFolder) resource);
+ return getResourceFolderName(resourceName);
+ }
+ return resourceName;
+ }
+
+ public void initialize() {
+ if (fTreeViewer.getInput() == null) {
+ fTreeViewer.setUseHashlookup(true);
+ fTreeViewer.setInput(fProject);
+ }
+ fBuildModel.addModelChangedListener(this);
+ }
+
+ public void dispose() {
+ fBuildModel.removeModelChangedListener(this);
+ PDEPlugin.getWorkspace().removeResourceChangeListener(this);
+ super.dispose();
+ }
+
+ protected void deleteEmptyEntries() {
+ IBuild build = fBuildModel.getBuild();
+ IBuildEntry[] entries = {
+ build.getEntry(IBuildPropertiesConstants.PROPERTY_BIN_EXCLUDES),
+ build.getEntry(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES),
+ build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES),
+ build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES)};
+ try {
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i] != null && entries[i].getTokens().length == 0)
+ build.remove(entries[i]);
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ public CheckboxTreeViewer getTreeViewer() {
+ return fTreeViewer;
+ }
+
+ protected ISelection getViewerSelection() {
+ return getTreeViewer().getSelection();
+ }
+
+ public void refresh() {
+ initializeCheckState();
+ super.refresh();
+ }
+
+ public void uncheckAll() {
+ fTreeViewer.setCheckedElements(new Object[0]);
+ }
+
+ protected void removeChildren(IBuildEntry entry, String parentFolder) {
+ try {
+ if (entry != null) {
+ String[] tokens = entry.getTokens();
+ for (int i = 0; i < tokens.length; i++) {
+ if (tokens[i].indexOf(Path.SEPARATOR) != -1
+ && tokens[i].startsWith(parentFolder)
+ && !tokens[i].equals(parentFolder)) {
+ entry.removeToken(tokens[i]);
+ }
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ public void resourceChanged(IResourceChangeEvent event) {
+ if (fTreeViewer.getControl().isDisposed())
+ return;
+ fDoRefresh = false;
+ IResourceDelta delta = event.getDelta();
+ try {
+ if (delta != null)
+ delta.accept(this);
+ if (fDoRefresh) {
+ asyncRefresh();
+ fDoRefresh = false;
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ public boolean visit(IResourceDelta delta) {
+ IResource resource = delta.getResource();
+ if ((resource instanceof IFile || resource instanceof IFolder)
+ && resource.getProject().equals(
+ fBuildModel.getUnderlyingResource().getProject())) {
+ if (delta.getKind() == IResourceDelta.ADDED
+ || delta.getKind() == IResourceDelta.REMOVED) {
+ fDoRefresh = true;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void asyncRefresh() {
+ Control control = fTreeViewer.getControl();
+ if (!control.isDisposed()) {
+ control.getDisplay().asyncExec(new Runnable() {
+
+ public void run() {
+ if (!fTreeViewer.getControl().isDisposed()) {
+ fTreeViewer.refresh(true);
+ initializeCheckState();
+ }
+ }
+ });
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.pde.internal.ui.editor.TableSection#selectionChanged(org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ protected void selectionChanged(IStructuredSelection selection) {
+ getPage().getPDEEditor().setSelection(selection);
+
+ }
+
+ public void modelChanged(IModelChangedEvent event) {
+
+ if (event.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
+ markStale();
+ }
+ Object changeObject = event.getChangedObjects()[0];
+
+ if (!(changeObject instanceof IBuildEntry && (((IBuildEntry) changeObject)
+ .getName().equals(
+ IBuildPropertiesConstants.PROPERTY_BIN_EXCLUDES)
+ || ((IBuildEntry) changeObject).getName().equals(
+ IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES)
+ || ((IBuildEntry) changeObject).getName().equals(
+ IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES) || ((IBuildEntry) changeObject)
+ .getName().equals(
+ IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES))))
+ return;
+
+ if ((fParentResource == null && fOriginalResource != null)
+ || (fOriginalResource == null && fParentResource != null)) {
+ initializeCheckState();
+ return;
+ }
+ if ((fParentResource == null && fOriginalResource == null)
+ || (event.getChangedProperty() != null && event
+ .getChangedProperty()
+ .equals(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES))) {
+
+ return;
+ }
+
+ fTreeViewer.setChecked(fParentResource, isChecked);
+ fTreeViewer.setGrayed(fOriginalResource, false);
+ fTreeViewer.setParentsGrayed(fParentResource, true);
+ setParentsChecked(fParentResource);
+ fTreeViewer.setGrayed(fParentResource, false);
+ if (fParentResource instanceof IFolder) {
+ fTreeViewer.setSubtreeChecked(fParentResource, isChecked);
+ setChildrenGrayed(fParentResource, false);
+ }
+ while (!fOriginalResource.equals(fParentResource)) {
+ fTreeViewer.setChecked(fOriginalResource, isChecked);
+ fOriginalResource = fOriginalResource.getParent();
+ }
+ fParentResource = null;
+ fOriginalResource = null;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditor.java
new file mode 100644
index 0000000..685bc18
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditor.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ajdt.pde.internal.ui.editor.ISortableContentOutlinePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.MultiSourceEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDESourcePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileEditorInput;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContextManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.core.build.IBuildModel;
+import org.eclipse.pde.internal.core.build.IBuildObject;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.dnd.RTFTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+
+public class BuildEditor extends MultiSourceEditor {
+ public BuildEditor() {
+ }
+ protected void createResourceContexts(InputContextManager manager,
+ IFileEditorInput input) {
+ IFile file = input.getFile();
+
+ manager.putContext(input, new BuildInputContext(this, input, true));
+ manager.monitorFile(file);
+ }
+
+ protected InputContextManager createInputContextManager() {
+ BuildInputContextManager manager = new BuildInputContextManager(this);
+ manager.setUndoManager(new BuildUndoManager(this));
+ return manager;
+ }
+
+ public void monitoredFileAdded(IFile file) {
+ if (!inputContextManager.hasContext(BuildInputContext.CONTEXT_ID)) {
+ IEditorInput in = new FileEditorInput(file);
+ inputContextManager.putContext(in, new BuildInputContext(this, in, false));
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void doSave(IProgressMonitor monitor) {
+ super.doSave(monitor);
+ // now perform a full rebuild if the file changed is the active configuration file
+ IEditorInput in = inputContextManager.getPrimaryContext().getInput();
+ if ((in instanceof IFileEditorInput)) { // && (pbc!=null)) {
+ IFile changedFile = ((IFileEditorInput)in).getFile();
+ AJLog.log("Build configuration file written: " + changedFile.getName()); //$NON-NLS-1$
+ }
+ }
+
+ public boolean monitoredFileRemoved(IFile file) {
+ //TODO may need to check with the user if there
+ //are unsaved changes in the model for the
+ //file that just got removed under us.
+ return true;
+ }
+ public void contextAdded(InputContext context) {
+ addSourcePage(context.getId());
+ }
+ public void contextRemoved(InputContext context) {
+ if (context.isPrimary()) {
+ close(true);
+ return;
+ }
+ IFormPage page = findPage(context.getId());
+ if (page!=null)
+ removePage(context.getId());
+ }
+
+ protected void createSystemFileContexts(InputContextManager manager,
+ SystemFileEditorInput input) {
+ manager.putContext(input, new BuildInputContext(this, input, true));
+ }
+
+ protected void createStorageContexts(InputContextManager manager,
+ IStorageEditorInput input) {
+ manager.putContext(input, new BuildInputContext(this, input, true));
+ }
+
+ public boolean canCopy(ISelection selection) {
+ return true;
+ }
+
+ protected void addPages() {
+ try {
+ if (getEditorInput() instanceof IFileEditorInput)
+ addPage(new BuildPage(this));
+ } catch (PartInitException e) {
+ PDEPlugin.logException(e);
+ }
+ addSourcePage(BuildInputContext.CONTEXT_ID);
+ }
+
+ protected String computeInitialPageId() {
+ String firstPageId = super.computeInitialPageId();
+ if (firstPageId == null) {
+ InputContext primary = inputContextManager.getPrimaryContext();
+ if (primary.getId().equals(BuildInputContext.CONTEXT_ID))
+ firstPageId = BuildPage.PAGE_ID;
+ if (firstPageId == null)
+ firstPageId = BuildPage.PAGE_ID;
+ }
+ return firstPageId;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.MultiSourceEditor#createXMLSourcePage(org.eclipse.pde.internal.ui.neweditor.PDEFormEditor, java.lang.String, java.lang.String)
+ */
+ protected PDESourcePage createSourcePage(PDEFormEditor editor, String title, String name, String contextId) {
+ return new BuildSourcePage(editor, title, name);
+ }
+
+ protected ISortableContentOutlinePage createContentOutline() {
+ return new BuildOutlinePage(this);
+ }
+
+ protected IPropertySheetPage getPropertySheet(PDEFormPage page) {
+ return null;
+ }
+
+ public String getTitle() {
+ return super.getTitle();
+ }
+
+ protected boolean isModelCorrect(Object model) {
+ return model != null ? ((IBuildModel) model).isValid() : false;
+ }
+ protected boolean hasKnownTypes() {
+ try {
+ TransferData[] types = getClipboard().getAvailableTypes();
+ Transfer[] transfers =
+ new Transfer[] { TextTransfer.getInstance(), RTFTransfer.getInstance()};
+ for (int i = 0; i < types.length; i++) {
+ for (int j = 0; j < transfers.length; j++) {
+ if (transfers[j].isSupportedType(types[i]))
+ return true;
+ }
+ }
+ } catch (SWTError e) {
+ }
+ return false;
+ }
+
+ public Object getAdapter(Class key) {
+ //No property sheet needed - block super
+ if (key.equals(IPropertySheetPage.class)) {
+ return null;
+ }
+ return super.getAdapter(key);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.editor.PDEFormEditor#getInputContext(java.lang.Object)
+ */
+ protected InputContext getInputContext(Object object) {
+ InputContext context = null;
+ if (object instanceof IBuildObject) {
+ context = inputContextManager.findContext(BuildInputContext.CONTEXT_ID);
+ }
+ return context;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditorContributor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditorContributor.java
new file mode 100644
index 0000000..5f6c03e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditorContributor.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditorContributor;
+
+public class BuildEditorContributor extends PDEFormEditorContributor {
+
+ public BuildEditorContributor() {
+ super("&Build"); //$NON-NLS-1$
+ }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContext.java
new file mode 100644
index 0000000..f1d4f6a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContext.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.BuildModel;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileEditorInput;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.internal.core.text.AbstractEditingModel;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+
+public class BuildInputContext extends InputContext {
+ public static final String CONTEXT_ID = "build-context"; //$NON-NLS-1$
+
+ private HashMap fOperationTable = new HashMap();
+
+ public BuildInputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+ super(editor, input, primary);
+ create();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#getCharSet()
+ */
+ protected String getDefaultCharset() {
+ return "ISO-8859-1"; //$NON-NLS-1$
+ }
+
+ protected IBaseModel createModel(IEditorInput input) throws CoreException {
+ BuildModel model = null;
+ if (input instanceof IStorageEditorInput) {
+ boolean isReconciling = input instanceof IFileEditorInput;
+ IDocument document = getDocumentProvider().getDocument(input);
+ model = new BuildModel(document, isReconciling);
+ if (input instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput)input).getFile();
+ model.setUnderlyingResource(file);
+ model.setCharset(file.getCharset());
+ } else if (input instanceof SystemFileEditorInput){
+ File file = (File)((SystemFileEditorInput)input).getAdapter(File.class);
+ model.setInstallLocation(file.getParent());
+ model.setCharset(getDefaultCharset());
+ } else {
+ model.setCharset(getDefaultCharset());
+ }
+ model.load();
+ }
+ return model;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.InputContext#getId()
+ */
+ public String getId() {
+ return CONTEXT_ID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#addTextEditOperation(java.util.ArrayList, org.eclipse.pde.core.IModelChangedEvent)
+ */
+ protected void addTextEditOperation(ArrayList ops, IModelChangedEvent event) {
+ Object[] objects = event.getChangedObjects();
+ if (objects != null) {
+ for (int i = 0; i < objects.length; i++) {
+ Object object = objects[i];
+ IDocumentKey key = (IDocumentKey)object;
+ TextEdit op = (TextEdit)fOperationTable.get(key);
+ if (op != null) {
+ fOperationTable.remove(key);
+ ops.remove(op);
+ }
+ switch (event.getChangeType()) {
+ case IModelChangedEvent.REMOVE :
+ deleteKey(key, ops);
+ break;
+ case IModelChangedEvent.INSERT :
+ insertKey(key, ops);
+ break;
+ case IModelChangedEvent.CHANGE :
+ modifyKey(key, ops);
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ private void insertKey(IDocumentKey key, ArrayList ops) {
+ IDocument doc = getDocumentProvider().getDocument(getInput());
+ String preTermination = ""; //$NON-NLS-1$
+ if (doc.getNumberOfLines() > 0) {
+ try {
+ if (doc.getLineDelimiter(doc.getNumberOfLines() - 1) == null
+ && doc.getLineLength(doc.getNumberOfLines() - 1) > 0) {
+ preTermination = getLineDelimiter();
+ }
+ } catch (BadLocationException ble) {
+ }
+ }
+ InsertEdit op = new InsertEdit(doc.getLength(), preTermination
+ + key.write());
+ fOperationTable.put(key, op);
+ ops.add(op);
+ }
+
+ private void deleteKey(IDocumentKey key, ArrayList ops) {
+ if (key.getOffset() >= 0) {
+ TextEdit op = new DeleteEdit(key.getOffset(), key.getLength());
+ fOperationTable.put(key, op);
+ ops.add(op);
+ }
+ }
+
+ private void modifyKey(IDocumentKey key, ArrayList ops) {
+ if (key.getOffset() == -1) {
+ insertKey(key, ops);
+ } else {
+ TextEdit op = new ReplaceEdit(key.getOffset(), key.getLength(), key.write());
+ fOperationTable.put(key, op);
+ ops.add(op);
+ }
+ }
+ public void doRevert() {
+ fEditOperations.clear();
+ fOperationTable.clear();
+ AbstractEditingModel model = (AbstractEditingModel)getModel();
+ model.reconciled(model.getDocument());
+ }
+
+ protected String getPartitionName() {
+ return "___build_partition"; //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContextManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContextManager.java
new file mode 100644
index 0000000..ee24db5
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContextManager.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.*;
+
+/**
+ * @author dejan
+ */
+public class BuildInputContextManager extends InputContextManager {
+ /**
+ *
+ */
+ public BuildInputContextManager(PDEFormEditor editor) {
+ super(editor);
+ }
+
+ public IBaseModel getAggregateModel() {
+ return findBuildModel();
+ }
+
+ private IBaseModel findBuildModel() {
+ InputContext bcontext = findContext(BuildInputContext.CONTEXT_ID);
+ if (bcontext!=null)
+ return bcontext.getModel();
+ else
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildOutlinePage.java
new file mode 100644
index 0000000..45e8b1c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildOutlinePage.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildModel;
+import org.eclipse.ajdt.pde.internal.ui.editor.FormOutlinePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+
+public class BuildOutlinePage extends FormOutlinePage {
+ /**
+ * @param editor
+ */
+ public BuildOutlinePage(PDEFormEditor editor) {
+ super(editor);
+ }
+ protected Object[] getChildren(Object parent) {
+ if (parent instanceof PDEFormPage) {
+ PDEFormPage page = (PDEFormPage) parent;
+ IBuildModel model = (IBuildModel) page.getModel();
+ if (model.isValid()) {
+ IBuild build = model.getBuild();
+ if (page.getId().equals(BuildPage.PAGE_ID))
+ return build.getBuildEntries();
+ }
+ }
+ return new Object[0];
+ }
+ protected String getParentPageId(Object item) {
+ String pageId = null;
+ if (item instanceof IBuildEntry)
+ pageId = BuildPage.PAGE_ID;
+ if (pageId != null)
+ return pageId;
+ return super.getParentPageId(item);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildPage.java
new file mode 100644
index 0000000..5599d39
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildPage.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Matt Chapman - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+public class BuildPage extends PDEFormPage {
+ public static final String PAGE_ID = "build"; //$NON-NLS-1$
+ private BuildContentsSection srcSection;
+
+ public BuildPage(FormEditor editor) {
+ super(editor, PAGE_ID, UIMessages.BuildPage_name);
+ }
+
+ protected void createFormContent(IManagedForm mform) {
+ super.createFormContent(mform);
+ GridLayout layout = new GridLayout();
+ ScrolledForm form = mform.getForm();
+ form.setText(UIMessages.AJPropsEditor_BuildPage_title);
+ layout.numColumns = 2;
+ layout.marginWidth = 10;
+ layout.horizontalSpacing = 15;
+ layout.verticalSpacing = 10;
+ layout.makeColumnsEqualWidth = true;
+ form.getBody().setLayout(layout);
+
+
+
+ srcSection = new SrcSection(this, form.getBody());
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = 2;
+ srcSection.getSection().setLayoutData(gd);
+
+ mform.addPart(srcSection);
+ }
+
+
+ public void enableAllSections(boolean enable){
+ srcSection.enableSection(enable);
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildProperties.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildProperties.java
new file mode 100644
index 0000000..c66949f
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildProperties.java
@@ -0,0 +1,545 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Matt Chapman - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.Build;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.BuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.BuildModel;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildModel;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.pde.core.IBaseModel;
+
+/**
+ * This class is used by the build configuration functionality in the UI to
+ * support the including and excluding of resources in .ajproperties files.
+ *
+ * @author Matt Chapman
+ *
+ */
+public class BuildProperties {
+
+ private IFile myPropertiesFile;
+
+ private IBuild build;
+
+ private IBuildModel buildModel;
+
+ public BuildProperties(IFile file) {
+ myPropertiesFile = file;
+ }
+
+ /**
+ * Create a new properties file with the given source folders included
+ * @param file the properties file
+ * @param sourceFolder the list of source filders to include
+ */
+ public BuildProperties(IFile file, List sourceFolders) {
+ myPropertiesFile = file;
+
+ initBuild(false);
+
+ IBuildEntry srcIncl = buildModel.getFactory().createEntry(
+ IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ build.addWithoutNotify(srcIncl);
+
+ IBuildEntry srcExcl = build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ if (srcExcl != null){
+ ((Build)build).removeWithoutNotify(srcExcl);
+ }
+
+ for (Iterator iter = sourceFolders.iterator(); iter.hasNext();) {
+ Object next = iter.next();
+ IPath path;
+ String entry;
+ if (next instanceof IResource) {
+ entry = getNameFromResource(((IResource) next));
+ } else {
+ path = ((IPath) next).addTrailingSeparator();
+ entry = path.toString();
+ }
+
+ addTokenToBuildEntry((BuildEntry) srcIncl, entry);
+ }
+
+ writeFile();
+ }
+
+ /**
+ * Returns a list of all files included by the current configuration.
+ *
+ * @param forceReadingFile if set ensures properties file is always read
+ * @return a list of file resources
+ */
+ public List getFiles(boolean forceReadingFile) {
+ if (forceReadingFile){
+ //ensure latest contents are read
+ initBuild(true);
+ } else {
+ initBuild(false);
+ }
+
+ IBuildEntry srcIncl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuildEntry srcExcl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ IProject fProject = myPropertiesFile.getProject();
+ List included = determineIncludedFiles(srcIncl, srcExcl, fProject);
+
+ return included;
+ }
+
+ /**
+ * Includes the given resource from the active configuration, and writes the
+ * updated configuration file.
+ *
+ * @param res
+ * the resource to include
+ */
+ public void include(IResource res) {
+ String name;
+ if (res.getType() == IResource.FOLDER) {
+ name = res.getProjectRelativePath().addTrailingSeparator()
+ .toString();
+ } else {
+ name = res.getProjectRelativePath().toString();
+ }
+ name = handleResourceFolder(res, name);
+ initBuild(false);
+
+ IBuildEntry srcIncl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuildEntry srcExcl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ handleCheck(srcIncl, srcExcl, name, res);
+
+ if (srcIncl != null) {
+ build.addWithoutNotify(srcIncl);
+ }
+ if (srcExcl != null) {
+ build.addWithoutNotify(srcExcl);
+ }
+ deleteEmptyEntries();
+ //writeFile();
+ }
+
+ /**
+ * Excludes the given resource from the active configuration, and writes the
+ * updated configuration file.
+ *
+ * @param res
+ * the resource to exclude
+ * @throws CoreException
+ */
+ public void exclude(IResource res) throws CoreException {
+ String name;
+ if (res.getType() == IResource.FOLDER) {
+ name = res.getProjectRelativePath().addTrailingSeparator()
+ .toString();
+ } else {
+ name = res.getProjectRelativePath().toString();
+ }
+ name = handleResourceFolder(res, name);
+
+ initBuild(false);
+
+ IBuildEntry srcIncl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuildEntry srcExcl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ handleUncheck(srcIncl, srcExcl, name, res);
+
+ if (srcIncl != null) {
+ build.addWithoutNotify(srcIncl);
+ }
+ if (srcExcl != null) {
+ build.addWithoutNotify(srcExcl);
+ }
+ deleteEmptyEntries();
+ }
+
+ //once build was initialized, it must never be set to null again
+ //to force reinitialization, use forceInit paramter instead
+ //(prevents concurrent access trouble)
+ private void initBuild(boolean forceInit) {
+ if (build == null || forceInit) {
+ BuildEditor be = new BuildEditor();
+ AJLog.log("Build configuration file read: " + myPropertiesFile.getName()); //$NON-NLS-1$
+ be.monitoredFileAdded(myPropertiesFile);
+ IBaseModel ibm = be.getContextManager().findContext(
+ myPropertiesFile).getModel();
+ if (ibm instanceof BuildModel) {
+ buildModel = (BuildModel) ibm;
+ build = buildModel.getBuild();
+ }
+ }
+ }
+
+ //return a list of all file resources in the given folder, including all
+ // sub-folders
+ private List allFiles(IContainer folder) {
+ final List contents = new ArrayList();
+ if(folder.exists()) {
+ try {
+ folder.accept(new IResourceVisitor() {
+ public boolean visit(IResource res) {
+ if (res.getType() == IResource.FILE
+ && CoreUtils.ASPECTJ_SOURCE_FILTER
+ .accept(res.getName())) {
+ contents.add(res);
+ }
+ return true;
+ }
+ });
+ } catch (CoreException e) {
+ }
+ }
+ return contents;
+ }
+
+ private List determineIncludedFiles(final IBuildEntry includes,
+ final IBuildEntry excludes, final IProject fProject) {
+ List includedFiles = new ArrayList();
+ Vector fileExt = new Vector();
+ String[] inclTokens, exclTokens = new String[0];
+ if (fProject == null || includes == null)
+ return includedFiles;
+ inclTokens = includes.getTokens();
+ if (excludes != null)
+ exclTokens = excludes.getTokens();
+ Set temp = new TreeSet();
+ for (int i = 0; i < inclTokens.length; i++)
+ temp.add(inclTokens[i]);
+ for (int i = 0; i < exclTokens.length; i++)
+ temp.add(exclTokens[i]);
+ Iterator iter = temp.iterator();
+ while (iter.hasNext()) {
+ String resource = iter.next().toString();
+ boolean isIncluded = includes.contains(resource);
+ if (resource.lastIndexOf(Path.SEPARATOR) == resource.length() - 1) {
+ IContainer folder;
+ if (resource.length() == 1) {
+ folder = fProject;
+ } else {
+ folder = fProject.getFolder(resource);
+ }
+ if (isIncluded) {
+ includedFiles.addAll(allFiles(folder));
+ } else {
+ includedFiles.removeAll(allFiles(folder));
+ }
+ } else if (resource.startsWith("*.")) { //$NON-NLS-1$
+ if (isIncluded)
+ fileExt.add(resource.substring(2));
+ } else {
+ IFile file = fProject.getFile(resource);
+ if (isIncluded
+ && CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file
+ .getName())) {
+ includedFiles.add(file);
+ } else {
+ includedFiles.remove(file);
+ }
+ }
+ }
+ if (fileExt.size() == 0)
+ return includedFiles;
+ return includedFiles;
+ }
+
+ public void writeFile() {
+ AJLog.log("Build configuration file written: " + myPropertiesFile.getName()); //$NON-NLS-1$
+ IBuildEntry[] entries = build.getBuildEntries();
+ final StringBuffer buff = new StringBuffer();
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i] instanceof BuildEntry) {
+ String s = ((BuildEntry) entries[i]).write();
+ buff.append(s);
+ }
+ }
+
+ if (!myPropertiesFile.getWorkspace().isTreeLocked()) {
+ InputStream inputStream = new ByteArrayInputStream(buff
+ .toString().getBytes());
+ try {
+ if (!myPropertiesFile.exists()) {
+ myPropertiesFile.create(inputStream, false,
+ null);
+ } else {
+ myPropertiesFile.setContents(inputStream,
+ false, true, null);
+ }
+ } catch (CoreException e) {
+ }
+ } else {
+ AJLog.log("BuildProperties: resource tree locked"); //$NON-NLS-1$
+ }
+ }
+
+ private void addTokenToBuildEntry(BuildEntry entry, String token) {
+ if (!entry.contains(token)) {
+ entry.addTokenWithoutNotify(token);
+ }
+ }
+
+ private boolean contains(Object[] array, Object o){
+ if (array == null)
+ return false;
+ for (int i=0; i<array.length; i++){
+ if (array[i].equals(o))
+ return true;
+ }
+ return false;
+ }
+
+ private String getNameFromResource(IResource res){
+ IPath p = res.getProjectRelativePath();
+ if ((res.getType() == IResource.FOLDER) || (res.getType() == IResource.PROJECT))
+ p = p.addTrailingSeparator();
+ return p.toString();
+ }
+
+ private boolean isIncluded(IResource res, IBuildEntry includes, IBuildEntry excludes) {
+ if (res.getParent() == null)
+ return false;
+ String name = getNameFromResource(res);
+ if (includes != null){
+ if (contains(includes.getTokens(), name))
+ return true;
+ }
+ if (excludes != null){
+ if (contains(excludes.getTokens(), name))
+ return false;
+ }
+ return isIncluded(res.getParent(), includes, excludes);
+ }
+
+
+ // from BuildContentsSection
+ /**
+ * @param resource -
+ * file/folder being modified in tree
+ * @param resourceName -
+ * name file/folder
+ * @return relative path of folder if resource is folder, otherwise, return
+ * resourceName
+ */
+ protected String handleResourceFolder(IResource resource,
+ String resourceName) {
+ if (resource instanceof IFolder) {
+ deleteFolderChildrenFromEntries((IFolder) resource);
+ return getResourceFolderName(resourceName);
+ }
+ return resourceName;
+ }
+
+ protected void deleteFolderChildrenFromEntries(IFolder folder) {
+ IBuild build = buildModel.getBuild();
+ IBuildEntry srcIncl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuildEntry srcExcl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ String parentFolder = getResourceFolderName(folder
+ .getProjectRelativePath().toString());
+
+ removeChildren(srcIncl, parentFolder);
+ removeChildren(srcExcl, parentFolder);
+ }
+
+ protected String getResourceFolderName(String resourceName) {
+ return resourceName;
+ }
+
+ protected void removeChildren(IBuildEntry entry, String parentFolder) {
+ if (entry != null) {
+ String[] tokens = entry.getTokens();
+ for (int i = 0; i < tokens.length; i++) {
+ if (tokens[i].indexOf(Path.SEPARATOR) != -1
+ && tokens[i].startsWith(parentFolder)
+ && !tokens[i].equals(parentFolder)) {
+ ((BuildEntry) entry).removeTokenWithoutNotify(tokens[i]);
+ }
+ }
+ }
+ }
+
+ // similar to BuildContentsSection.handleCheck
+ protected void handleCheck(IBuildEntry includes, IBuildEntry excludes,
+ String resourceName, IResource resource) {
+ if (includes == null) {
+ includes = buildModel.getFactory().createEntry(
+ IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuild build = buildModel.getBuild();
+ build.addWithoutNotify(includes);
+ }
+ if ((excludes != null) && excludes.contains(resourceName)) {
+ excludes.removeTokenWithoutNotify(resourceName);
+ }
+ if (!this.isIncluded(resource, includes, excludes)){
+ includes.addTokenWithoutNotify(resourceName);
+ }
+ }
+
+ // similar to BuildContentsSection.handleUnCheck
+ protected void handleUncheck(IBuildEntry includes, IBuildEntry excludes,
+ String resourceName, IResource resource) throws CoreException {
+ if (isIncluded(resource.getParent(), includes, excludes)) {
+ if (excludes == null) {
+ excludes = buildModel.getFactory().createEntry(
+ IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ IBuild build = buildModel.getBuild();
+ build.addWithoutNotify(excludes);
+ }
+ if (!excludes.contains(resourceName)
+ && (includes != null ? !includes.contains(resourceName)
+ : true))
+ excludes.addTokenWithoutNotify(resourceName);
+ }
+ if (includes != null) {
+ if (includes.contains(resourceName))
+ ((BuildEntry) includes).removeTokenWithoutNotify(resourceName);
+ if (includes.contains("*." + resource.getFileExtension())) { //$NON-NLS-1$
+ IResource[] members = myPropertiesFile.getProject().members();
+ for (int i = 0; i < members.length; i++) {
+ if (!(members[i] instanceof IFolder)
+ && !members[i].getName().equals(resource.getName())
+ && (resource.getFileExtension().equals(members[i]
+ .getFileExtension()))) {
+ includes.addTokenWithoutNotify(members[i].getName());
+ }
+ }
+ includes
+ .removeTokenWithoutNotify("*." + resource.getFileExtension()); //$NON-NLS-1$
+ }
+ }
+ }
+
+ protected void deleteEmptyEntries() {
+ IBuild build = buildModel.getBuild();
+ IBuildEntry[] entries = {
+ build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES),
+ build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES) };
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i] != null && entries[i].getTokens().length == 0)
+ ((Build) build).removeWithoutNotify(entries[i]);
+ }
+ }
+
+ /**
+ * @param sourcePathes
+ */
+ public void updateSourceFolders(List sourcePathes) {
+ boolean changed = false;
+
+ initBuild(false);
+
+ IBuildEntry srcIncl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ if (srcIncl != null) {
+ changed |= removeOldSourceFolders(sourcePathes, srcIncl);
+ } else {
+ srcIncl = buildModel.getFactory().createEntry(
+ IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ build.addWithoutNotify(srcIncl);
+ }
+ IBuildEntry srcExcl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ if (srcExcl != null) {
+ changed |= removeOldSourceFolders(sourcePathes, srcExcl);
+ }
+ changed |= addNewSourceFolders(sourcePathes, srcIncl, srcExcl);
+
+ if (changed) {
+ writeFile();
+ }
+ }
+
+ private boolean removeOldSourceFolders(List sourcePathes,
+ IBuildEntry srcIncl) {
+ boolean changed = false;
+ String[] entries = srcIncl.getTokens();
+ Iterator iter;
+ for (int i = 0; i < entries.length; i++) {
+ iter = sourcePathes.iterator();
+ boolean toBeRemoved = true;
+ while (iter.hasNext()) {
+ IPath p = (IPath) iter.next();
+ if (p.isPrefixOf(new Path(entries[i]))) {
+ toBeRemoved = false;
+ break;
+ }
+ }
+ if (toBeRemoved) {
+ srcIncl.removeTokenWithoutNotify(entries[i]);
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ private boolean addNewSourceFolders(List sourcePathes, IBuildEntry srcIncl, IBuildEntry srcExcl) {
+ boolean changed = false;
+ String[] entries = srcIncl.getTokens();
+ String[] excludedEntries;
+ if(srcExcl != null) {
+ excludedEntries = srcExcl.getTokens();
+ } else {
+ excludedEntries = new String[0];
+ }
+ Iterator iter;
+
+ iter = sourcePathes.iterator();
+ while (iter.hasNext()) {
+ boolean isNewSrcPath = true;
+ IPath path = (IPath) iter.next();
+ for (int i = 0; i < entries.length; i++) {
+ if (path.isPrefixOf(new Path(entries[i]))) {
+ isNewSrcPath = false;
+ break;
+ }
+ }
+ // Part of the fix for bug 102493 - check excluded entries too
+ for (int i = 0; i < excludedEntries.length; i++) {
+ if (path.isPrefixOf(new Path(excludedEntries[i]))) {
+ isNewSrcPath = false;
+ break;
+ }
+ }
+ if (isNewSrcPath) {
+ srcIncl.addTokenWithoutNotify(path.addTrailingSeparator()
+ .toString());
+ changed = true;
+ }
+
+ }
+ return changed;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourcePage.java
new file mode 100644
index 0000000..516c057
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourcePage.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.KeyValueSourcePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.pde.core.build.IBuild;
+import org.eclipse.pde.core.build.IBuildEntry;
+import org.eclipse.pde.core.build.IBuildModel;
+import org.eclipse.pde.internal.core.text.IDocumentRange;
+import org.eclipse.pde.internal.core.text.build.BuildEntry;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.editor.text.ColorManager;
+import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class BuildSourcePage extends KeyValueSourcePage {
+ public BuildSourcePage(PDEFormEditor editor, String id, String title) {
+ super(editor, id, title);
+ }
+
+ protected ILabelProvider createOutlineLabelProvider() {
+ return new BuildLabelProvider();
+ }
+
+ protected ITreeContentProvider createOutlineContentProvider() {
+ return new BuildOutlineContentProvider();
+ }
+
+ class BuildOutlineContentProvider extends DefaultContentProvider
+ implements
+ ITreeContentProvider {
+ public Object[] getChildren(Object parent) {
+ return new Object[0];
+ }
+ public boolean hasChildren(Object parent) {
+ return false;
+ }
+ public Object getParent(Object child) {
+ if (child instanceof IBuildEntry)
+ return ((IBuildEntry) child).getModel();
+ return null;
+ }
+ public Object[] getElements(Object parent) {
+ if (parent instanceof IBuildModel) {
+ IBuildModel model = (IBuildModel) parent;
+ IBuild build = model.getBuild();
+ return build.getBuildEntries();
+ }
+ return new Object[0];
+ }
+ }
+ class BuildLabelProvider extends LabelProvider {
+ public String getText(Object obj) {
+ if (obj instanceof IBuildEntry) {
+ return ((IBuildEntry) obj).getName();
+ }
+ return super.getText(obj);
+ }
+ public Image getImage(Object obj) {
+ if (obj instanceof IBuildEntry)
+ return PDEPlugin.getDefault().getLabelProvider().get(
+ PDEPluginImages.DESC_BUILD_VAR_OBJ);
+ return null;
+ }
+ }
+/*
+ private ColorManager fColorManager;
+
+ public BuildSourcePage(PDEFormEditor editor, String id, String title) {
+ super(editor, id, title);
+ IPreferenceStore store = JavaPlugin.getDefault().getCombinedPreferenceStore();
+ setPreferenceStore(store);
+ fColorManager = ColorManager.getDefault();
+ setSourceViewerConfiguration(new BuildSourceViewerConfiguration(fColorManager, store, this));
+ }
+
+ public void dispose() {
+ fColorManager.dispose();
+ super.dispose();
+ }
+
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ try {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null)
+ return;
+ ((BuildSourceViewerConfiguration) getSourceViewerConfiguration()).handlePropertyChangeEvent(event);
+ } finally {
+ super.handlePreferenceStoreChanged(event);
+ }
+ }
+
+ protected IDocumentRange getRangeElement(ITextSelection selection) {
+ if (selection.isEmpty())
+ return null;
+ IBuildModel model = (IBuildModel) getInputContext().getModel();
+ return findBuildNode(model.getBuild().getBuildEntries(), selection.getOffset());
+ }
+
+ private BuildEntry findBuildNode(IBuildEntry[] nodes, int offset) {
+ for (int i = 0; i < nodes.length; i++) {
+ BuildEntry node = (BuildEntry) nodes[i];
+ if (offset >= node.getOffset()
+ && offset < node.getOffset() + node.getLength()) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ protected String[] collectContextMenuPreferencePages() {
+ String[] ids= super.collectContextMenuPreferencePages();
+ String[] more= new String[ids.length + 1];
+ more[0]= "org.eclipse.jdt.ui.preferences.PropertiesFileEditorPreferencePage"; //$NON-NLS-1$
+ System.arraycopy(ids, 0, more, 1, ids.length);
+ return more;
+ }
+
+ protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+ return ((BuildSourceViewerConfiguration)getSourceViewerConfiguration()).affectsTextPresentation(event) || super.affectsTextPresentation(event);
+ }
+ */
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourceViewerConfiguration.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourceViewerConfiguration.java
new file mode 100644
index 0000000..93a17d8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourceViewerConfiguration.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+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.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.pde.internal.ui.editor.text.ArgumentRule;
+import org.eclipse.pde.internal.ui.editor.text.BasePDEScanner;
+import org.eclipse.pde.internal.ui.editor.text.IColorManager;
+import org.eclipse.pde.internal.ui.editor.text.ReconcilingStrategy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+
+
+public class BuildSourceViewerConfiguration extends TextSourceViewerConfiguration {
+
+ protected static String PROPERTIES_FILE_PARTITIONING = "___pf_partitioning"; //$NON-NLS-1$
+ protected static String COMMENT = "__pf_comment"; //$NON-NLS-1$
+ protected static String PROPERTY_VALUE = "__pf_roperty_value"; //$NON-NLS-1$
+ protected static String[] PARTITIONS = new String[] { COMMENT, PROPERTY_VALUE };
+
+ private BasePDEScanner fPropertyKeyScanner;
+ private BasePDEScanner fCommentScanner;
+ private BasePDEScanner fPropertyValueScanner;
+ private IColorManager fColorManager;
+
+ private MonoReconciler fReconciler;
+ private BuildSourcePage fSourcePage;
+
+ private abstract class AbstractJavaScanner extends BasePDEScanner {
+
+ public void adaptToPreferenceChange(PropertyChangeEvent event) {
+ String property= event.getProperty();
+ if (affectsTextPresentation(property)) {
+ Token token = getTokenAffected(event);
+ if (property.endsWith(PreferenceConstants.EDITOR_BOLD_SUFFIX))
+ adaptToStyleChange(event, token, SWT.BOLD);
+ else if (property.endsWith(PreferenceConstants.EDITOR_ITALIC_SUFFIX))
+ adaptToStyleChange(event, token, SWT.ITALIC);
+ else if (property.endsWith(PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX))
+ adaptToStyleChange(event, token, TextAttribute.STRIKETHROUGH);
+ else if (property.endsWith(PreferenceConstants.EDITOR_UNDERLINE_SUFFIX))
+ adaptToStyleChange(event, token, TextAttribute.UNDERLINE);
+ else
+ adaptToColorChange(event, token);
+ }
+ }
+
+ protected TextAttribute createTextAttribute(String property) {
+ Color color = fColorManager.getColor(property);
+ int style = SWT.NORMAL;
+ if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_BOLD_SUFFIX))
+ style |= SWT.BOLD;
+ if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_ITALIC_SUFFIX))
+ style |= SWT.ITALIC;
+ if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX))
+ style |= TextAttribute.STRIKETHROUGH;
+ if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_UNDERLINE_SUFFIX))
+ style |= TextAttribute.UNDERLINE;
+ return new TextAttribute(color, null, style);
+ }
+ }
+
+ private class SingleTokenJavaScanner extends AbstractJavaScanner {
+
+ private String fProperty;
+ public SingleTokenJavaScanner(String property) {
+ fProperty = property;
+ setColorManager(fColorManager);
+ initialize();
+ }
+
+ public boolean affectsTextPresentation(String property) {
+ return property.startsWith(fProperty);
+ }
+
+ protected Token getTokenAffected(PropertyChangeEvent event) {
+ return (Token)fDefaultReturnToken;
+ }
+
+ protected void initialize() {
+ setDefaultReturnToken(new Token(createTextAttribute(fProperty)));
+ }
+ }
+
+ public class PropertyValueScanner extends AbstractJavaScanner {
+
+ public class AssignmentDetector implements IWordDetector {
+
+ public boolean isWordStart(char c) {
+ if ('=' != c && ':' != c || fDocument == null)
+ return false;
+
+ try {
+ // check whether it is the first '='
+ IRegion lineInfo = fDocument.getLineInformationOfOffset(fOffset);
+ int offset = lineInfo.getOffset();
+ String line = fDocument.get(offset, lineInfo.getLength());
+ int i = line.indexOf(c);
+ return i != -1 && i + lineInfo.getOffset() + 1 == fOffset;
+ } catch (BadLocationException ex) {
+ return false;
+ }
+ }
+
+ public boolean isWordPart(char c) {
+ return false;
+ }
+ }
+
+ private Token fArgumentToken;
+ private Token fAssignmentToken;
+
+ public PropertyValueScanner() {
+ setColorManager(fColorManager);
+ initialize();
+ }
+
+ public boolean affectsTextPresentation(String property) {
+ return property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_VALUE)
+ || property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT)
+ || property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT);
+ }
+
+ protected Token getTokenAffected(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT))
+ return fArgumentToken;
+ if (property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT))
+ return fAssignmentToken;
+ return (Token)fDefaultReturnToken;
+ }
+
+ protected void initialize() {
+ IRule[] rules = new IRule[3];
+ fArgumentToken = new Token(createTextAttribute(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT));
+ rules[0] = new ArgumentRule(fArgumentToken);
+
+ fAssignmentToken = new Token(createTextAttribute(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT));
+ rules[1] = new WordRule(new AssignmentDetector(), fAssignmentToken);
+
+ rules[2] = new WhitespaceRule(new IWhitespaceDetector() {
+ public boolean isWhitespace(char c) {
+ return Character.isWhitespace(c);
+ }
+ });
+ setRules(rules);
+ setDefaultReturnToken(new Token(createTextAttribute(PreferenceConstants.PROPERTIES_FILE_COLORING_VALUE)));
+ }
+ }
+
+ public BuildSourceViewerConfiguration(IColorManager colorManager, IPreferenceStore store, BuildSourcePage sourcePage) {
+ super(store);
+ fColorManager = colorManager;
+ fSourcePage = sourcePage;
+ initializeScanners();
+ }
+
+
+ private void initializeScanners() {
+ fPropertyKeyScanner = new SingleTokenJavaScanner(PreferenceConstants.PROPERTIES_FILE_COLORING_KEY);
+ fPropertyValueScanner = new PropertyValueScanner();
+ fCommentScanner = new SingleTokenJavaScanner(PreferenceConstants.PROPERTIES_FILE_COLORING_COMMENT);
+ }
+
+ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+ reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+ DefaultDamagerRepairer dr = new DefaultDamagerRepairer(fPropertyKeyScanner);
+ reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+ dr = new DefaultDamagerRepairer(fCommentScanner);
+ reconciler.setDamager(dr, COMMENT);
+ reconciler.setRepairer(dr, COMMENT);
+
+ dr = new DefaultDamagerRepairer(fPropertyValueScanner);
+ reconciler.setDamager(dr, PROPERTY_VALUE);
+ reconciler.setRepairer(dr, PROPERTY_VALUE);
+
+ return reconciler;
+ }
+
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ if (fReconciler == null) {
+ IBaseModel model = fSourcePage.getInputContext().getModel();
+ if (model instanceof IReconcilingParticipant) {
+ ReconcilingStrategy strategy = new ReconcilingStrategy();
+ strategy.addParticipant((IReconcilingParticipant)model);
+ if (fSourcePage.getContentOutline() instanceof IReconcilingParticipant)
+ strategy.addParticipant((IReconcilingParticipant)fSourcePage.getContentOutline());
+ fReconciler = new MonoReconciler(strategy, false);
+ fReconciler.setDelay(500);
+ }
+ }
+ return fReconciler;
+ }
+
+ public void handlePropertyChangeEvent(PropertyChangeEvent event) {
+ if (affectsColorPresentation(event.getProperty()))
+ fColorManager.handlePropertyChangeEvent(event);
+ fPropertyKeyScanner.adaptToPreferenceChange(event);
+ fCommentScanner.adaptToPreferenceChange(event);
+ fPropertyValueScanner.adaptToPreferenceChange(event);
+ }
+
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ int length = PARTITIONS.length;
+ String[] contentTypes = new String[length + 1];
+ contentTypes[0] = IDocument.DEFAULT_CONTENT_TYPE;
+ for (int i = 0; i < length; i++)
+ contentTypes[i+1] = PARTITIONS[i];
+
+ return contentTypes;
+ }
+
+ public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) {
+ return PROPERTIES_FILE_PARTITIONING;
+ }
+
+ public boolean affectsTextPresentation(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ return fCommentScanner.affectsTextPresentation(property)
+ || fPropertyKeyScanner.affectsTextPresentation(property)
+ || fPropertyValueScanner.affectsTextPresentation(property);
+ }
+
+ private boolean affectsColorPresentation(String property) {
+ return property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_VALUE)
+ || property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT)
+ || property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT)
+ || property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_KEY)
+ || property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_COMMENT);
+ }
+}
+
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUndoManager.java
new file mode 100644
index 0000000..5d9a7d3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUndoManager.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.ModelUndoManager;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.build.IBuild;
+import org.eclipse.pde.core.build.IBuildEntry;
+import org.eclipse.pde.core.build.IBuildModel;
+import org.eclipse.pde.internal.core.build.BuildObject;
+import org.eclipse.pde.internal.core.build.IBuildObject;
+
+public class BuildUndoManager extends ModelUndoManager {
+
+ public BuildUndoManager(PDEFormEditor editor) {
+ super(editor);
+ setUndoLevelLimit(30);
+ }
+
+ protected String getPageId(Object obj) {
+ if (obj instanceof IBuildEntry)
+ return BuildPage.PAGE_ID;
+ return null;
+ }
+
+ protected void execute(IModelChangedEvent event, boolean undo) {
+ Object[] elements = event.getChangedObjects();
+ int type = event.getChangeType();
+ String propertyName = event.getChangedProperty();
+ IBuildModel model = (IBuildModel)event.getChangeProvider();
+
+ switch (type) {
+ case IModelChangedEvent.INSERT :
+ if (undo)
+ executeRemove(model, elements);
+ else
+ executeAdd(model, elements);
+ break;
+ case IModelChangedEvent.REMOVE :
+ if (undo)
+ executeAdd(model, elements);
+ else
+ executeRemove(model, elements);
+ break;
+ case IModelChangedEvent.CHANGE :
+ if (undo)
+ executeChange(
+ elements[0],
+ propertyName,
+ event.getNewValue(),
+ event.getOldValue());
+ else
+ executeChange(
+ elements[0],
+ propertyName,
+ event.getOldValue(),
+ event.getNewValue());
+ }
+ }
+
+ private void executeAdd(IBuildModel model, Object[] elements) {
+ IBuild build = model.getBuild();
+
+ try {
+ for (int i = 0; i < elements.length; i++) {
+ Object element = elements[i];
+
+ if (element instanceof IBuildEntry) {
+ build.add((IBuildEntry)element);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ private void executeRemove(IBuildModel model, Object[] elements) {
+ IBuild build = model.getBuild();
+
+ try {
+ for (int i = 0; i < elements.length; i++) {
+ Object element = elements[i];
+
+ if (element instanceof IBuildEntry) {
+ build.remove((IBuildEntry)element);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ private void executeChange(
+ Object element,
+ String propertyName,
+ Object oldValue,
+ Object newValue) {
+ if (element instanceof BuildObject) {
+ BuildObject bobj = (BuildObject) element;
+ try {
+ bobj.restoreProperty(propertyName, oldValue, newValue);
+ } catch (CoreException e) {
+ }
+ }
+ }
+
+ public void modelChanged(IModelChangedEvent event) {
+ if (event.getChangeType() == IModelChangedEvent.CHANGE) {
+ Object obj = event.getChangedObjects()[0];
+ if (obj instanceof IBuildObject) {
+ IBuildObject bobj = (IBuildObject) event.getChangedObjects()[0];
+ //Ignore events from objects that are not yet in the model.
+ if (!(bobj instanceof IBuild) && bobj.isInTheModel() == false)
+ return;
+ }
+ }
+ super.modelChanged(event);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUtil.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUtil.java
new file mode 100644
index 0000000..0251a82
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUtil.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.util.Vector;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+
+public class BuildUtil {
+
+ public static IBuildEntry[] getBuildLibraries(IBuildEntry[] entries) {
+ Vector temp = new Vector();
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i].getName().startsWith(IBuildEntry.JAR_PREFIX))
+ temp.add(entries[i]);
+ }
+ IBuildEntry[] result = new IBuildEntry[temp.size()];
+ temp.copyInto(result);
+ return result;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/IBuildPropertiesConstants.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/IBuildPropertiesConstants.java
new file mode 100644
index 0000000..663758c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/IBuildPropertiesConstants.java
@@ -0,0 +1,54 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+public interface IBuildPropertiesConstants {
+ public final static String PERMISSIONS = "permissions"; //$NON-NLS-1$
+ public final static String LINK = "link"; //$NON-NLS-1$
+ public final static String EXECUTABLE = "executable"; //$NON-NLS-1$
+ public final static String ROOT_PREFIX = "root."; //$NON-NLS-1$
+ public final static String ROOT = "root"; //$NON-NLS-1$
+
+ public final static String TRUE = "true"; //$NON-NLS-1$
+ public final static String FALSE = "false"; //$NON-NLS-1$
+
+ public static final String PROPERTY_JAR_EXTRA_CLASSPATH = "jars.extra.classpath"; //$NON-NLS-1$
+ public static final String PROPERTY_JAR_ORDER = "jars.compile.order"; //$NON-NLS-1$
+ public static final String PROPERTY_SOURCE_PREFIX = "source."; //$NON-NLS-1$
+ public static final String PROPERTY_OUTPUT_PREFIX = "output."; //$NON-NLS-1$
+ public static final String PROPERTY_EXTRAPATH_PREFIX = "extra."; //$NON-NLS-1$
+ public static final String PROPERTY_JAR_SUFFIX = ".jar"; //$NON-NLS-1$
+
+ public static final String PROPERTY_QUALIFIER = "qualifier"; //$NON-NLS-1$
+ public static final String PROPERTY_NONE = "none"; //$NON-NLS-1$
+ public static final String PROPERTY_CONTEXT = "context"; //$NON-NLS-1$
+
+ public final static String GENERATION_SOURCE_PREFIX = "generate."; //$NON-NLS-1$
+ public final static String GENERATION_SOURCE_FEATURE_PREFIX = GENERATION_SOURCE_PREFIX + "feature@"; //$NON-NLS-1$
+ public final static String GENERATION_SOURCE_PLUGIN_PREFIX = GENERATION_SOURCE_PREFIX + "plugin@"; //$NON-NLS-1$
+ public final static String PROPERTY_SOURCE_FEATURE_NAME = "sourceFeature.name"; //$NON-NLS-1$
+
+ public static final String PROPERTY_CUSTOM = "custom"; //$NON-NLS-1$
+ public static final String PROPERTY_ZIP_SUFFIX = ".zip"; //$NON-NLS-1$
+
+ public static final String PROPERTY_BIN_EXCLUDES = "bin.excludes"; //$NON-NLS-1$
+ public static final String PROPERTY_BIN_INCLUDES = "bin.includes"; //$NON-NLS-1$
+
+ public static final String PROPERTY_SRC_EXCLUDES = "src.excludes"; //$NON-NLS-1$
+ public static final String PROPERTY_SRC_INCLUDES = "src.includes"; //$NON-NLS-1$
+
+ public static final String DEFAULT_MATCH_ALL = "*"; //$NON-NLS-1$
+ public static final String DEFAULT_FINAL_SHAPE = "*"; //$NON-NLS-1$
+
+ //Internal usage only
+ public static final String SOURCE_PLUGIN = "sourcePlugin"; //$NON-NLS-1$
+}
+
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/PropertiesUtil.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/PropertiesUtil.java
new file mode 100644
index 0000000..c4149d8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/PropertiesUtil.java
@@ -0,0 +1,130 @@
+/**********************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.io.PrintWriter;
+import java.util.Enumeration;
+
+/**
+ * @author dejan
+ *
+ */
+public class PropertiesUtil {
+ private static final char[] HEX =
+ {
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F' };
+
+ public static String createWritableName(String source) {
+ if (source.indexOf(' ') == -1)
+ return source;
+ // has blanks
+ StringBuffer writableName = new StringBuffer();
+ for (int i = 0; i < source.length(); i++) {
+ char c = source.charAt(i);
+ if (c == ' ') {
+ writableName.append("\\ "); //$NON-NLS-1$
+ } else
+ writableName.append(c);
+ }
+ return writableName.toString();
+ }
+
+ public static String createEscapedValue(String value) {
+ // if required, escape property values as \\uXXXX
+ StringBuffer buf = new StringBuffer(value.length() * 2);
+ // assume expansion by less than factor of 2
+ for (int i = 0; i < value.length(); i++) {
+ char character = value.charAt(i);
+ if (character == '\\'
+ || character == '\t'
+ || character == '\r'
+ || character == '\n'
+ || character == '\f') {
+ // handle characters requiring leading \
+ buf.append('\\');
+ buf.append(character);
+ } else if ((character < 0x0020) || (character > 0x007e)) {
+ // handle characters outside base range (encoded)
+ buf.append('\\');
+ buf.append('u');
+ buf.append(HEX[(character >> 12) & 0xF]); // first nibble
+ buf.append(HEX[(character >> 8) & 0xF]); // second nibble
+ buf.append(HEX[(character >> 4) & 0xF]); // third nibble
+ buf.append(HEX[character & 0xF]); // fourth nibble
+ } else {
+ // handle base characters
+ buf.append(character);
+ }
+ }
+ return buf.toString();
+ }
+
+ public static void writeKeyValuePair(String name, String value, PrintWriter writer) {
+ String writableName = createWritableName(name);
+ writer.print(writableName + " = "); //$NON-NLS-1$
+
+ writer.println(PropertiesUtil.createEscapedValue(value));
+ }
+
+ public static void writeKeyValuePair(String name, Enumeration tokens, PrintWriter writer) {
+ String writableName = createWritableName(name);
+ writer.print(writableName + " = "); //$NON-NLS-1$
+ if (!tokens.hasMoreElements()) {
+ writer.println();
+ return;
+ }
+ int indentLength = name.length() + 3;
+ for (;tokens.hasMoreElements();) {
+ String token = tokens.nextElement().toString();
+ writer.print(PropertiesUtil.createEscapedValue(token));
+ if (tokens.hasMoreElements()) {
+ writer.println(",\\"); //$NON-NLS-1$
+ for (int j = 0; j < indentLength; j++) {
+ writer.print(" "); //$NON-NLS-1$
+ }
+ } else
+ writer.println(""); //$NON-NLS-1$
+ }
+ }
+
+ public static String writeKeyValuePair(String name, String[] tokens) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(createWritableName(name));
+ buffer.append(" = "); //$NON-NLS-1$
+ int indentLength = name.length() + 3;
+ for (int i = 0; i < tokens.length; i++) {
+ buffer.append(createEscapedValue(tokens[i]));
+ if (i < tokens.length - 1) {
+ buffer.append(",\\" + System.getProperty("line.separator")); //$NON-NLS-1$ //$NON-NLS-2$
+ for (int j = 0; j < indentLength; j++) {
+ buffer.append(" "); //$NON-NLS-1$
+ }
+ }
+ }
+ buffer.append(System.getProperty("line.separator")); //$NON-NLS-1$
+ return buffer.toString();
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/SrcSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/SrcSection.java
new file mode 100644
index 0000000..186f7e8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/SrcSection.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Common Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.core.resources.*;
+import org.eclipse.pde.core.IModelChangedListener;
+import org.eclipse.swt.widgets.Composite;
+
+public class SrcSection extends BuildContentsSection
+ implements
+ IModelChangedListener {
+
+ public SrcSection(BuildPage page, Composite parent) {
+ super(page, parent);
+ getSection().setText(UIMessages.AJPropsEditor_SrcSection_title);
+ getSection().setDescription(UIMessages.AJPropsEditor_SrcSection_desc);
+
+ }
+
+ protected void initializeCheckState() {
+
+ super.initializeCheckState();
+ IBuild build = fBuildModel.getBuild();
+
+ IBuildEntry srcIncl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuildEntry srcExcl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+
+ if (srcIncl == null)
+ return;
+
+ super.initializeCheckState(srcIncl, srcExcl);
+
+ }
+
+ protected void deleteFolderChildrenFromEntries(IFolder folder) {
+ IBuild build = fBuildModel.getBuild();
+ IBuildEntry srcIncl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuildEntry srcExcl = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+ String parentFolder = getResourceFolderName(folder
+ .getProjectRelativePath().toString());
+
+ removeChildren(srcIncl, parentFolder);
+ removeChildren(srcExcl, parentFolder);
+ }
+
+ protected void handleBuildCheckStateChange(boolean wasTopParentChecked) {
+ IResource resource = fParentResource;
+ String resourceName = fParentResource.getFullPath()
+ .removeFirstSegments(1).toString();
+ IBuild build = fBuildModel.getBuild();
+ IBuildEntry includes = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ IBuildEntry excludes = build
+ .getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+
+ resourceName = handleResourceFolder(resource, resourceName);
+
+ if (isChecked)
+ handleCheck(includes, excludes, resourceName, resource,
+ wasTopParentChecked,
+ IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+ else
+ handleUncheck(includes, excludes, resourceName, resource,
+ IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+
+ deleteEmptyEntries();
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/WriteThread.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/WriteThread.java
new file mode 100644
index 0000000..8e82e84
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/WriteThread.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+public class WriteThread extends Thread{
+
+ private static WriteThread instance;
+ //we only need to remember the last posted job and not the
+ //whole queue because jobs in the middle of the queue get
+ //overwritten anyway by the subsequent ones
+ private static Runnable nextJob;
+
+ private WriteThread(){}
+
+ public static synchronized void asyncExec(Runnable r){
+ nextJob = r;
+ if (instance == null){
+ instance = new WriteThread();
+ instance.start();
+ }
+ }
+
+ private synchronized Runnable getNextJob(){
+ Runnable temp = nextJob;
+ if (temp == null){
+ instance = null;
+ return null;
+ }
+ nextJob = null;
+ return temp;
+ }
+
+ public void run(){
+ Runnable myRunnable = getNextJob();
+ while(myRunnable != null){
+ myRunnable.run();
+ myRunnable = getNextJob();
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/Build.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/Build.java
new file mode 100644
index 0000000..78e3957
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/Build.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.ModelChangedEvent;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+
+public class Build implements IBuild {
+
+ private BuildModel fModel;
+ private HashMap fEntries = new HashMap();
+
+ public Build(BuildModel model) {
+ fModel = model;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuild#add(org.eclipse.pde.core.build.IBuildEntry)
+ */
+ public void add(IBuildEntry entry) {
+ fEntries.put(entry.getName(), entry);
+ fModel.fireModelChanged(new ModelChangedEvent(fModel,
+ IModelChangedEvent.INSERT, new Object[]{entry}, null));
+ }
+ public void addWithoutNotify(IBuildEntry entry) {
+ fEntries.put(entry.getName(), entry);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuild#getBuildEntries()
+ */
+ public IBuildEntry[] getBuildEntries() {
+ return (IBuildEntry[])fEntries.values().toArray(new IBuildEntry[fEntries.size()]);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuild#getEntry(java.lang.String)
+ */
+ public IBuildEntry getEntry(String name) {
+ return (IBuildEntry)fEntries.get(name);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuild#remove(org.eclipse.pde.core.build.IBuildEntry)
+ */
+ public void remove(IBuildEntry entry) {
+ fEntries.remove(entry.getName());
+ fModel.fireModelChanged(new ModelChangedEvent(fModel,
+ IModelChangedEvent.REMOVE, new Object[]{entry}, null));
+ }
+ public void removeWithoutNotify(IBuildEntry entry) {
+ fEntries.remove(entry.getName());
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.pde.core.IWritable#write(java.lang.String,
+ * java.io.PrintWriter)
+ */
+ public void write(String indent, PrintWriter writer) {
+ }
+
+ public void load(InputStream source) throws IOException {
+ fEntries.clear();
+ Properties properties = new Properties();
+ properties.load(source);
+ Enumeration iter = properties.keys();
+ while (iter.hasMoreElements()) {
+ String name = iter.nextElement().toString();
+ BuildEntry entry = (BuildEntry)fModel.getFactory().createEntry(name);
+ entry.processEntry(properties.get(name).toString());
+ fEntries.put(name, entry);
+ }
+ adjustOffsets(fModel.getDocument());
+ }
+
+ public void adjustOffsets(IDocument document) {
+ int lines = document.getNumberOfLines();
+ try {
+ IDocumentKey currentKey = null;
+ for (int i = 0; i < lines; i++) {
+ int offset = document.getLineOffset(i);
+ int length = document.getLineLength(i);
+ String line = document.get(offset, length);
+ if (line.startsWith("#") | line.startsWith("!")) { //$NON-NLS-1$ //$NON-NLS-2$
+ if (currentKey != null) {
+ currentKey.setLength(offset - 1 - currentKey.getOffset());
+ currentKey = null;
+ }
+ continue;
+ }
+
+ line = line.trim();
+ if (line.length() == 0)
+ continue;
+
+ if (currentKey != null) {
+ if (!line.endsWith("\\")) { //$NON-NLS-1$
+ currentKey.setLength(offset + document.getLineLength(i) - currentKey.getOffset());
+ currentKey = null;
+ }
+ } else {
+ int index = line.indexOf('=');
+ if (index == -1)
+ index = line.indexOf(':');
+ if (index == -1)
+ index = line.indexOf(' ');
+ if (index == -1)
+ index = line.indexOf('\t');
+ String name = (index != -1) ? line.substring(0, index).trim() : line;
+ currentKey = (IDocumentKey)getEntry(name);
+ if (currentKey != null) {
+ while (Character.isSpaceChar(document.getChar(offset))) {
+ offset += 1;
+ }
+ currentKey.setOffset(offset);
+ if (!line.endsWith("\\")) { //$NON-NLS-1$
+ currentKey.setLength(document.getLineOffset(i) + document.getLineLength(i) - currentKey.getOffset());
+ currentKey = null;
+ }
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ }
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildEntry.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildEntry.java
new file mode 100644
index 0000000..5cbebc7
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildEntry.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.PropertiesUtil;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+
+public class BuildEntry implements IBuildEntry, IDocumentKey {
+
+ private int fLength = -1;
+ private int fOffset = -1;
+ private IBuildModel fModel;
+ private String fName;
+ private ArrayList fTokens = new ArrayList();
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildEntry#addToken(java.lang.String)
+ */
+ public void addToken(String token) {
+ fTokens.add(token);
+ getModel().fireModelObjectChanged(this, getName(), null, token);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildEntry#addToken(java.lang.String)
+ */
+ public void addTokenWithoutNotify(String token) {
+ fTokens.add(token);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.IDocumentKey#getName()
+ */
+ public String getName() {
+ return fName;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildEntry#getTokens()
+ */
+ public String[] getTokens() {
+ return (String[])fTokens.toArray(new String[fTokens.size()]);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildEntry#contains(java.lang.String)
+ */
+ public boolean contains(String token) {
+ return fTokens.contains(token);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildEntry#removeToken(java.lang.String)
+ */
+ public void removeToken(String token) {
+ fTokens.remove(token);
+ getModel().fireModelObjectChanged(this, getName(), token, null);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildEntry#removeToken(java.lang.String)
+ */
+ public void removeTokenWithoutNotify(String token) {
+ fTokens.remove(token);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildEntry#renameToken(java.lang.String, java.lang.String)
+ */
+ public void renameToken(String oldToken, String newToken) {
+ int index = fTokens.indexOf(oldToken);
+ if (index != -1) {
+ fTokens.set(index, newToken);
+ getModel().fireModelObjectChanged(this, getName(), oldToken, newToken);
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.IDocumentKey#setName(java.lang.String)
+ */
+ public void setName(String name) {
+ String oldName = fName;
+ fName = name;
+ if (getModel() != null)
+ getModel().fireModelObjectChanged(this, getName(), oldName, name);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.IDocumentKey#getOffset()
+ */
+ public int getOffset() {
+ return fOffset;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.IDocumentKey#setOffset(int)
+ */
+ public void setOffset(int offset) {
+ fOffset = offset;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.IDocumentKey#getLength()
+ */
+ public int getLength() {
+ return fLength;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.IDocumentKey#setLength(int)
+ */
+ public void setLength(int length) {
+ fLength = length;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.IWritable#write(java.lang.String, java.io.PrintWriter)
+ */
+ public void write(String indent, PrintWriter writer) {
+ }
+
+ public void setModel(IBuildModel model) {
+ fModel = model;
+ }
+
+ public IBuildModel getModel() {
+ return fModel;
+ }
+
+ public void processEntry(String value) {
+ StringTokenizer stok = new StringTokenizer(value, ","); //$NON-NLS-1$
+ while (stok.hasMoreTokens()) {
+ fTokens.add(stok.nextToken().trim());
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.IDocumentKey#write()
+ */
+ public String write() {
+ return PropertiesUtil.writeKeyValuePair(getName(), getTokens());
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModel.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModel.java
new file mode 100644
index 0000000..aa66190
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModel.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.pde.internal.core.NLResourceHelper;
+import org.eclipse.pde.internal.core.text.AbstractEditingModel;
+
+
+public class BuildModel extends AbstractEditingModel implements IBuildModel {
+
+ //private Properties fProperties;
+ private BuildModelFactory fFactory;
+ private Build fBuild;
+
+ /**
+ * @param document
+ * @param isReconciling
+ */
+ public BuildModel(IDocument document, boolean isReconciling) {
+ super(document, isReconciling);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.AbstractEditingModel#createNLResourceHelper()
+ */
+ protected NLResourceHelper createNLResourceHelper() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.IModel#load(java.io.InputStream, boolean)
+ */
+ public void load(InputStream source, boolean outOfSync) {
+ try {
+ fLoaded = true;
+ ((Build)getBuild()).load(source);
+ } catch (IOException e) {
+ fLoaded = false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.model.AbstractEditingModel#adjustOffsets(org.eclipse.jface.text.IDocument)
+ */
+ protected void adjustOffsets(IDocument document) {
+ ((Build)getBuild()).adjustOffsets(document);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildModel#getBuild()
+ */
+ public IBuild getBuild() {
+ if (fBuild == null)
+ fBuild = new Build(this);
+ return fBuild;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildModel#getFactory()
+ */
+ public IBuildModelFactory getFactory() {
+ if (fFactory == null)
+ fFactory = new BuildModelFactory(this);
+ return fFactory;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModelFactory.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModelFactory.java
new file mode 100644
index 0000000..9e0bc8c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModelFactory.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+public class BuildModelFactory implements IBuildModelFactory {
+
+ private IBuildModel fModel;
+
+ public BuildModelFactory(IBuildModel model) {
+ fModel = model;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.core.build.IBuildModelFactory#createEntry(java.lang.String)
+ */
+ public IBuildEntry createEntry(String name) {
+ BuildEntry entry = new BuildEntry();
+ entry.setName(name);
+ entry.setModel(fModel);
+ return entry;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuild.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuild.java
new file mode 100644
index 0000000..d5a8607
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuild.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.core.*;
+/**
+ * The top-level model object of the model that is created from
+ * "build.properties" file.
+ *
+ */
+public interface IBuild extends IWritable {
+ /**
+ * Adds a new build entry. This method can throw a CoreException if the
+ * model is not editable.
+ *
+ * @param entry
+ * an entry to be added
+ */
+ void add(IBuildEntry entry) throws CoreException;
+
+ /**
+ * Adds a new build entry.
+ *
+ * @param entry
+ * an entry to be added
+ */
+ void addWithoutNotify(IBuildEntry entry);
+
+ /**
+ * Returns all the build entries in this object.
+ *
+ * @return an array of build entries
+ */
+ IBuildEntry[] getBuildEntries();
+ /**
+ * Returns the build entry with the specified name.
+ *
+ * @param the
+ * name of the desired entry
+ * @return the entry object with the specified name, or <samp>null </samp>
+ * if not found.
+ */
+ IBuildEntry getEntry(String name);
+ /**
+ * Removes a build entry. This method can throw a CoreException if the model
+ * is not editable.
+ *
+ * @param entry
+ * an entry to be removed
+ */
+ void remove(IBuildEntry entry) throws CoreException;
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildEntry.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildEntry.java
new file mode 100644
index 0000000..483a516
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildEntry.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.core.*;
+/**
+ * Jar entry represents one 'library=folder list' entry
+ * in plugin.jars file.
+ */
+public interface IBuildEntry extends IWritable {
+ /**
+ * A property name for changes to the 'name' field.
+ */
+ public static final String P_NAME = "name"; //$NON-NLS-1$
+ /**
+ * A property name for changes to the '' field.
+ */
+ public static final String JAR_PREFIX = "source."; //$NON-NLS-1$
+ /**
+ * A property name for changes to the 'name' field.
+ */
+ public static final String OUTPUT_PREFIX = "output."; //$NON-NLS-1$
+ /**
+ * A property name for changes to the 'name' field.
+ */
+ public static final String BIN_INCLUDES = "bin.includes"; //$NON-NLS-1$
+ /**
+ * A property name for changes to the 'name' field.
+ */
+ public static final String SRC_INCLUDES = "src.includes"; //$NON-NLS-1$
+ /**
+ * A property name for changes to the 'name' field.
+ */
+ public static final String JARS_EXTRA_CLASSPATH = "jars.extra.classpath"; //$NON-NLS-1$
+ /**
+ * Adds the token to the list of token for this entry.
+ * This method will throw a CoreException if
+ * the model is not editable.
+ *
+ * @param token a name to be added to the list of tokens
+ */
+ void addToken(String token) throws CoreException;
+
+ /**
+ * Adds the token to the list of token for this entry.
+ *
+ * @param token a name to be added to the list of tokens
+ */
+ void addTokenWithoutNotify(String token);
+
+ /**
+ * Returns a model that owns this entry
+ * @return build.properties model
+ */
+ IBuildModel getModel();
+ /**
+ * Returns the name of this entry.
+ * @return the entry name
+ */
+ String getName();
+ /**
+ * Returns an array of tokens for this entry
+ * @return array of tokens
+ */
+ String[] getTokens();
+
+ /**
+ * Returns true if the provided token exists in this entry.
+ * @return true if the token exists in the entry
+ */
+ boolean contains(String token);
+ /**
+ * Removes the token from the list of tokens for this entry.
+ * This method will throw a CoreException if
+ * the model is not editable.
+ *
+ * @param token a name to be removed from the list of tokens
+ */
+ void removeToken(String token) throws CoreException;
+
+ /**
+ * Removes the token from the list of tokens for this entry.
+ *
+ * @param token a name to be removed from the list of tokens
+ */
+ void removeTokenWithoutNotify(String token);
+
+ /**
+ * Changes the name of the token without changing its
+ * position in the list. This method will throw
+ * a CoreException if the model is not editable.
+ *
+ * @param oldToken the old token name
+ * @param newToken the new token name
+ */
+ void renameToken(String oldToken, String newToken) throws CoreException;
+ /**
+ * Sets the name of this build entry. This
+ * method will throw a CoreException if
+ * model is not editable.
+ *
+ * @param name the new name for the entry
+ */
+ void setName(String name) throws CoreException;
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModel.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModel.java
new file mode 100644
index 0000000..1726ef6
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModel.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import org.eclipse.pde.core.*;
+/**
+ * This model is created from the "plugin.jars" file
+ * that defines what source folders in the plug-in are
+ * to be used to build require plug-in Jars.
+ * <p>
+ * If this model is editable, isEditable() will return
+ * true and the model instance will implement IEditable
+ * interface. The model is capable of providing
+ * change notification for the registered listeners.
+ */
+public interface IBuildModel extends IModel, IModelChangeProvider {
+ /**
+ * Returns the top-level model object of this model.
+ *
+ * @return a build.properties top-level model object
+ */
+ IBuild getBuild();
+ /**
+ * Returns the factory that should be used
+ * to create new instance of model objects.
+ * @return the build.properties model factory
+ */
+ IBuildModelFactory getFactory();
+ /**
+ * Returns the location of the file
+ * used to create the model.
+ *
+ * @return the location of the build.properties file
+ * or <samp>null</samp> if the file
+ * is in a workspace.
+ */
+ String getInstallLocation();
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModelFactory.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModelFactory.java
new file mode 100644
index 0000000..3dbaf95
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModelFactory.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+/**
+ * This model factory should be used to
+ * create new instances of plugin.jars model
+ * objects.
+ */
+public interface IBuildModelFactory {
+ /**
+ * Creates a new build entry with
+ * the provided name.
+ * @return a new build.properties entry instance
+ */
+ IBuildEntry createEntry(String name);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/AddBuildConfigurationAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/AddBuildConfigurationAction.java
new file mode 100644
index 0000000..3ca07f0
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/AddBuildConfigurationAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.menu;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurationCreationException;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.jface.action.Action;
+
+/**
+ * @author Luzius Meisser
+ *
+ * Action to add a Build Configuration
+ */
+public class AddBuildConfigurationAction extends Action {
+ static int counter = 0;
+
+ IBuildConfigurator buildconf;
+
+ AddBuildConfigurationAction(){
+ super(UIMessages.BCLabels_SaveBCAs);
+ buildconf = DefaultBuildConfigurator.getBuildConfigurator();
+ }
+
+ public void run(){
+ if (buildconf.getActiveProjectBuildConfigurator() == null){
+ return;
+ }
+ IProjectBuildConfigurator pbc = buildconf.getActiveProjectBuildConfigurator();
+
+ try {
+ new BuildConfiguration(pbc, null);
+ } catch (BuildConfigurationCreationException e) {
+ // creation failed, maybe user has cancelled it, do nothing
+ // can be ignored
+ }
+
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/BuildConfigurationSelectedAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/BuildConfigurationSelectedAction.java
new file mode 100644
index 0000000..0c3a52a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/BuildConfigurationSelectedAction.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.menu;
+
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.jface.action.Action;
+
+/**
+ * @author Luzius Meisser
+ *
+ * Action to select a build configuration
+ */
+
+public class BuildConfigurationSelectedAction extends Action {
+ IProjectBuildConfigurator pbc;
+ IBuildConfiguration myBC;
+
+ public BuildConfigurationSelectedAction(IBuildConfiguration bc){
+ super(bc.getName());
+ myBC = bc;
+ pbc = DefaultBuildConfigurator.getBuildConfigurator().getActiveProjectBuildConfigurator();
+ }
+
+ public void run(){
+ pbc.setActiveBuildConfiguration(myBC);
+ }
+
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/DynamicBuildConfigurationMenu.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/DynamicBuildConfigurationMenu.java
new file mode 100644
index 0000000..9840571
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/DynamicBuildConfigurationMenu.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.menu;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.internal.buildconfig.IBuildConfigurationChangedListener;
+import org.eclipse.ajdt.internal.ui.resources.AspectJImages;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.progress.UIJob;
+
+/**
+ * @author Luzius Meisser
+ *
+ * Submenu displayed in the Project menu.
+ *
+ */
+public class DynamicBuildConfigurationMenu extends MenuManager implements
+ IBuildConfigurationChangedListener {
+ IBuildConfigurator buildconf;
+
+ IContributionItem separator;
+
+ private ImageDescriptor id;
+
+ public DynamicBuildConfigurationMenu(String menuID) {
+ super(UIMessages.BCLabels_ConfigurationSelectionMenu, menuID);
+ separator = new Separator();
+
+ id = AspectJImages.BC_TICK.getImageDescriptor();
+ buildconf = DefaultBuildConfigurator.getBuildConfigurator();
+ ((BuildConfigurator)buildconf).addBuildConfigurationChangedListener(this);
+ IAction addAction = new AddBuildConfigurationAction();
+ addAction.setEnabled(false);
+ this.add(addAction);
+ }
+
+ public void buildConfigurationChanged(final IProjectBuildConfigurator pbc) {
+ Job job = new UIJob(UIMessages.dynamicBuildConfigurationMenu_job_name) {
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ new AddBuildConfigurationAction();
+ rebuildMenu(pbc);
+ return Status.OK_STATUS;
+ }
+ };
+ job.setPriority(Job.SHORT);
+ job.schedule();
+ }
+
+ private void rebuildMenu(final IProjectBuildConfigurator pbc) {
+ final IAction addAction = new AddBuildConfigurationAction();
+ if (pbc == null) {
+ DynamicBuildConfigurationMenu.this.removeAll();
+ DynamicBuildConfigurationMenu.this.setVisible(true);
+ addAction.setEnabled(false);
+ DynamicBuildConfigurationMenu.this.add(separator);
+ DynamicBuildConfigurationMenu.this.add(addAction);
+ return;
+ }
+
+ BuildConfiguration[] bcs = (BuildConfiguration[]) pbc
+ .getBuildConfigurations().toArray(new BuildConfiguration[0]);
+ Util.sort(bcs);
+ final IBuildConfiguration activeBuildConfiguration = pbc.getActiveBuildConfiguration();
+ final BuildConfiguration[] bcs2 = new BuildConfiguration[bcs.length];
+ System.arraycopy(bcs, 0, bcs2, 0, bcs.length);
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ DynamicBuildConfigurationMenu.this.removeAll();
+ for (int i = 0; i < bcs2.length; i++) {
+ Action act = new BuildConfigurationSelectedAction(bcs2[i]);
+ if (bcs2[i] == activeBuildConfiguration)
+ act.setImageDescriptor(id);
+ DynamicBuildConfigurationMenu.this.add(act);
+ }
+ DynamicBuildConfigurationMenu.this.add(separator);
+ DynamicBuildConfigurationMenu.this.add(addAction);
+ DynamicBuildConfigurationMenu.this.setVisible(true);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.action.IContributionItem#isDynamic()
+ */
+ public boolean isDynamic() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCContainerWorkbookPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCContainerWorkbookPage.java
new file mode 100644
index 0000000..b7d855b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCContainerWorkbookPage.java
@@ -0,0 +1,669 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.internal.corext.util.Messages;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.util.PixelConverter;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementSorter;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ExclusionInclusionDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.MultipleFolderSelectionDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.NewSourceFolderDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.OutputLocationDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceContainerWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.ITreeListAdapter;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.TreeListDialogField;
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.NewFolderDialog;
+import org.eclipse.ui.model.BaseWorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * Copied from org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceContainerWorkbookPage;
+ * Change marked with //AspectJ
+ *
+ */
+
+public class BCContainerWorkbookPage extends SourceContainerWorkbookPage {
+
+ private ListDialogField fClassPathList;
+ private IJavaProject fCurrJProject;
+ private IPath fProjPath;
+
+ private Control fSWTControl;
+
+ private IWorkspaceRoot fWorkspaceRoot;
+
+ private TreeListDialogField fFoldersList;
+
+ private StringDialogField fOutputLocationField;
+
+// AspectJ Change Begin
+// Removed "Allow output folder for source folders" option
+// private SelectionButtonDialogField fUseFolderOutputs;
+// AspectJ Change End
+
+ private final int IDX_ADD= 0;
+ private final int IDX_EDIT= 2;
+ private final int IDX_REMOVE= 3;
+
+ public BCContainerWorkbookPage(ListDialogField classPathList, StringDialogField outputLocationField) {
+ super(classPathList, outputLocationField);
+
+ fWorkspaceRoot= ResourcesPlugin.getWorkspace().getRoot();
+ fClassPathList= classPathList;
+
+ fOutputLocationField= outputLocationField;
+
+ fSWTControl= null;
+
+ SourceContainerAdapter adapter= new SourceContainerAdapter();
+
+ String[] buttonLabels;
+
+
+ buttonLabels= new String[] {
+ /* 0 = IDX_ADDEXIST */ NewWizardMessages.SourceContainerWorkbookPage_folders_add_button,
+ /* 1 */ null,
+// AspectJ Change Begin
+// Removed 'Edit' button as we have removed everything that could have been edited.
+ /* 2 */ null,
+// /* 2 = IDX_EDIT */ NewWizardMessages.getString("SourceContainerWorkbookPage.folders.edit.button"), //$NON-NLS-1$
+// AspectJ Change End
+ /* 3 = IDX_REMOVE */ NewWizardMessages.SourceContainerWorkbookPage_folders_remove_button
+ };
+
+ fFoldersList= new TreeListDialogField(adapter, buttonLabels, new CPListLabelProvider());
+ fFoldersList.setDialogFieldListener(adapter);
+ fFoldersList.setLabelText(NewWizardMessages.SourceContainerWorkbookPage_folders_label);
+
+ fFoldersList.setViewerSorter(new CPListElementSorter());
+ fFoldersList.enableButton(IDX_EDIT, false);
+
+// AspectJ Change Begin
+// Removed "Allow output folder for source folders" option
+// fUseFolderOutputs= new SelectionButtonDialogField(SWT.CHECK);
+// fUseFolderOutputs.setSelection(false);
+// fUseFolderOutputs.setLabelText(NewWizardMessages.getString("SourceContainerWorkbookPage.folders.check")); //$NON-NLS-1$
+// fUseFolderOutputs.setDialogFieldListener(adapter);
+// AspectJ Change End
+ }
+
+ public void init(IJavaProject jproject) {
+ fCurrJProject= jproject;
+ fProjPath= fCurrJProject.getProject().getFullPath();
+ updateFoldersList();
+ }
+
+ private void updateFoldersList() {
+ ArrayList folders= new ArrayList();
+
+ List cpelements= fClassPathList.getElements();
+ for (int i= 0; i < cpelements.size(); i++) {
+ CPListElement cpe= (CPListElement)cpelements.get(i);
+ if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ folders.add(cpe);
+ }
+ }
+ fFoldersList.setElements(folders);
+// AspectJ Change Begin
+// Removed "Allow output folder for source folders" option
+// fUseFolderOutputs.setSelection(useFolderOutputs);
+// AspectJ Change End
+
+ for (int i= 0; i < folders.size(); i++) {
+ CPListElement cpe= (CPListElement) folders.get(i);
+ IPath[] patterns= (IPath[]) cpe.getAttribute(CPListElement.EXCLUSION);
+ boolean hasOutputFolder= (cpe.getAttribute(CPListElement.OUTPUT) != null);
+ if (patterns.length > 0 || hasOutputFolder) {
+ fFoldersList.expandElement(cpe, 3);
+ }
+ }
+ }
+
+ public Control getControl(Composite parent) {
+ PixelConverter converter= new PixelConverter(parent);
+ Composite composite= new Composite(parent, SWT.NONE);
+
+ LayoutUtil.doDefaultLayout(composite, new DialogField[] { fFoldersList }, true);
+ LayoutUtil.setHorizontalGrabbing(fFoldersList.getTreeControl(null));
+
+ int buttonBarWidth= converter.convertWidthInCharsToPixels(24);
+ fFoldersList.setButtonsMinWidth(buttonBarWidth);
+
+ fSWTControl= composite;
+
+ // expand
+ List elements= fFoldersList.getElements();
+ for (int i= 0; i < elements.size(); i++) {
+ CPListElement elem= (CPListElement) elements.get(i);
+ IPath[] exclusionPatterns= (IPath[]) elem.getAttribute(CPListElement.EXCLUSION);
+ IPath[] inclusionPatterns= (IPath[]) elem.getAttribute(CPListElement.INCLUSION);
+ IPath output= (IPath) elem.getAttribute(CPListElement.OUTPUT);
+ if (exclusionPatterns.length > 0 || inclusionPatterns.length > 0 || output != null) {
+ fFoldersList.expandElement(elem, 3);
+ }
+ }
+ return composite;
+ }
+
+ private Shell getShell() {
+ if (fSWTControl != null) {
+ return fSWTControl.getShell();
+ }
+ return JavaPlugin.getActiveWorkbenchShell();
+ }
+
+
+ private class SourceContainerAdapter implements ITreeListAdapter, IDialogFieldListener {
+
+ private final Object[] EMPTY_ARR= new Object[0];
+
+ // -------- IListAdapter --------
+ public void customButtonPressed(TreeListDialogField field, int index) {
+ sourcePageCustomButtonPressed(field, index);
+ }
+
+ public void selectionChanged(TreeListDialogField field) {
+ sourcePageSelectionChanged(field);
+ }
+
+ public void doubleClicked(TreeListDialogField field) {
+ sourcePageDoubleClicked(field);
+ }
+
+ public void keyPressed(TreeListDialogField field, KeyEvent event) {
+ sourcePageKeyPressed(field, event);
+ }
+
+ public Object[] getChildren(TreeListDialogField field, Object element) {
+// AspectJ Change Begin
+// Removed "Allow output folder for source folders" option
+// if (element instanceof CPListElement) {
+// return ((CPListElement) element).getChildren(!fUseFolderOutputs.isSelected());
+// }
+// AspectJ Change End
+ return EMPTY_ARR;
+ }
+
+ public Object getParent(TreeListDialogField field, Object element) {
+ if (element instanceof CPListElementAttribute) {
+ return ((CPListElementAttribute) element).getParent();
+ }
+ return null;
+ }
+
+ public boolean hasChildren(TreeListDialogField field, Object element) {
+ //AspectJ Change Begin
+ //We don't want the user to see inclusions or exclusion patterns
+ return false; //(element instanceof CPListElement);
+ //AspectJ Change End
+ }
+
+ // ---------- IDialogFieldListener --------
+ public void dialogFieldChanged(DialogField field) {
+ sourcePageDialogFieldChanged(field);
+ }
+
+ }
+
+ protected void sourcePageKeyPressed(TreeListDialogField field, KeyEvent event) {
+ if (field == fFoldersList) {
+ if (event.character == SWT.DEL && event.stateMask == 0) {
+ List selection= field.getSelectedElements();
+ if (canRemove(selection)) {
+ removeEntry();
+ }
+ }
+ }
+ }
+
+ protected void sourcePageDoubleClicked(TreeListDialogField field) {
+ if (field == fFoldersList) {
+ List selection= field.getSelectedElements();
+ if (canEdit(selection)) {
+ editEntry();
+ }
+ }
+ }
+
+ private boolean hasFolders(IContainer container) {
+ try {
+ IResource[] members= container.members();
+ for (int i= 0; i < members.length; i++) {
+ if (members[i] instanceof IContainer) {
+ return true;
+ }
+ }
+ } catch (CoreException e) {
+ // ignore
+ }
+ return false;
+ }
+
+
+ protected void sourcePageCustomButtonPressed(DialogField field, int index) {
+ if (field == fFoldersList) {
+ if (index == IDX_ADD) {
+ List elementsToAdd= new ArrayList(10);
+ IProject project= fCurrJProject.getProject();
+ if (project.exists()) {
+ if (hasFolders(project)) {
+ CPListElement[] srcentries= openSourceContainerDialog(null);
+ if (srcentries != null) {
+ for (int i= 0; i < srcentries.length; i++) {
+ elementsToAdd.add(srcentries[i]);
+ }
+ }
+ } else {
+ CPListElement entry= openNewSourceContainerDialog(null, true);
+ if (entry != null) {
+ elementsToAdd.add(entry);
+ }
+ }
+ } else {
+ CPListElement entry= openNewSourceContainerDialog(null, false);
+ if (entry != null) {
+ elementsToAdd.add(entry);
+ }
+ }
+ if (!elementsToAdd.isEmpty()) {
+ if (fFoldersList.getSize() == 1) {
+ CPListElement existing= (CPListElement) fFoldersList.getElement(0);
+ if (existing.getResource() instanceof IProject) {
+ askForChangingBuildPathDialog(existing);
+ }
+ }
+ HashSet modifiedElements= new HashSet();
+ askForAddingExclusionPatternsDialog(elementsToAdd, modifiedElements);
+
+ fFoldersList.addElements(elementsToAdd);
+ fFoldersList.postSetSelection(new StructuredSelection(elementsToAdd));
+
+ if (!modifiedElements.isEmpty()) {
+ for (Iterator iter= modifiedElements.iterator(); iter.hasNext();) {
+ Object elem= iter.next();
+ fFoldersList.refresh(elem);
+ fFoldersList.expandElement(elem, 3);
+ }
+ }
+
+ }
+ } else if (index == IDX_EDIT) {
+ editEntry();
+ } else if (index == IDX_REMOVE) {
+ removeEntry();
+ }
+ }
+ }
+
+ private void editEntry() {
+ List selElements= fFoldersList.getSelectedElements();
+ if (selElements.size() != 1) {
+ return;
+ }
+ Object elem= selElements.get(0);
+ if (fFoldersList.getIndexOfElement(elem) != -1) {
+ editElementEntry((CPListElement) elem);
+ } else if (elem instanceof CPListElementAttribute) {
+ editAttributeEntry((CPListElementAttribute) elem);
+ }
+ }
+
+ private void editElementEntry(CPListElement elem) {
+ CPListElement res= null;
+
+ res= openNewSourceContainerDialog(elem, true);
+
+ if (res != null) {
+ fFoldersList.replaceElement(elem, res);
+ }
+ }
+
+ private void editAttributeEntry(CPListElementAttribute elem) {
+ String key= elem.getKey();
+ if (key.equals(CPListElement.OUTPUT)) {
+ CPListElement selElement= elem.getParent();
+ OutputLocationDialog dialog= new OutputLocationDialog(getShell(), selElement, fClassPathList.getElements());
+ if (dialog.open() == Window.OK) {
+ selElement.setAttribute(CPListElement.OUTPUT, dialog.getOutputLocation());
+ fFoldersList.refresh();
+ fClassPathList.dialogFieldChanged(); // validate
+ }
+ } else if (key.equals(CPListElement.EXCLUSION)) {
+ showExclusionInclusionDialog(elem.getParent(), true);
+ } else if (key.equals(CPListElement.INCLUSION)) {
+ showExclusionInclusionDialog(elem.getParent(), false);
+ }
+ }
+
+ private void showExclusionInclusionDialog(CPListElement selElement, boolean focusOnExclusion) {
+ ExclusionInclusionDialog dialog= new ExclusionInclusionDialog(getShell(), selElement, focusOnExclusion);
+ if (dialog.open() == Window.OK) {
+ selElement.setAttribute(CPListElement.INCLUSION, dialog.getInclusionPattern());
+ selElement.setAttribute(CPListElement.EXCLUSION, dialog.getExclusionPattern());
+ fFoldersList.refresh();
+ fClassPathList.dialogFieldChanged(); // validate
+ }
+ }
+
+ protected void sourcePageSelectionChanged(DialogField field) {
+ List selected= fFoldersList.getSelectedElements();
+ fFoldersList.enableButton(IDX_EDIT, canEdit(selected));
+ fFoldersList.enableButton(IDX_REMOVE, canRemove(selected));
+ }
+
+ private void removeEntry() {
+ List selElements= fFoldersList.getSelectedElements();
+ for (int i= selElements.size() - 1; i >= 0 ; i--) {
+ Object elem= selElements.get(i);
+ if (elem instanceof CPListElementAttribute) {
+ CPListElementAttribute attrib= (CPListElementAttribute) elem;
+ String key= attrib.getKey();
+ Object value= null;
+ if (key.equals(CPListElement.EXCLUSION) || key.equals(CPListElement.INCLUSION)) {
+ value= new Path[0];
+ }
+ attrib.getParent().setAttribute(key, value);
+ selElements.remove(i);
+ }
+ }
+ if (selElements.isEmpty()) {
+ fFoldersList.refresh();
+ fClassPathList.dialogFieldChanged(); // validate
+ } else {
+ fFoldersList.removeElements(selElements);
+ }
+ }
+
+ private boolean canRemove(List selElements) {
+ if (selElements.size() == 0) {
+ return false;
+ }
+ for (int i= 0; i < selElements.size(); i++) {
+ Object elem= selElements.get(i);
+ if (elem instanceof CPListElementAttribute) {
+ CPListElementAttribute attrib= (CPListElementAttribute) elem;
+ String key= attrib.getKey();
+ if (CPListElement.INCLUSION.equals(key)) {
+ if (((IPath[]) attrib.getValue()).length == 0) {
+ return false;
+ }
+ } else if (CPListElement.EXCLUSION.equals(key)) {
+ if (((IPath[]) attrib.getValue()).length == 0) {
+ return false;
+ }
+ } else if (attrib.getValue() == null) {
+ return false;
+ }
+ } else if (elem instanceof CPListElement) {
+ CPListElement curr= (CPListElement) elem;
+ if (curr.getParentContainer() != null) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean canEdit(List selElements) {
+ if (selElements.size() != 1) {
+ return false;
+ }
+ Object elem= selElements.get(0);
+ if (elem instanceof CPListElement) {
+ return false;
+ }
+ if (elem instanceof CPListElementAttribute) {
+ return true;
+ }
+ return false;
+ }
+
+ private void sourcePageDialogFieldChanged(DialogField field) {
+ if (fCurrJProject == null) {
+ // not initialized
+ return;
+ }
+
+// AspectJ Change Begin
+// Removed "Allow output folder for source folders" option
+// if (field == fUseFolderOutputs) {
+// if (!fUseFolderOutputs.isSelected()) {
+// int nFolders= fFoldersList.getSize();
+// for (int i= 0; i < nFolders; i++) {
+// CPListElement cpe= (CPListElement) fFoldersList.getElement(i);
+// cpe.setAttribute(CPListElement.OUTPUT, null);
+// }
+// }
+// fFoldersList.refresh();
+// } else
+// AspectJ Change End
+ if (field == fFoldersList) {
+ updateClasspathList();
+ }
+ }
+
+
+ private void updateClasspathList() {
+ List srcelements= fFoldersList.getElements();
+
+ List cpelements= fClassPathList.getElements();
+ int nEntries= cpelements.size();
+ // backwards, as entries will be deleted
+ int lastRemovePos= nEntries;
+ int afterLastSourcePos= 0;
+ for (int i= nEntries - 1; i >= 0; i--) {
+ CPListElement cpe= (CPListElement)cpelements.get(i);
+ int kind= cpe.getEntryKind();
+ if (isEntryKind(kind)) {
+ if (!srcelements.remove(cpe)) {
+ cpelements.remove(i);
+ lastRemovePos= i;
+ } else if (lastRemovePos == nEntries) {
+ afterLastSourcePos= i + 1;
+ }
+ }
+ }
+
+ if (!srcelements.isEmpty()) {
+ int insertPos= Math.min(afterLastSourcePos, lastRemovePos);
+ cpelements.addAll(insertPos, srcelements);
+ }
+
+ if (lastRemovePos != nEntries || !srcelements.isEmpty()) {
+ fClassPathList.setElements(cpelements);
+ }
+ }
+
+ private CPListElement openNewSourceContainerDialog(CPListElement existing, boolean includeLinked) {
+ if (includeLinked) {
+ NewFolderDialog dialog= new NewFolderDialog(getShell(), fCurrJProject.getProject());
+ dialog.setTitle(NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_new_title);
+ if (dialog.open() == Window.OK) {
+ IResource createdFolder= (IResource) dialog.getResult()[0];
+ return newCPSourceElement(createdFolder);
+ }
+ return null;
+ } else {
+ String title= (existing == null) ? NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_new_title : NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_edit_title;
+
+ IProject proj= fCurrJProject.getProject();
+ NewSourceFolderDialog dialog= new NewSourceFolderDialog(getShell(), title, proj, getExistingContainers(existing), existing);
+ dialog.setMessage(Messages.format(NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_description, fProjPath.toString()));
+ if (dialog.open() == Window.OK) {
+ IResource folder= dialog.getSourceFolder();
+ return newCPSourceElement(folder);
+ }
+ return null;
+ }
+ }
+
+
+
+ /**
+ * Asks to change the output folder to 'proj/bin' when no source folders were existing
+ */
+ private void askForChangingBuildPathDialog(CPListElement existing) {
+ IPath outputFolder= new Path(fOutputLocationField.getText());
+
+ IPath newOutputFolder= null;
+ String message;
+ if (outputFolder.segmentCount() == 1) {
+ String outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
+ newOutputFolder= outputFolder.append(outputFolderName);
+ message= Messages.format(NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_project_and_output_message, newOutputFolder);
+ } else {
+ message= NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_project_message;
+ }
+ String title= NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_title;
+ if (MessageDialog.openQuestion(getShell(), title, message)) {
+ fFoldersList.removeElement(existing);
+ if (newOutputFolder != null) {
+ fOutputLocationField.setText(newOutputFolder.toString());
+ }
+ }
+ }
+
+ private void askForAddingExclusionPatternsDialog(List newEntries, Set modifiedEntries) {
+ fixNestingConflicts(newEntries, fFoldersList.getElements(), modifiedEntries);
+ if (!modifiedEntries.isEmpty()) {
+ String title= NewWizardMessages.SourceContainerWorkbookPage_exclusion_added_title;
+ String message= NewWizardMessages.SourceContainerWorkbookPage_exclusion_added_message;
+ MessageDialog.openInformation(getShell(), title, message);
+ }
+ }
+
+ private CPListElement[] openSourceContainerDialog(CPListElement existing) {
+
+ Class[] acceptedClasses= new Class[] { IProject.class, IFolder.class };
+ List existingContainers= getExistingContainers(null);
+
+ IProject[] allProjects= fWorkspaceRoot.getProjects();
+ ArrayList rejectedElements= new ArrayList(allProjects.length);
+ IProject currProject= fCurrJProject.getProject();
+ for (int i= 0; i < allProjects.length; i++) {
+ if (!allProjects[i].equals(currProject)) {
+ rejectedElements.add(allProjects[i]);
+ }
+ }
+ ViewerFilter filter= new TypedViewerFilter(acceptedClasses, rejectedElements.toArray());
+
+ ILabelProvider lp= new WorkbenchLabelProvider();
+ ITreeContentProvider cp= new BaseWorkbenchContentProvider();
+
+ String title= (existing == null) ? NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_new_title : NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_edit_title;
+ String message= (existing == null) ? NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_new_description : NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_edit_description;
+
+ MultipleFolderSelectionDialog dialog= new MultipleFolderSelectionDialog(getShell(), lp, cp);
+ dialog.setExisting(existingContainers.toArray());
+ dialog.setTitle(title);
+ dialog.setMessage(message);
+ dialog.addFilter(filter);
+ dialog.setInput(fCurrJProject.getProject().getParent());
+ if (existing == null) {
+ dialog.setInitialFocus(fCurrJProject.getProject());
+ } else {
+ dialog.setInitialFocus(existing.getResource());
+ }
+ if (dialog.open() == Window.OK) {
+ Object[] elements= dialog.getResult();
+ CPListElement[] res= new CPListElement[elements.length];
+ for (int i= 0; i < res.length; i++) {
+ IResource elem= (IResource)elements[i];
+ res[i]= newCPSourceElement(elem);
+ }
+ return res;
+ }
+ return null;
+ }
+
+ private List getExistingContainers(CPListElement existing) {
+ List res= new ArrayList();
+ List cplist= fFoldersList.getElements();
+ for (int i= 0; i < cplist.size(); i++) {
+ CPListElement elem= (CPListElement)cplist.get(i);
+ if (elem != existing) {
+ IResource resource= elem.getResource();
+ if (resource instanceof IContainer) { // defensive code
+ res.add(resource);
+ }
+ }
+ }
+ return res;
+ }
+
+ private CPListElement newCPSourceElement(IResource res) {
+ Assert.isNotNull(res);
+ return new CPListElement(fCurrJProject, IClasspathEntry.CPE_SOURCE, res.getFullPath(), res);
+ }
+
+ /*
+ * @see BuildPathBasePage#getSelection
+ */
+ public List getSelection() {
+ return fFoldersList.getSelectedElements();
+ }
+
+ /*
+ * @see BuildPathBasePage#setSelection
+ */
+ public void setSelection(List selElements) {
+ fFoldersList.selectElements(new StructuredSelection(selElements));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage#isEntryKind(int)
+ */
+ public boolean isEntryKind(int kind) {
+ return kind == IClasspathEntry.CPE_SOURCE;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCPropertyPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCPropertyPage.java
new file mode 100644
index 0000000..6341685
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCPropertyPage.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
+import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
+import org.eclipse.jdt.internal.ui.preferences.PreferencesMessages;
+import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferencePageContainer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+
+/**
+ * Copied from jdt Original name:
+ * org.eclipse.jdt.internal.ui.preferences.BuildPathsPropertyPage
+ * only change: use BuildPathsBlock of this package
+ *
+ */
+public class BCPropertyPage extends PropertyPage implements IStatusChangeListener {
+
+
+private static final String PAGE_SETTINGS= "BuildPathsPropertyPage"; //$NON-NLS-1$
+private static final String INDEX= "pageIndex"; //$NON-NLS-1$
+
+private BuildPathsBlock fBuildPathsBlock;
+
+/*
+ * @see PreferencePage#createControl(Composite)
+ */
+protected Control createContents(Composite parent) {
+ // ensure the page has no special buttons
+ noDefaultAndApplyButton();
+
+ IProject project= getProject();
+ Control result;
+ if (project == null || !isJavaProject(project)) {
+ result= createWithoutJava(parent);
+ } else if (!project.isOpen()) {
+ result= createForClosedProject(parent);
+ } else {
+ result= createWithJava(parent, project);
+ }
+ Dialog.applyDialogFont(result);
+ return result;
+}
+
+/*
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+public void createControl(Composite parent) {
+ super.createControl(parent);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaHelpContextIds.BUILD_PATH_PROPERTY_PAGE);
+}
+
+private IDialogSettings getSettings() {
+ IDialogSettings javaSettings= JavaPlugin.getDefault().getDialogSettings();
+ IDialogSettings pageSettings= javaSettings.getSection(PAGE_SETTINGS);
+ if (pageSettings == null) {
+ pageSettings= javaSettings.addNewSection(PAGE_SETTINGS);
+ pageSettings.put(INDEX, 3);
+ }
+ return pageSettings;
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
+ */
+public void setVisible(boolean visible) {
+ if (fBuildPathsBlock != null) {
+ if (!visible) {
+ if (fBuildPathsBlock.hasChangesInDialog()) {
+ String title= PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_title;
+ String message= PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_message;
+ String[] buttonLabels= new String[] {
+ PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_save,
+ PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_discard,
+ PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_ignore
+ };
+ MessageDialog dialog= new MessageDialog(getShell(), title, null, message, MessageDialog.QUESTION, buttonLabels, 0);
+ int res= dialog.open();
+ if (res == 0) {
+ performOk();
+ } else if (res == 1) {
+ fBuildPathsBlock.init(JavaCore.create(getProject()), null, null);
+ } else {
+ fBuildPathsBlock.initializeTimeStamps();
+ }
+ }
+ } else {
+ if (!fBuildPathsBlock.hasChangesInDialog() && fBuildPathsBlock.hasChangesInClasspathFile()) {
+ fBuildPathsBlock.init(JavaCore.create(getProject()), null, null);
+ }
+ }
+ }
+ super.setVisible(visible);
+}
+
+
+/*
+ * Content for valid projects.
+ */
+private Control createWithJava(Composite parent, IProject project) {
+ IWorkbenchPreferenceContainer pageContainer= null;
+ IPreferencePageContainer container= getContainer();
+ if (container instanceof IWorkbenchPreferenceContainer) {
+ pageContainer= (IWorkbenchPreferenceContainer) container;
+ }
+
+ fBuildPathsBlock= new BuildPathsBlock(new BusyIndicatorRunnableContext(), this, getSettings().getInt(INDEX), false, pageContainer);
+
+ fBuildPathsBlock.init(JavaCore.create(project), null, null);
+ return fBuildPathsBlock.createControl(parent);
+}
+
+/*
+ * Content for non-Java projects.
+ */
+private Control createWithoutJava(Composite parent) {
+ Label label= new Label(parent, SWT.LEFT);
+ label.setText(PreferencesMessages.BuildPathsPropertyPage_no_java_project_message);
+
+ fBuildPathsBlock= null;
+ setValid(true);
+ return label;
+}
+
+/*
+ * Content for closed projects.
+ */
+private Control createForClosedProject(Composite parent) {
+ Label label= new Label(parent, SWT.LEFT);
+ label.setText(PreferencesMessages.BuildPathsPropertyPage_closed_project_message);
+
+ fBuildPathsBlock= null;
+ setValid(true);
+ return label;
+}
+
+private IProject getProject() {
+ IAdaptable adaptable= getElement();
+ if (adaptable != null) {
+ IJavaElement elem= (IJavaElement) adaptable.getAdapter(IJavaElement.class);
+ if (elem instanceof IJavaProject) {
+ return ((IJavaProject) elem).getProject();
+ }
+ }
+ return null;
+}
+
+private boolean isJavaProject(IProject proj) {
+ try {
+ return proj.hasNature(JavaCore.NATURE_ID);
+ } catch (CoreException e) {
+ JavaPlugin.log(e);
+ }
+ return false;
+}
+
+/*
+ * @see IPreferencePage#performOk
+ */
+public boolean performOk() {
+ if (fBuildPathsBlock != null) {
+ getSettings().put(INDEX, fBuildPathsBlock.getPageIndex());
+ IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
+ fBuildPathsBlock.configureJavaProject(monitor);
+ }
+ };
+ WorkbenchRunnableAdapter op= new WorkbenchRunnableAdapter(runnable);
+ op.runAsUserJob(PreferencesMessages.BuildPathsPropertyPage_job_title, null);
+ }
+ return true;
+}
+
+/* (non-Javadoc)
+ * @see IStatusChangeListener#statusChanged
+ */
+public void statusChanged(IStatus status) {
+ setValid(!status.matches(IStatus.ERROR));
+ StatusUtil.applyToStatusLine(this, status);
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jface.preference.IPreferencePage#performCancel()
+ */
+public boolean performCancel() {
+ if (fBuildPathsBlock != null) {
+ getSettings().put(INDEX, fBuildPathsBlock.getPageIndex());
+ }
+ return super.performCancel();
+}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BuildPathsBlock.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BuildPathsBlock.java
new file mode 100644
index 0000000..d8aaf09
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BuildPathsBlock.java
@@ -0,0 +1,869 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaModelStatus;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.corext.util.Messages;
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
+import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
+import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
+import org.eclipse.jdt.internal.ui.util.CoreUtility;
+import org.eclipse.jdt.internal.ui.util.PixelConverter;
+import org.eclipse.jdt.internal.ui.viewsupport.ImageDisposer;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator;
+import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ClasspathOrderingWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.FolderSelectionDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.LibrariesWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ProjectsWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceContainerWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.eclipse.ui.views.navigator.ResourceSorter;
+
+
+/**
+ * Copied from jdt Original name:
+ * org.eclipse.jdt.internal.ui.preferences.BuildPathsBlock
+ * change marked with //AspectJ
+ *
+ */
+
+public class BuildPathsBlock {
+
+ public static interface IRemoveOldBinariesQuery {
+
+ /**
+ * Do the callback. Returns <code>true</code> if .class files should be removed from the
+ * old output location.
+ * @param oldOutputLocation The old output location
+ * @return Returns true if .class files should be removed.
+ * @throws OperationCanceledException
+ */
+ boolean doQuery(IPath oldOutputLocation) throws OperationCanceledException;
+
+ }
+
+
+ private IWorkspaceRoot fWorkspaceRoot;
+
+ private CheckedListDialogField fClassPathList;
+ private StringButtonDialogField fBuildPathDialogField;
+
+ private StatusInfo fClassPathStatus;
+ private StatusInfo fOutputFolderStatus;
+ private StatusInfo fBuildPathStatus;
+
+ private IJavaProject fCurrJProject;
+
+ private IPath fOutputLocationPath;
+
+ private IStatusChangeListener fContext;
+ private Control fSWTWidget;
+
+ private int fPageIndex;
+
+ private BuildPathBasePage fSourceContainerPage;
+ private ProjectsWorkbookPage fProjectsPage;
+ private LibrariesWorkbookPage fLibrariesPage;
+
+ private BuildPathBasePage fCurrPage;
+
+ private String fUserSettingsTimeStamp;
+ private long fFileTimeStamp;
+
+ private final IWorkbenchPreferenceContainer fPageContainer; // null when invoked from a non-property page context
+
+ public BuildPathsBlock(IRunnableContext runnableContext, IStatusChangeListener context, int pageToShow, boolean useNewPage, IWorkbenchPreferenceContainer pageContainer) {
+ fPageContainer= pageContainer;
+ fWorkspaceRoot= JavaPlugin.getWorkspace().getRoot();
+ fContext= context;
+
+ fPageIndex= pageToShow;
+
+ fSourceContainerPage= null;
+ fLibrariesPage= null;
+ fProjectsPage= null;
+ fCurrPage= null;
+
+ BuildPathAdapter adapter= new BuildPathAdapter();
+
+ String[] buttonLabels= new String[] {
+ NewWizardMessages.BuildPathsBlock_classpath_up_button,
+ NewWizardMessages.BuildPathsBlock_classpath_down_button,
+ /* 2 */ null,
+ NewWizardMessages.BuildPathsBlock_classpath_checkall_button,
+ NewWizardMessages.BuildPathsBlock_classpath_uncheckall_button
+
+ };
+
+ fClassPathList= new CheckedListDialogField(null, buttonLabels, new CPListLabelProvider());
+ fClassPathList.setDialogFieldListener(adapter);
+ fClassPathList.setLabelText(NewWizardMessages.BuildPathsBlock_classpath_label);
+ fClassPathList.setUpButtonIndex(0);
+ fClassPathList.setDownButtonIndex(1);
+ fClassPathList.setCheckAllButtonIndex(3);
+ fClassPathList.setUncheckAllButtonIndex(4);
+
+ fBuildPathDialogField= new StringButtonDialogField(adapter);
+ fBuildPathDialogField.setButtonLabel(NewWizardMessages.BuildPathsBlock_buildpath_button);
+ fBuildPathDialogField.setDialogFieldListener(adapter);
+ fBuildPathDialogField.setLabelText(NewWizardMessages.BuildPathsBlock_buildpath_label);
+
+ fBuildPathStatus= new StatusInfo();
+ fClassPathStatus= new StatusInfo();
+ fOutputFolderStatus= new StatusInfo();
+
+ fCurrJProject= null;
+ }
+
+ // -------- UI creation ---------
+
+ public Control createControl(Composite parent) {
+ fSWTWidget= parent;
+
+ PixelConverter converter= new PixelConverter(parent);
+
+ Composite composite= new Composite(parent, SWT.NONE);
+ composite.setFont(parent.getFont());
+
+ GridLayout layout= new GridLayout();
+ layout.marginWidth= 0;
+ layout.marginHeight= 0;
+ layout.numColumns= 1;
+ composite.setLayout(layout);
+
+ TabFolder folder= new TabFolder(composite, SWT.NONE);
+ folder.setLayoutData(new GridData(GridData.FILL_BOTH));
+ folder.setFont(composite.getFont());
+
+ TabItem item;
+ //AspectJ Extension Begin (by Luzius)
+ if (fCurrJProject != null) {
+ try {
+ if (fCurrJProject.getProject().hasNature("org.eclipse.ajdt.ui.ajnature")){ //$NON-NLS-1$
+ fSourceContainerPage = new BCContainerWorkbookPage(
+ fClassPathList, fBuildPathDialogField);
+ } else
+ fSourceContainerPage = new SourceContainerWorkbookPage(
+ fClassPathList, fBuildPathDialogField);
+ } catch (CoreException e1) {
+ fSourceContainerPage = new SourceContainerWorkbookPage(
+ fClassPathList, fBuildPathDialogField);
+ }
+ } else { // Sian - added this else block so that this class can be used in the new Aspectj project wizard (bug 78264)
+ fSourceContainerPage= new BCContainerWorkbookPage(
+ fClassPathList, fBuildPathDialogField);
+ }
+ //AspectJ Extension End (by Luzius)
+ item= new TabItem(folder, SWT.NONE);
+ item.setText(NewWizardMessages.BuildPathsBlock_tab_source);
+ item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_PACKFRAG_ROOT));
+
+// AspectJ Extension Start
+// if (fUseNewPage) {
+// fSourceContainerPage= new NewSourceContainerWorkbookPage(fClassPathList, fBuildPathDialogField, fRunnableContext);
+// } else {
+// fSourceContainerPage= new SourceContainerWorkbookPage(fClassPathList, fBuildPathDialogField);
+// }
+// AspectJ Extension End
+ item.setData(fSourceContainerPage);
+ item.setControl(fSourceContainerPage.getControl(folder));
+
+ IWorkbench workbench= JavaPlugin.getDefault().getWorkbench();
+ Image projectImage= workbench.getSharedImages().getImage(IDE.SharedImages.IMG_OBJ_PROJECT);
+
+ fProjectsPage= new ProjectsWorkbookPage(fClassPathList, fPageContainer);
+ item= new TabItem(folder, SWT.NONE);
+ item.setText(NewWizardMessages.BuildPathsBlock_tab_projects);
+ item.setImage(projectImage);
+ item.setData(fProjectsPage);
+ item.setControl(fProjectsPage.getControl(folder));
+
+ fLibrariesPage= new LibrariesWorkbookPage(fClassPathList, fPageContainer);
+ item= new TabItem(folder, SWT.NONE);
+ item.setText(NewWizardMessages.BuildPathsBlock_tab_libraries);
+ item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_LIBRARY));
+ item.setData(fLibrariesPage);
+ item.setControl(fLibrariesPage.getControl(folder));
+
+ // a non shared image
+ Image cpoImage= JavaPluginImages.DESC_TOOL_CLASSPATH_ORDER.createImage();
+ composite.addDisposeListener(new ImageDisposer(cpoImage));
+
+ ClasspathOrderingWorkbookPage ordpage= new ClasspathOrderingWorkbookPage(fClassPathList);
+ item= new TabItem(folder, SWT.NONE);
+ item.setText(NewWizardMessages.BuildPathsBlock_tab_order);
+ item.setImage(cpoImage);
+ item.setData(ordpage);
+ item.setControl(ordpage.getControl(folder));
+
+ if (fCurrJProject != null) {
+ fSourceContainerPage.init(fCurrJProject);
+ fLibrariesPage.init(fCurrJProject);
+ fProjectsPage.init(fCurrJProject);
+ }
+
+ Composite editorcomp= new Composite(composite, SWT.NONE);
+
+ DialogField[] editors= new DialogField[] { fBuildPathDialogField };
+ LayoutUtil.doDefaultLayout(editorcomp, editors, true, 0, 0);
+
+ int maxFieldWidth= converter.convertWidthInCharsToPixels(40);
+ LayoutUtil.setWidthHint(fBuildPathDialogField.getTextControl(null), maxFieldWidth);
+ LayoutUtil.setHorizontalGrabbing(fBuildPathDialogField.getTextControl(null));
+
+ editorcomp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ folder.setSelection(fPageIndex);
+ fCurrPage= (BuildPathBasePage) folder.getItem(fPageIndex).getData();
+ folder.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ tabChanged(e.item);
+ }
+ });
+
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.BUILD_PATH_BLOCK);
+ Dialog.applyDialogFont(composite);
+ return composite;
+ }
+
+ private Shell getShell() {
+ if (fSWTWidget != null) {
+ return fSWTWidget.getShell();
+ }
+ return JavaPlugin.getActiveWorkbenchShell();
+ }
+
+ /**
+ * Initializes the classpath for the given project. Multiple calls to init are allowed,
+ * but all existing settings will be cleared and replace by the given or default paths.
+ * @param jproject The java project to configure. Does not have to exist.
+ * @param outputLocation The output location to be set in the page. If <code>null</code>
+ * is passed, jdt default settings are used, or - if the project is an existing Java project- the
+ * output location of the existing project
+ * @param classpathEntries The classpath entries to be set in the page. If <code>null</code>
+ * is passed, jdt default settings are used, or - if the project is an existing Java project - the
+ * classpath entries of the existing project
+ */
+ public void init(IJavaProject jproject, IPath outputLocation, IClasspathEntry[] classpathEntries) {
+ fCurrJProject= jproject;
+ boolean projectExists= false;
+ List newClassPath= null;
+ IProject project= fCurrJProject.getProject();
+ projectExists= (project.exists() && project.getFile(".classpath").exists()); //$NON-NLS-1$
+ if (projectExists) {
+ if (outputLocation == null) {
+ outputLocation= fCurrJProject.readOutputLocation();
+ }
+ if (classpathEntries == null) {
+ classpathEntries= fCurrJProject.readRawClasspath();
+ }
+ }
+ if (outputLocation == null) {
+ outputLocation= getDefaultBuildPath(jproject);
+ }
+
+ if (classpathEntries != null) {
+ newClassPath= getExistingEntries(classpathEntries);
+ }
+ if (newClassPath == null) {
+ newClassPath= getDefaultClassPath(jproject);
+ }
+
+ List exportedEntries = new ArrayList();
+ for (int i= 0; i < newClassPath.size(); i++) {
+ CPListElement curr= (CPListElement) newClassPath.get(i);
+ if (curr.isExported() || curr.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ exportedEntries.add(curr);
+ }
+ }
+
+ // inits the dialog field
+ fBuildPathDialogField.setText(outputLocation.makeRelative().toString());
+ fBuildPathDialogField.enableButton(project.exists());
+ fClassPathList.setElements(newClassPath);
+ fClassPathList.setCheckedElements(exportedEntries);
+
+ initializeTimeStamps();
+ updateUI();
+ }
+
+ protected void updateUI() {
+ if (fSWTWidget == null || fSWTWidget.isDisposed()) {
+ return;
+ }
+
+ if (Display.getCurrent() != null) {
+ doUpdateUI();
+ } else {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ if (fSWTWidget == null || fSWTWidget.isDisposed()) {
+ return;
+ }
+ doUpdateUI();
+ }
+ });
+ }
+ }
+
+ protected void doUpdateUI() {
+ fBuildPathDialogField.refresh();
+ fClassPathList.refresh();
+
+ if (fSourceContainerPage != null) {
+ fSourceContainerPage.init(fCurrJProject);
+ fProjectsPage.init(fCurrJProject);
+ fLibrariesPage.init(fCurrJProject);
+ }
+ doStatusLineUpdate();
+ }
+
+ private String getEncodedSettings() {
+ StringBuffer buf= new StringBuffer();
+ CPListElement.appendEncodePath(fOutputLocationPath, buf).append(';');
+
+ int nElements= fClassPathList.getSize();
+ buf.append('[').append(nElements).append(']');
+ for (int i= 0; i < nElements; i++) {
+ CPListElement elem= (CPListElement) fClassPathList.getElement(i);
+ elem.appendEncodedSettings(buf);
+ }
+ return buf.toString();
+ }
+
+ public boolean hasChangesInDialog() {
+ String currSettings= getEncodedSettings();
+ return !currSettings.equals(fUserSettingsTimeStamp);
+ }
+
+ public boolean hasChangesInClasspathFile() {
+ IFile file= fCurrJProject.getProject().getFile(".classpath"); //$NON-NLS-1$
+ return fFileTimeStamp != file.getModificationStamp();
+ }
+
+ public void initializeTimeStamps() {
+ IFile file= fCurrJProject.getProject().getFile(".classpath"); //$NON-NLS-1$
+ fFileTimeStamp= file.getModificationStamp();
+ fUserSettingsTimeStamp= getEncodedSettings();
+ }
+
+
+
+ private ArrayList getExistingEntries(IClasspathEntry[] classpathEntries) {
+ ArrayList newClassPath= new ArrayList();
+ for (int i= 0; i < classpathEntries.length; i++) {
+ IClasspathEntry curr= classpathEntries[i];
+ newClassPath.add(CPListElement.createFromExisting(curr, fCurrJProject));
+ }
+ return newClassPath;
+ }
+
+ // -------- public api --------
+
+ /**
+ * @return Returns the Java project. Can return <code>null<code> if the page has not
+ * been initialized.
+ */
+ public IJavaProject getJavaProject() {
+ return fCurrJProject;
+ }
+
+ /**
+ * @return Returns the current output location. Note that the path returned must not be valid.
+ */
+ public IPath getOutputLocation() {
+ return new Path(fBuildPathDialogField.getText()).makeAbsolute();
+ }
+
+ /**
+ * @return Returns the current class path (raw). Note that the entries returned must not be valid.
+ */
+ public IClasspathEntry[] getRawClassPath() {
+ List elements= fClassPathList.getElements();
+ int nElements= elements.size();
+ IClasspathEntry[] entries= new IClasspathEntry[elements.size()];
+
+ for (int i= 0; i < nElements; i++) {
+ CPListElement currElement= (CPListElement) elements.get(i);
+ entries[i]= currElement.getClasspathEntry();
+ }
+ return entries;
+ }
+
+ public int getPageIndex() {
+ return fPageIndex;
+ }
+
+
+ // -------- evaluate default settings --------
+
+ private List getDefaultClassPath(IJavaProject jproj) {
+ List list= new ArrayList();
+ IResource srcFolder;
+ IPreferenceStore store= PreferenceConstants.getPreferenceStore();
+ String sourceFolderName= store.getString(PreferenceConstants.SRCBIN_SRCNAME);
+ if (store.getBoolean(PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ) && sourceFolderName.length() > 0) {
+ srcFolder= jproj.getProject().getFolder(sourceFolderName);
+ } else {
+ srcFolder= jproj.getProject();
+ }
+
+ list.add(new CPListElement(jproj, IClasspathEntry.CPE_SOURCE, srcFolder.getFullPath(), srcFolder));
+
+ IClasspathEntry[] jreEntries= PreferenceConstants.getDefaultJRELibrary();
+ list.addAll(getExistingEntries(jreEntries));
+ return list;
+ }
+
+ private IPath getDefaultBuildPath(IJavaProject jproj) {
+ IPreferenceStore store= PreferenceConstants.getPreferenceStore();
+ if (store.getBoolean(PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ)) {
+ String outputLocationName= store.getString(PreferenceConstants.SRCBIN_BINNAME);
+ return jproj.getProject().getFullPath().append(outputLocationName);
+ } else {
+ return jproj.getProject().getFullPath();
+ }
+ }
+
+ private class BuildPathAdapter implements IStringButtonAdapter, IDialogFieldListener {
+
+ // -------- IStringButtonAdapter --------
+ public void changeControlPressed(DialogField field) {
+ buildPathChangeControlPressed(field);
+ }
+
+ // ---------- IDialogFieldListener --------
+ public void dialogFieldChanged(DialogField field) {
+ buildPathDialogFieldChanged(field);
+ }
+ }
+
+ private void buildPathChangeControlPressed(DialogField field) {
+ if (field == fBuildPathDialogField) {
+ IContainer container= chooseContainer();
+ if (container != null) {
+ fBuildPathDialogField.setText(container.getFullPath().toString());
+ }
+ }
+ }
+
+ private void buildPathDialogFieldChanged(DialogField field) {
+ if (field == fClassPathList) {
+ updateClassPathStatus();
+ } else if (field == fBuildPathDialogField) {
+ updateOutputLocationStatus();
+ }
+ doStatusLineUpdate();
+ }
+
+
+
+ // -------- verification -------------------------------
+
+ private void doStatusLineUpdate() {
+ if (Display.getCurrent() != null) {
+ IStatus res= findMostSevereStatus();
+ fContext.statusChanged(res);
+ }
+ }
+
+ private IStatus findMostSevereStatus() {
+ return StatusUtil.getMostSevere(new IStatus[] { fClassPathStatus, fOutputFolderStatus, fBuildPathStatus });
+ }
+
+
+ /**
+ * Validates the build path.
+ */
+ public void updateClassPathStatus() {
+ fClassPathStatus.setOK();
+
+ List elements= fClassPathList.getElements();
+
+ CPListElement entryMissing= null;
+ int nEntriesMissing= 0;
+ IClasspathEntry[] entries= new IClasspathEntry[elements.size()];
+
+ for (int i= elements.size()-1 ; i >= 0 ; i--) {
+ CPListElement currElement= (CPListElement)elements.get(i);
+ boolean isChecked= fClassPathList.isChecked(currElement);
+ if (currElement.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ if (!isChecked) {
+ fClassPathList.setCheckedWithoutUpdate(currElement, true);
+ }
+ } else {
+ currElement.setExported(isChecked);
+ }
+
+ entries[i]= currElement.getClasspathEntry();
+ if (currElement.isMissing()) {
+ nEntriesMissing++;
+ if (entryMissing == null) {
+ entryMissing= currElement;
+ }
+ }
+ }
+
+ if (nEntriesMissing > 0) {
+ if (nEntriesMissing == 1) {
+ fClassPathStatus.setWarning(Messages.format(NewWizardMessages.BuildPathsBlock_warning_EntryMissing, entryMissing.getPath().toString()));
+ } else {
+ fClassPathStatus.setWarning(Messages.format(NewWizardMessages.BuildPathsBlock_warning_EntriesMissing, String.valueOf(nEntriesMissing)));
+ }
+ }
+
+/* if (fCurrJProject.hasClasspathCycle(entries)) {
+ fClassPathStatus.setWarning(NewWizardMessages.getString("BuildPathsBlock.warning.CycleInClassPath")); //$NON-NLS-1$
+ }
+*/
+ updateBuildPathStatus();
+ }
+
+ /**
+ * Validates output location & build path.
+ */
+ private void updateOutputLocationStatus() {
+ fOutputLocationPath= null;
+
+ String text= fBuildPathDialogField.getText();
+ if ("".equals(text)) { //$NON-NLS-1$
+ fOutputFolderStatus.setError(NewWizardMessages.BuildPathsBlock_error_EnterBuildPath);
+ return;
+ }
+ IPath path= getOutputLocation();
+ fOutputLocationPath= path;
+
+ IResource res= fWorkspaceRoot.findMember(path);
+ if (res != null) {
+ // if exists, must be a folder or project
+ if (res.getType() == IResource.FILE) {
+ fOutputFolderStatus.setError(NewWizardMessages.BuildPathsBlock_error_InvalidBuildPath);
+ return;
+ }
+ }
+ fOutputFolderStatus.setOK();
+ updateBuildPathStatus();
+ }
+
+ private void updateBuildPathStatus() {
+ List elements= fClassPathList.getElements();
+ IClasspathEntry[] entries= new IClasspathEntry[elements.size()];
+
+ for (int i= elements.size()-1 ; i >= 0 ; i--) {
+ CPListElement currElement= (CPListElement)elements.get(i);
+ entries[i]= currElement.getClasspathEntry();
+ }
+
+ IJavaModelStatus status= JavaConventions.validateClasspath(fCurrJProject, entries, fOutputLocationPath);
+ if (!status.isOK()) {
+ fBuildPathStatus.setError(status.getMessage());
+ return;
+ }
+ fBuildPathStatus.setOK();
+ }
+
+ // -------- creation -------------------------------
+
+ public static void createProject(IProject project, IPath locationPath, IProgressMonitor monitor) throws CoreException {
+ if (monitor == null) {
+ monitor= new NullProgressMonitor();
+ }
+ monitor.beginTask(NewWizardMessages.BuildPathsBlock_operationdesc_project, 10);
+
+ // create the project
+ try {
+ if (!project.exists()) {
+ IProjectDescription desc= project.getWorkspace().newProjectDescription(project.getName());
+ if (Platform.getLocation().equals(locationPath)) {
+ locationPath= null;
+ }
+ desc.setLocation(locationPath);
+ project.create(desc, monitor);
+ monitor= null;
+ }
+ if (!project.isOpen()) {
+ project.open(monitor);
+ monitor= null;
+ }
+ } finally {
+ if (monitor != null) {
+ monitor.done();
+ }
+ }
+ }
+
+ public static void addJavaNature(IProject project, IProgressMonitor monitor) throws CoreException {
+ if (monitor != null && monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ if (!project.hasNature(JavaCore.NATURE_ID)) {
+ IProjectDescription description = project.getDescription();
+ String[] prevNatures= description.getNatureIds();
+ String[] newNatures= new String[prevNatures.length + 1];
+ System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
+ newNatures[prevNatures.length]= JavaCore.NATURE_ID;
+ description.setNatureIds(newNatures);
+ project.setDescription(description, monitor);
+ } else {
+ monitor.worked(1);
+ }
+ }
+
+ public void configureJavaProject(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
+ if (monitor == null) {
+ monitor= new NullProgressMonitor();
+ }
+ monitor.setTaskName(NewWizardMessages.BuildPathsBlock_operationdesc_java);
+ monitor.beginTask("", 10); //$NON-NLS-1$
+ try {
+ IRemoveOldBinariesQuery reorgQuery= getRemoveOldBinariesQuery(null);
+ // remove old .class files
+ if (reorgQuery != null) {
+ IPath oldOutputLocation= fCurrJProject.getOutputLocation();
+ if (!getOutputLocation().equals(oldOutputLocation)) {
+ IResource res= fWorkspaceRoot.findMember(oldOutputLocation);
+ if (res instanceof IContainer && hasClassfiles(res)) {
+ if (reorgQuery.doQuery(oldOutputLocation)) {
+ removeOldClassfiles(res);
+ }
+ }
+ }
+ }
+
+ internalConfigureJavaProject(fClassPathList.getElements(), getOutputLocation(), reorgQuery, monitor);
+ } finally {
+ monitor.done();
+ }
+ updateUI();
+ }
+
+ /*
+ * Creates the Java project and sets the configured build path and output location.
+ * If the project already exists only build paths are updated.
+ */
+ private void internalConfigureJavaProject(List classPathEntries, IPath outputLocation, IRemoveOldBinariesQuery reorgQuery, IProgressMonitor monitor) throws CoreException, OperationCanceledException {
+ // 10 monitor steps to go
+
+ // create and set the output path first
+ if (!fWorkspaceRoot.exists(outputLocation)) {
+ IFolder folder= fWorkspaceRoot.getFolder(outputLocation);
+ CoreUtility.createFolder(folder, true, true, null);
+ folder.setDerived(true);
+ }
+
+
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ monitor.worked(2);
+
+ int nEntries= classPathEntries.size();
+ IClasspathEntry[] classpath= new IClasspathEntry[nEntries];
+
+ // create and set the class path
+ for (int i= 0; i < nEntries; i++) {
+ CPListElement entry= ((CPListElement)classPathEntries.get(i));
+ IResource res= entry.getResource();
+ if ((res instanceof IFolder) && !res.exists()) {
+ CoreUtility.createFolder((IFolder)res, true, true, null);
+ }
+ if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ IPath folderOutput= (IPath) entry.getAttribute(CPListElement.OUTPUT);
+ if (folderOutput != null && folderOutput.segmentCount() > 1) {
+ IFolder folder= fWorkspaceRoot.getFolder(folderOutput);
+ CoreUtility.createFolder(folder, true, true, null);
+ }
+ }
+
+ classpath[i]= entry.getClasspathEntry();
+ }
+
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ monitor.worked(1);
+
+ fCurrJProject.setRawClasspath(classpath, outputLocation, new SubProgressMonitor(monitor, 7));
+ initializeTimeStamps();
+ }
+
+ public static boolean hasClassfiles(IResource resource) throws CoreException {
+ if (resource.isDerived()) { //$NON-NLS-1$
+ return true;
+ }
+ if (resource instanceof IContainer) {
+ IResource[] members= ((IContainer) resource).members();
+ for (int i= 0; i < members.length; i++) {
+ if (hasClassfiles(members[i])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ public static void removeOldClassfiles(IResource resource) throws CoreException {
+ if (resource.isDerived()) {
+ resource.delete(false, null);
+ } else if (resource instanceof IContainer) {
+ IResource[] members= ((IContainer) resource).members();
+ for (int i= 0; i < members.length; i++) {
+ removeOldClassfiles(members[i]);
+ }
+ }
+ }
+
+ public static IRemoveOldBinariesQuery getRemoveOldBinariesQuery(final Shell shell) {
+ return new IRemoveOldBinariesQuery() {
+ public boolean doQuery(final IPath oldOutputLocation) throws OperationCanceledException {
+ final int[] res= new int[] { 1 };
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
+ String title= NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_title;
+ String message= Messages.format(NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_description, oldOutputLocation.toString());
+ MessageDialog dialog= new MessageDialog(sh, title, null, message, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
+ res[0]= dialog.open();
+ }
+ });
+ if (res[0] == 0) {
+ return true;
+ } else if (res[0] == 1) {
+ return false;
+ }
+ throw new OperationCanceledException();
+ }
+ };
+ }
+
+
+ // ---------- util method ------------
+
+ private IContainer chooseContainer() {
+ Class[] acceptedClasses= new Class[] { IProject.class, IFolder.class };
+ ISelectionStatusValidator validator= new TypedElementSelectionValidator(acceptedClasses, false);
+ IProject[] allProjects= fWorkspaceRoot.getProjects();
+ ArrayList rejectedElements= new ArrayList(allProjects.length);
+ IProject currProject= fCurrJProject.getProject();
+ for (int i= 0; i < allProjects.length; i++) {
+ if (!allProjects[i].equals(currProject)) {
+ rejectedElements.add(allProjects[i]);
+ }
+ }
+ ViewerFilter filter= new TypedViewerFilter(acceptedClasses, rejectedElements.toArray());
+
+ ILabelProvider lp= new WorkbenchLabelProvider();
+ ITreeContentProvider cp= new WorkbenchContentProvider();
+
+ IResource initSelection= null;
+ if (fOutputLocationPath != null) {
+ initSelection= fWorkspaceRoot.findMember(fOutputLocationPath);
+ }
+
+ FolderSelectionDialog dialog= new FolderSelectionDialog(getShell(), lp, cp);
+ dialog.setTitle(NewWizardMessages.BuildPathsBlock_ChooseOutputFolderDialog_title);
+ dialog.setValidator(validator);
+ dialog.setMessage(NewWizardMessages.BuildPathsBlock_ChooseOutputFolderDialog_description);
+ dialog.addFilter(filter);
+ dialog.setInput(fWorkspaceRoot);
+ dialog.setInitialSelection(initSelection);
+ dialog.setSorter(new ResourceSorter(ResourceSorter.NAME));
+
+ if (dialog.open() == Window.OK) {
+ return (IContainer)dialog.getFirstResult();
+ }
+ return null;
+ }
+
+ // -------- tab switching ----------
+
+ private void tabChanged(Widget widget) {
+ if (widget instanceof TabItem) {
+ TabItem tabItem= (TabItem) widget;
+ BuildPathBasePage newPage= (BuildPathBasePage) tabItem.getData();
+ if (fCurrPage != null) {
+ List selection= fCurrPage.getSelection();
+ if (!selection.isEmpty()) {
+ newPage.setSelection(selection, false);
+ }
+ }
+ fCurrPage= newPage;
+ fPageIndex= tabItem.getParent().getSelectionIndex();
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/JavaCapabilityConfigurationPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/JavaCapabilityConfigurationPage.java
new file mode 100644
index 0000000..dfb9bab
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/JavaCapabilityConfigurationPage.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.ui.wizards.NewElementWizardPage;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Copied from same in org.eclipse.jdt.ui.wizards. Only change is to use
+ * BuildPathsBlock in this package.
+ */
+public class JavaCapabilityConfigurationPage extends NewElementWizardPage {
+
+ private static final String PAGE_NAME= "JavaCapabilityConfigurationPage"; //$NON-NLS-1$
+
+ private IJavaProject fJavaProject;
+ private BuildPathsBlock fBuildPathsBlock;
+
+ /**
+ * Creates a wizard page that can be used in a Java project creation wizard.
+ * It contains UI to configure a the classpath and the output folder.
+ *
+ * <p>
+ * After constructing, a call to <code>init</code> is required.
+ * </p>
+ */
+ public JavaCapabilityConfigurationPage() {
+ super(PAGE_NAME);
+ fJavaProject= null;
+
+ setTitle(NewWizardMessages.JavaCapabilityConfigurationPage_title);
+ setDescription(NewWizardMessages.JavaCapabilityConfigurationPage_description);
+ }
+
+ private BuildPathsBlock getBuildPathsBlock() {
+ if (fBuildPathsBlock == null) {
+ IStatusChangeListener listener= new IStatusChangeListener() {
+ public void statusChanged(IStatus status) {
+ updateStatus(status);
+ }
+ };
+ fBuildPathsBlock= new BuildPathsBlock(new BusyIndicatorRunnableContext(), listener, 0, useNewSourcePage(), null);
+ }
+ return fBuildPathsBlock;
+ }
+
+ /**
+ * Clients can override this method to choose if the new source page is used. The new source page
+ * requires that the project is already created as Java project. The page will directly manipulate the classpath.
+ * By default <code>false</code> is returned.
+ * @return Returns <code>true</code> if the new source page should be used.
+ * @since 3.1
+ */
+ protected boolean useNewSourcePage() {
+ return false;
+ }
+
+ /**
+ * Initializes the page with the project and default classpaths.
+ * <p>
+ * The default classpath entries must correspond the the given project.
+ * </p>
+ * <p>
+ * The caller of this method is responsible for creating the underlying project. The page will create the output,
+ * source and library folders if required.
+ * </p>
+ * <p>
+ * The project does not have to exist at the time of initialization, but must exist when executing the runnable
+ * obtained by <code>getRunnable()</code>.
+ * </p>
+ * @param jproject The Java project.
+ * @param defaultOutputLocation The default classpath entries or <code>null</code> to let the page choose the default
+ * @param defaultEntries The folder to be taken as the default output path or <code>null</code> to let the page choose the default
+ * @param defaultsOverrideExistingClasspath If set to <code>true</code>, an existing '.classpath' file is ignored. If set to <code>false</code>
+ * the given default classpath and output location is only used if no '.classpath' exists.
+ */
+ public void init(IJavaProject jproject, IPath defaultOutputLocation, IClasspathEntry[] defaultEntries, boolean defaultsOverrideExistingClasspath) {
+ if (!defaultsOverrideExistingClasspath && jproject.exists() && jproject.getProject().getFile(".classpath").exists()) { //$NON-NLS-1$
+ defaultOutputLocation= null;
+ defaultEntries= null;
+ }
+ getBuildPathsBlock().init(jproject, defaultOutputLocation, defaultEntries);
+ fJavaProject= jproject;
+ }
+
+ /* (non-Javadoc)
+ * @see WizardPage#createControl
+ */
+ public void createControl(Composite parent) {
+ Composite composite= new Composite(parent, SWT.NONE);
+ composite.setFont(parent.getFont());
+ composite.setLayout(new GridLayout(1, false));
+ Control control= getBuildPathsBlock().createControl(composite);
+ control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ Dialog.applyDialogFont(composite);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.NEW_JAVAPROJECT_WIZARD_PAGE);
+ setControl(composite);
+ }
+
+ /**
+ * Returns the currently configured output location. Note that the returned path
+ * might not be a valid path.
+ *
+ * @return the currently configured output location
+ */
+ public IPath getOutputLocation() {
+ return getBuildPathsBlock().getOutputLocation();
+ }
+
+ /**
+ * Returns the currently configured classpath. Note that the classpath might
+ * not be valid.
+ *
+ * @return the currently configured classpath
+ */
+ public IClasspathEntry[] getRawClassPath() {
+ return getBuildPathsBlock().getRawClassPath();
+ }
+
+ /**
+ * Returns the Java project that was passed in <code>init</code> or <code>null</code> if the
+ * page has not been initialized yet.
+ *
+ * @return the managed Java project or <code>null</code>
+ */
+ public IJavaProject getJavaProject() {
+ return fJavaProject;
+ }
+
+
+ /**
+ * Returns the runnable that will create the Java project or <code>null</code> if the page has
+ * not been initialized. The runnable sets the project's classpath and output location to the values
+ * configured in the page and adds the Java nature if not set yet. The method requires that the
+ * project is created and opened.
+ *
+ * @return the runnable that creates the new Java project
+ */
+ public IRunnableWithProgress getRunnable() {
+ if (getJavaProject() != null) {
+ return new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ try {
+ configureJavaProject(monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+ };
+ }
+ return null;
+ }
+
+ /**
+ * Helper method to create and open a IProject . The project location
+ * is configured. No natures are added.
+ *
+ * @param project The handle of the project to create.
+ * @param locationPath The location of the project.
+ * @param monitor a progress monitor to report progress or <code>null</code> if
+ * progress reporting is not desired
+ * @throws CoreException
+ * @since 2.1
+ */
+ public static void createProject(IProject project, IPath locationPath, IProgressMonitor monitor) throws CoreException {
+ BuildPathsBlock.createProject(project, locationPath, monitor);
+ }
+
+ /**
+ * Adds the Java nature to the project (if not set yet) and configures the build classpath.
+ *
+ * @param monitor a progress monitor to report progress or <code>null</code> if
+ * progress reporting is not desired
+ * @throws CoreException Thrown when the configuring the Java project failed.
+ * @throws InterruptedException Thrown when the operation has been cancelled.
+ */
+ public void configureJavaProject(IProgressMonitor monitor) throws CoreException, InterruptedException {
+ if (monitor == null) {
+ monitor= new NullProgressMonitor();
+ }
+
+ int nSteps= 6;
+ monitor.beginTask(NewWizardMessages.JavaCapabilityConfigurationPage_op_desc_java, nSteps);
+
+ try {
+ IProject project= getJavaProject().getProject();
+ BuildPathsBlock.addJavaNature(project, new SubProgressMonitor(monitor, 1));
+ getBuildPathsBlock().configureJavaProject(new SubProgressMonitor(monitor, 5));
+ } catch (OperationCanceledException e) {
+ throw new InterruptedException();
+ } finally {
+ monitor.done();
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationCreationPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationCreationPage.java
new file mode 100755
index 0000000..b299f35
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationCreationPage.java
@@ -0,0 +1,212 @@
+/**********************************************************************
+Copyright (c) 2002, 2005 IBM Corporation and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+Contributors:
+Adrian Colyer, Andy Clement, Tracy Gardner - initial version
+Sian January - updated for new style build configurations
+...
+**********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.wizards;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.dialogs.WizardNewFileCreationPage;
+import org.eclipse.ui.ide.IDE;
+
+/**
+ * This class is the only page of the ".lst" file resource creation wizard.
+ * It subclasses the standard file resource creation page class,
+ * and consequently inherits the file resource creation functionality.
+ */
+public class BuildConfigurationCreationPage extends WizardNewFileCreationPage {
+ private IWorkbench workbench;
+
+ // widgets
+ private Button openFileCheckbox;
+ private Button makeActiveCheckbox;
+
+ // constants
+
+ private IStructuredSelection selection;
+
+
+ /**
+ * Creates the page for the build configuration file creation wizard.
+ *
+ * @param workbench the workbench on which the page should be created
+ * @param selection the current selection
+ */
+ public BuildConfigurationCreationPage(
+ IWorkbench workbench,
+ IStructuredSelection selection) {
+ super("CreateBuildConfigurationFilePage1", selection); //$NON-NLS-1$
+ this.setTitle(UIMessages.BuildConfig_createLstFile);
+ this.setDescription(UIMessages.BuildConfig_createLstDesc);
+ this.workbench = workbench;
+ this.selection = selection;
+ }
+
+ /**
+ * Build the GUI representation of the page.
+ */
+ public void createControl(Composite parent) {
+ // inherit default container and name specification widgets
+ super.createControl(parent);
+ Composite composite = (Composite) getControl();
+
+ //ASCFIXME: Add help!
+ //WorkbenchHelp.setHelp(composite, new String[] {IReadmeConstants.CREATION_WIZARD_PAGE_CONTEXT});
+
+ this.setFileName(getFreeFileName() + "." + IBuildConfiguration.EXTENSION); //$NON-NLS-1$
+
+ // open file for editing checkbox
+ openFileCheckbox = new Button(composite, SWT.CHECK);
+ openFileCheckbox.setText(UIMessages.BuildConfig_openForEdit);
+ openFileCheckbox.setSelection(true);
+
+ makeActiveCheckbox = new Button(composite, SWT.CHECK);
+ makeActiveCheckbox.setText(UIMessages.BuildConfig_activate);
+ makeActiveCheckbox.setSelection(true);
+
+ setPageComplete(validatePage());
+
+ }
+
+ /**
+ * Get a suitable and unused filename (without file extension)
+ * @return
+ */
+ private String getFreeFileName() {
+ IProject project = null;
+ if(selection.size() > 0) {
+ Object element = selection.getFirstElement();
+ if(element instanceof IResource) {
+ project = ((IResource)element).getProject();
+ } else if (element instanceof IJavaElement) {
+ project = ((IJavaElement)element).getJavaProject().getProject();
+ }
+ }
+ return BuildConfigurator.getFreeFileName(project);
+ }
+
+ /*
+ * Override because linking to a file in the file system doesn't make a lot
+ * of sense in this case
+ */
+ protected void createAdvancedControls(Composite parent){}
+
+ /*
+ * Override because we overrode createAdvancedControls(..)
+ */
+ protected IStatus validateLinkedResource() {
+ return new Status(IStatus.OK, AspectJUIPlugin.PLUGIN_ID, IStatus.OK, "", null); //$NON-NLS-1$
+ }
+
+ /*
+ * Override because we overrode createAdvancedControls(..)
+ */
+ protected void createLinkTarget() {}
+
+ /**
+ * Creates a new file resource as requested by the user. If everything
+ * is OK then answer true. If not, false will cause the dialog
+ * to stay open.
+ *
+ * @return whether creation was successful
+ * @see ReadmeCreationWizard#performFinish()
+ */
+ public boolean finish() {
+ // create the new file resource
+
+ IFile newFile = createNewFile();
+
+
+ if (newFile == null)
+ return false; // ie.- creation was unsuccessful
+
+ // Since the file resource was created fine, open it for editing
+ // if requested by the user
+ IProject project = newFile.getProject();
+ IProjectBuildConfigurator pbc = DefaultBuildConfigurator.getBuildConfigurator().getProjectBuildConfigurator(project);
+ new BuildConfiguration(newFile, pbc, makeActiveCheckbox.getSelection());
+ try {
+ if (openFileCheckbox.getSelection()) {
+ IWorkbenchWindow dwindow = workbench.getActiveWorkbenchWindow();
+ IWorkbenchPage page = dwindow.getActivePage();
+ if (page != null) IDE.openEditor(page,newFile,true);
+ }
+ } catch (PartInitException e) {
+ return false;
+ }
+ AJLog.log("New config file created: " + newFile.getName()); //$NON-NLS-1$
+ return true;
+ }
+
+
+ /**
+ * Validate the page
+ */
+ protected boolean validatePage() {
+ if(super.validatePage()) {
+ if(!isProjectSelected()) {
+ setErrorMessage(UIMessages.BuildConfig_needToSelectProject);
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Test to see whether the selected parent is a project
+ * @return
+ */
+ private boolean isProjectSelected() {
+ IPath containerPath = getContainerFullPath();
+ IProject[] projects = AspectJPlugin.getWorkspace().getRoot().getProjects();
+ for (int i = 0; i < projects.length; i++) {
+ IProject project = projects[i];
+ IPath path = project.getFullPath();
+ if(path.equals(containerPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** (non-Javadoc)
+ * Method declared on WizardNewFileCreationPage.
+ */
+ protected String getNewFileLabel() {
+ return UIMessages.BuildConfig_newBCFile;
+ }
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationFileWizard.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationFileWizard.java
new file mode 100755
index 0000000..eefc265
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationFileWizard.java
@@ -0,0 +1,77 @@
+/**********************************************************************
+Copyright (c) 2002 IBM Corporation and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+Contributors:
+Adrian Colyer, Andy Clement, Tracy Gardner - initial version
+...
+**********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.wizards;
+
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * This class implements the interface required by the desktop
+ * for all 'New' wizards. This wizard creates Aspect#J Build
+ * configuration files.
+ */
+public class BuildConfigurationFileWizard
+ extends Wizard
+ implements INewWizard {
+ protected IStructuredSelection selection;
+ protected IWorkbench workbench;
+ private BuildConfigurationCreationPage mainPage;
+
+ /**
+ * Adds the BuildConfigurationCreationPage
+ */
+ public void addPages() {
+ mainPage = new BuildConfigurationCreationPage(workbench, selection);
+ addPage(mainPage);
+ }
+
+ /**
+ * Set-up the title and icon.
+ */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.workbench = workbench;
+ if(selection instanceof StructuredSelection) {
+ if(((StructuredSelection)selection).size() > 0) {
+ Object firstObject = ((StructuredSelection)selection).getFirstElement();
+ if(firstObject instanceof IResource) {
+ IProject project = ((IResource)firstObject).getProject();
+ StructuredSelection newSelection = new StructuredSelection(project);
+ this.selection = newSelection;
+ } else if(firstObject instanceof IJavaElement) {
+ IJavaProject project = ((IJavaElement)firstObject).getJavaProject();
+ StructuredSelection newSelection = new StructuredSelection(project);
+ this.selection = newSelection;
+ }
+ }
+ }
+ if(this.selection == null) {
+ this.selection = selection;
+ }
+ setWindowTitle(UIMessages.newConfig);
+ //setDefaultPageImageDescriptor( AspectJImages.getImageDescriptor( AspectJImages.FILE_LST ) );
+ }
+
+
+ /**
+ * Complete generation of the build configuration file.
+ */
+ public boolean performFinish() {
+ return mainPage.finish();
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/EmptyOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/EmptyOutlinePage.java
new file mode 100755
index 0000000..2c2a4e5
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/EmptyOutlinePage.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Jan 28, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.IActionBars;
+
+
+public class EmptyOutlinePage implements ISortableContentOutlinePage {
+ private Composite control;
+ /**
+ *
+ */
+ public EmptyOutlinePage() {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ control = new Composite(parent, SWT.NULL);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.IPage#dispose()
+ */
+ public void dispose() {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.IPage#getControl()
+ */
+ public Control getControl() {
+ return control;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.IPage#setActionBars(org.eclipse.ui.IActionBars)
+ */
+ public void setActionBars(IActionBars actionBars) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.IPage#setFocus()
+ */
+ public void setFocus() {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+ */
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
+ */
+ public ISelection getSelection() {
+ return new ISelection() {
+ public boolean isEmpty() { return true; }
+ };
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+ */
+ public void removeSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
+ */
+ public void setSelection(ISelection selection) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.editor.ISortable#sort(boolean)
+ */
+ public void sort(boolean sorting) {
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormEntryAdapter.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormEntryAdapter.java
new file mode 100644
index 0000000..3c0e64e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormEntryAdapter.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Feb 27, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.ui.*;
+import org.eclipse.ui.forms.events.*;
+
+public class FormEntryAdapter implements IFormEntryListener {
+ private IContextPart contextPart;
+ protected IActionBars actionBars;
+
+ public FormEntryAdapter(IContextPart contextPart) {
+ this(contextPart, null);
+ }
+ public FormEntryAdapter(IContextPart contextPart, IActionBars actionBars) {
+ this.contextPart = contextPart;
+ this.actionBars = actionBars;
+ }
+ public void focusGained(FormEntry entry) {
+ ITextSelection selection = new TextSelection(1,1);
+ contextPart.getPage().getPDEEditor().getContributor().updateSelectableActions(selection);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.newparts.IFormEntryListener#textDirty(org.eclipse.pde.internal.ui.newparts.FormEntry)
+ */
+ public void textDirty(FormEntry entry) {
+ contextPart.fireSaveNeeded();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.newparts.IFormEntryListener#textValueChanged(org.eclipse.pde.internal.ui.newparts.FormEntry)
+ */
+ public void textValueChanged(FormEntry entry) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.newparts.IFormEntryListener#browseButtonSelected(org.eclipse.pde.internal.ui.newparts.FormEntry)
+ */
+ public void browseButtonSelected(FormEntry entry) {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.events.HyperlinkListener#linkEntered(org.eclipse.ui.forms.events.HyperlinkEvent)
+ */
+ public void linkEntered(HyperlinkEvent e) {
+ if (actionBars==null) return;
+ IStatusLineManager mng = actionBars.getStatusLineManager();
+ mng.setMessage(e.getLabel());
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.events.HyperlinkListener#linkExited(org.eclipse.ui.forms.events.HyperlinkEvent)
+ */
+ public void linkExited(HyperlinkEvent e) {
+ if (actionBars==null) return;
+ IStatusLineManager mng = actionBars.getStatusLineManager();
+ mng.setMessage(null);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.events.HyperlinkListener#linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent)
+ */
+ public void linkActivated(HyperlinkEvent e) {
+ }
+ public void selectionChanged(FormEntry entry) {
+ ITextSelection selection = new TextSelection(1,1);
+ contextPart.getPage().getPDEEditor().getContributor().updateSelectableActions(selection);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormOutlinePage.java
new file mode 100755
index 0000000..4f59255
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormOutlinePage.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.util.ArrayList;
+
+import org.eclipse.jface.viewers.*;
+import org.eclipse.pde.core.*;
+import org.eclipse.pde.internal.core.plugin.ImportObject;
+import org.eclipse.pde.internal.core.text.IDocumentNode;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+public class FormOutlinePage extends ContentOutlinePage
+ implements
+ IModelChangedListener, ISortableContentOutlinePage {
+ private boolean stale;
+ private ViewerSorter fViewerSorter;
+ private boolean sorted;
+ public class BasicContentProvider extends DefaultContentProvider
+ implements
+ ITreeContentProvider {
+ public Object[] getElements(Object obj) {
+ return getPages();
+ }
+ public Object[] getChildren(Object obj) {
+ return FormOutlinePage.this.getChildren(obj);
+ }
+ public boolean hasChildren(Object obj) {
+ return getChildren(obj).length > 0;
+ }
+ public Object getParent(Object obj) {
+ return null;
+ }
+ }
+ public class BasicLabelProvider extends LabelProvider {
+ public String getText(Object obj) {
+ if (obj instanceof IFormPage)
+ return ((IFormPage)obj).getTitle();
+ return PDEPlugin.getDefault().getLabelProvider().getText(obj);
+ }
+ public Image getImage(Object obj) {
+ if (obj instanceof IFormPage)
+ return PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_PAGE_OBJ);
+ return PDEPlugin.getDefault().getLabelProvider().getImage(obj);
+ }
+ }
+ public class BasicSorter extends ViewerSorter {
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ViewerSorter#category(java.lang.Object)
+ */
+ public int category(Object element) {
+ Object[] pages = getPages();
+ for(int i=0; i<pages.length; i++){
+ if(pages[i]==element){
+ return i;
+ }
+ }
+ return Integer.MAX_VALUE;
+ }
+ }
+ protected TreeViewer treeViewer;
+ protected PDEFormEditor editor;
+ protected boolean editorSelection = false;
+ protected boolean outlineSelection = false;
+ public FormOutlinePage(PDEFormEditor editor) {
+ this.editor = editor;
+ }
+ protected ITreeContentProvider createContentProvider() {
+ return new BasicContentProvider();
+ }
+ protected ViewerSorter createOutlineSorter(){
+ fViewerSorter = new BasicSorter();
+ return fViewerSorter;
+ }
+ public void createControl(Composite parent) {
+ Tree widget = new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ treeViewer = new TreeViewer(widget);
+ treeViewer.addSelectionChangedListener(this);
+ treeViewer.setContentProvider(createContentProvider());
+ treeViewer.setLabelProvider(createLabelProvider());
+ createOutlineSorter();
+ if(sorted)
+ treeViewer.setSorter(fViewerSorter);
+ else
+ treeViewer.setSorter(null);
+ treeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
+ treeViewer.setUseHashlookup(true);
+ treeViewer.setInput(editor);
+ IBaseModel model = editor.getAggregateModel();
+ if (model instanceof IModelChangeProvider)
+ ((IModelChangeProvider)model).addModelChangedListener(this);
+ }
+ protected ILabelProvider createLabelProvider() {
+ return new BasicLabelProvider();
+ }
+ public void dispose() {
+ IBaseModel model = editor.getAggregateModel();
+ if (model instanceof IModelChangeProvider)
+ ((IModelChangeProvider)model).removeModelChangedListener(this);
+ super.dispose();
+ }
+
+ public Control getControl() {
+ return treeViewer != null ? treeViewer.getControl() : null;
+ }
+ private Object[] getPages() {
+ ArrayList formPages = new ArrayList();
+ IFormPage [] pages = editor.getPages();
+ for (int i=0; i<pages.length; i++) {
+ if (pages[i].isEditor()==false)
+ formPages.add(pages[i]);
+ }
+ return formPages.toArray();
+ }
+
+ public void modelChanged(IModelChangedEvent event) {
+ IFormPage page = editor.getActivePageInstance();
+ stale=true;
+ if (page.isEditor()==false)
+ refresh();
+ }
+
+ public void refresh() {
+ if (stale) {
+ treeViewer.refresh();
+ treeViewer.expandAll();
+ stale=false;
+ }
+ }
+
+ protected String getParentPageId(Object item) {
+ if (item instanceof IFormPage)
+ return ((IFormPage)item).getId();
+ return null;
+ }
+
+ protected Object[] getChildren(Object parent) {
+ return new Object[0];
+ }
+
+ public void selectionChanged(Object item) {
+ IFormPage page = editor.getActivePageInstance();
+ String id = getParentPageId(item);
+ IFormPage newPage=null;
+ if (id!=null && (page==null || !page.getId().equals(id)))
+ newPage = editor.setActivePage(id);
+ IFormPage revealPage = newPage!=null?newPage:page;
+ if (revealPage!=null && !(item instanceof IFormPage))
+ revealPage.selectReveal(item);
+ }
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (editorSelection)
+ return;
+ outlineSelection = true;
+ try {
+ ISelection selection = event.getSelection();
+ if (selection.isEmpty() == false
+ && selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ Object item = ssel.getFirstElement();
+ selectionChanged(item);
+ }
+ fireSelectionChanged(selection);
+ } finally {
+ outlineSelection = false;
+ }
+ }
+ public void setFocus() {
+ if (treeViewer != null)
+ treeViewer.getTree().setFocus();
+ }
+ public ISelection getSelection() {
+ if (treeViewer == null)
+ return StructuredSelection.EMPTY;
+ return treeViewer.getSelection();
+ }
+ public void sort (boolean sorting){
+ sorted = sorting;
+ if(treeViewer!=null)
+ if(sorting)
+ treeViewer.setSorter(fViewerSorter);
+ else
+ treeViewer.setSorter(null);
+ }
+ /*
+ * (non-Javadoc) Method declared on ISelectionProvider.
+ */
+ public void setSelection(ISelection selection) {
+ if (outlineSelection)
+ return;
+ editorSelection = true;
+ try {
+ if (treeViewer == null)
+ return;
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+ Object item = ((IStructuredSelection) selection)
+ .getFirstElement();
+ if (item instanceof ImportObject) {
+ selection = new StructuredSelection(((ImportObject) item)
+ .getImport());
+ }
+ if (item instanceof IDocumentNode) {
+ while (null == treeViewer.testFindItem(item)) {
+ item = ((IDocumentNode) item).getParentNode();
+ if (item == null) {
+ break;
+ }
+ selection = new StructuredSelection(item);
+ }
+ }
+ }
+ treeViewer.setSelection(selection);
+ } finally {
+ editorSelection = false;
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/GenericSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/GenericSourcePage.java
new file mode 100755
index 0000000..cc61cc1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/GenericSourcePage.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.*;
+
+/**
+ *
+ */
+public class GenericSourcePage extends PDESourcePage {
+ /**
+ * @param editor
+ * @param id
+ * @param title
+ */
+ public GenericSourcePage(PDEFormEditor editor, String id, String title) {
+ super(editor, id, title);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createOutlineLabelProvider()
+ */
+ protected ILabelProvider createOutlineLabelProvider() {
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createOutlineContentProvider()
+ */
+ protected ITreeContentProvider createOutlineContentProvider() {
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createOutlineContentProvider()
+ */
+ protected ViewerSorter createOutlineSorter() {
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#outlineSelectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+ */
+ protected void outlineSelectionChanged(SelectionChangedEvent e) {
+ }
+ protected ISortableContentOutlinePage createOutlinePage() {
+ return null;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IContextPart.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IContextPart.java
new file mode 100755
index 0000000..0f94e46
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IContextPart.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.pde.core.IModelChangedListener;
+
+public interface IContextPart extends IModelChangedListener {
+ boolean isEditable();
+ PDEFormPage getPage();
+ String getContextId();
+ void fireSaveNeeded();
+ void cancelEdit();
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IModelUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IModelUndoManager.java
new file mode 100755
index 0000000..e7a87c2
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IModelUndoManager.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.pde.core.IModelChangeProvider;
+
+/**
+ * Classes that implement this interface provide undo/redo
+ * capability linked to changes reported by model change
+ * providers. Model change events carry sufficient data
+ * to be used in an undo/redo stack and reverted to or
+ * reapplied after the change.
+ * <p>Model undo manager adds itself as a change listener
+ * after being connected to the provider. It is expected
+ * to stop listening to change events after being disconnected.
+ * Changes reported while being connected are kept in the
+ * operation stack whose size can be controlled.
+ * <p>The part that uses the undo manager is responsible
+ * for supplying Undo and Redo action objects for
+ * the purpose of controlling their availability.
+ * Undo manager should keep track of its current
+ * operation stack pointer and adjust Undo/Redo action
+ * availability by calling 'setEnabled' on the
+ * provided action objects. Implementation of this
+ * interface may also opt to modify Undo/Redo action
+ * labels in order to better indicate the effect
+ * of the operations if selected (for example,
+ * 'Undo Delete' instead of 'Undo').
+ */
+public interface IModelUndoManager {
+ /**
+ * Connects to the change provider. Until disconnecting,
+ * the manager will keep model changes in the operation
+ * stack and will be able to revert or reapply these
+ * changes in the source model.
+ * @param provider the model change provider to connect to
+ */
+ public void connect(IModelChangeProvider provider);
+ /**
+ * Disconnects from the change provider. Upon disconnecting,
+ * the manager will no longer be able to revert or reapply
+ * changes in the source model.
+ * @param provider the model change provider to disconnect from
+ */
+ public void disconnect(IModelChangeProvider provider);
+ /**
+ * Tests whether the current operation in the undo stack can
+ * be reverted.
+ * @return true if the current operation can be undone.
+ */
+ public boolean isUndoable();
+ /**
+ * Tests whether the current operation in the undo stack can
+ * be reapplied.
+ * @return true if the current operation can be redone.
+ */
+ public boolean isRedoable();
+ /**
+ * Reverts the current operation in the undo stack and decrements
+ * the stack pointer.
+ */
+ public void undo();
+ /**
+ * Reapplies the next operation in the undo stack and sets
+ * the stack pointer to that operation.
+ *
+ */
+ public void redo();
+ /**
+ * Sets the depth of the undo stack.
+ * @param limit number of levels in the undo stack.
+ */
+ public void setUndoLevelLimit(int limit);
+ /**
+ * Temporarily suspends undo manager.
+ * @param ignore if true, model changes reported by the
+ * model change provider will be ignore until this
+ * property is set to <samp>false</samp> again.
+ */
+ public void setIgnoreChanges(boolean ignore);
+ /**
+ * Connects the undo manager with the undo and redo actions
+ * in the workbench part using the manager. The manager
+ * uses these objects to enable or disable the actions
+ * according to the state of the undo stack and the current
+ * location of the stack pointer.
+ * @param undoAction the action in the workbench part that performs
+ * the undo operation.
+ * @param redoAction the action in the workbench part that performs
+ * the redo operation.
+ */
+ public void setActions(IAction undoAction, IAction redoAction);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ISortableContentOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ISortableContentOutlinePage.java
new file mode 100755
index 0000000..5c73170
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ISortableContentOutlinePage.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * IConentOutlinePage with externally enabled/disabled element sorting
+ */
+public interface ISortableContentOutlinePage extends IContentOutlinePage {
+ /**
+ * Turns sorting on or off
+ * @param sorting - boolean value indicating if sorting should be enabled
+ */
+ public void sort(boolean sorting);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryEditorInput.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryEditorInput.java
new file mode 100644
index 0000000..d0cb27f
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryEditorInput.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+
+import java.io.*;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.*;
+
+
+/**
+ * An EditorInput for a JarEntryFile.
+ */
+public class JarEntryEditorInput implements IStorageEditorInput {
+
+ private IStorage fJarEntryFile;
+
+ public JarEntryEditorInput(IStorage jarEntryFile) {
+ fJarEntryFile= jarEntryFile;
+ }
+
+ /*
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof JarEntryEditorInput))
+ return false;
+ JarEntryEditorInput other= (JarEntryEditorInput) obj;
+ return fJarEntryFile.equals(other.fJarEntryFile);
+ }
+
+ /*
+ * @see IEditorInput#getPersistable()
+ */
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ /*
+ * @see IEditorInput#getName()
+ */
+ public String getName() {
+ return fJarEntryFile.getName();
+ }
+
+ /*
+ * @see IEditorInput#getFullPath()
+ */
+ public String getFullPath() {
+ return fJarEntryFile.getFullPath().toString();
+ }
+
+ /*
+ * @see IEditorInput#getContentType()
+ */
+ public String getContentType() {
+ return fJarEntryFile.getFullPath().getFileExtension();
+ }
+
+ /*
+ * @see IEditorInput#getToolTipText()
+ */
+ public String getToolTipText() {
+ return fJarEntryFile.getFullPath().toString();
+ }
+
+ /*
+ * @see IEditorInput#getImageDescriptor()
+ */
+ public ImageDescriptor getImageDescriptor() {
+ IEditorRegistry registry= PlatformUI.getWorkbench().getEditorRegistry();
+ return registry.getImageDescriptor(fJarEntryFile.getFullPath().getFileExtension());
+ }
+
+ /*
+ * @see IEditorInput#exists()
+ */
+ public boolean exists() {
+ // JAR entries can't be deleted
+ return true;
+ }
+
+ /*
+ * @see IAdaptable#getAdapter(Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter.equals(File.class))
+ return fJarEntryFile.getAdapter(File.class);
+ return null;
+ }
+
+ /*
+ * see IStorageEditorInput#getStorage()
+ */
+ public IStorage getStorage() {
+ return fJarEntryFile;
+ }
+}
+
+
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryFile.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryFile.java
new file mode 100644
index 0000000..14b4abb
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryFile.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import java.util.zip.*;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.internal.ui.*;
+
+
+public class JarEntryFile extends PlatformObject implements IStorage {
+
+ private ZipFile fZipFile;
+ private String fEntryName;
+
+ public JarEntryFile(ZipFile zipFile, String entryName) {
+ fZipFile = zipFile;
+ fEntryName = entryName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IStorage#getContents()
+ */
+ public InputStream getContents() throws CoreException {
+ try {
+ ZipEntry zipEntry = fZipFile.getEntry(fEntryName);
+ return fZipFile.getInputStream(zipEntry);
+ } catch (Exception e){
+ throw new CoreException(new Status(IStatus.ERROR, PDEPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IStorage#getFullPath()
+ */
+ public IPath getFullPath() {
+ return new Path(fEntryName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IStorage#getName()
+ */
+ public String getName() {
+ return getFullPath().lastSegment();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IStorage#isReadOnly()
+ */
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter.equals(ZipFile.class))
+ return fZipFile;
+ if (adapter.equals(File.class))
+ return new File(fZipFile.getName());
+ return super.getAdapter(adapter);
+ }
+
+ public String toString() {
+ return "JarEntryFile["+ fZipFile.getName() + "::" + fEntryName + "]"; //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JarEntryFile))
+ return false;
+ return toString().equals(obj.toString());
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/KeyValueSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/KeyValueSourcePage.java
new file mode 100755
index 0000000..1480f5b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/KeyValueSourcePage.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.pde.internal.core.util.PropertiesUtil;
+import org.eclipse.pde.internal.ui.editor.text.AnnotationHover;
+import org.eclipse.pde.internal.ui.editor.text.ReconcilingStrategy;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+
+public abstract class KeyValueSourcePage extends PDESourcePage {
+
+ class KeyValueSourceViewerConfiguration extends TextSourceViewerConfiguration {
+ private AnnotationHover fAnnotationHover;
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ ReconcilingStrategy strategy = new ReconcilingStrategy();
+ strategy.addParticipant((IReconcilingParticipant) getInputContext()
+ .getModel());
+ strategy.addParticipant((SourceOutlinePage)getContentOutline());
+ MonoReconciler reconciler = new MonoReconciler(strategy, false);
+ reconciler.setDelay(500);
+ return reconciler;
+ }
+ public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+ if (fAnnotationHover == null)
+ fAnnotationHover = new AnnotationHover();
+ return fAnnotationHover;
+ }
+ }
+ public KeyValueSourcePage(PDEFormEditor editor, String id, String title) {
+ super(editor, id, title);
+ setSourceViewerConfiguration(new KeyValueSourceViewerConfiguration());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createViewerSorter()
+ */
+ protected ViewerSorter createDefaultOutlineSorter() {
+ return new ViewerSorter() {
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ IDocumentKey key1 = (IDocumentKey)e1;
+ IDocumentKey key2 = (IDocumentKey)e2;
+ return key1.getOffset() < key2.getOffset() ? -1 : 1;
+ }
+ };
+ }
+
+ protected void outlineSelectionChanged(SelectionChangedEvent event) {
+ ISelection selection= event.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection= (IStructuredSelection) selection;
+ Object first= structuredSelection.getFirstElement();
+ if (first instanceof IDocumentKey) {
+ setHighlightRange((IDocumentKey)first);
+ } else {
+ resetHighlightRange();
+ }
+ }
+ }
+
+ public void setHighlightRange(IDocumentKey key) {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null)
+ return;
+
+ IDocument document = sourceViewer.getDocument();
+ if (document == null)
+ return;
+
+ int offset = key.getOffset();
+ int length = key.getLength();
+ setHighlightRange(offset, length, true);
+ int nameLength = PropertiesUtil.createWritableName(key.getName())
+ .length();
+ sourceViewer.setSelectedRange(offset, Math.min(nameLength, length));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.editor.PDESourcePage#createOutlineSorter()
+ */
+ protected ViewerSorter createOutlineSorter() {
+ return new ViewerSorter();
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/LinkSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/LinkSection.java
new file mode 100644
index 0000000..1acff42
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/LinkSection.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.events.*;
+import org.eclipse.ui.forms.widgets.*;
+/**
+ * This class can be used to show a standard section with an array of links.
+ * Links are objects from editor pages, and each one will select the owning
+ * page and reveal the element in it. If the number of objects from the content
+ * provider is greated than the preset limit, only the first 'limit' number of
+ * links will be shown, and a 'More...' button will show up (this is a change
+ * from 2.1 where 'More...' was visible all the time).
+ */
+public class LinkSection extends PDESection {
+ private ILinkLabelProvider labelProvider;
+ private IStructuredContentProvider contentProvider;
+ private Composite linkContainer;
+ private Composite container;
+ private Button moreButton;
+ private String morePageId;
+ private int linkNumberLimit = 20;
+ private LinkHandler linkHandler;
+ class LinkHandler implements IHyperlinkListener {
+ public void linkActivated(HyperlinkEvent e) {
+ doLinkActivated((Hyperlink) e.widget);
+ }
+ public void linkEntered(HyperlinkEvent e) {
+ doEnter((Hyperlink) e.widget);
+ }
+ public void linkExited(HyperlinkEvent e) {
+ doExit((Hyperlink) e.widget);
+ }
+ }
+ /**
+ * @param page
+ * @param parent
+ * @param style
+ */
+ public LinkSection(PDEFormPage page, Composite parent, int style) {
+ super(page, parent, style);
+ FormToolkit toolkit = page.getManagedForm().getToolkit();
+ linkHandler = new LinkHandler();
+ createClient(getSection(), toolkit);
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.pde.internal.ui.neweditor.PDESection#createClient(org.eclipse.ui.forms.widgets.Section,
+ * org.eclipse.ui.forms.widgets.FormToolkit)
+ */
+ protected void createClient(Section section, FormToolkit toolkit) {
+ container = toolkit.createComposite(section);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ container.setLayout(layout);
+ section.setClient(container);
+ linkContainer = toolkit.createComposite(container);
+ linkContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout linkLayout = new GridLayout();
+ linkLayout.marginWidth = 0;
+ linkLayout.marginHeight = 0;
+ linkLayout.verticalSpacing = 0;
+ linkContainer.setLayout(linkLayout);
+ }
+ private void createMoreButton() {
+ moreButton = getManagedForm().getToolkit().createButton(container, "More...", //$NON-NLS-1$
+ SWT.PUSH);
+ moreButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ BusyIndicator.showWhile(getSection().getDisplay(),
+ new Runnable() {
+ public void run() {
+ getPage().getEditor().setActivePage(morePageId);
+ }
+ });
+ }
+ });
+ moreButton
+ .setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
+ }
+ public void add(Object[] links) {
+ for (int i = 0; i < links.length; i++) {
+ createLink(links[i]);
+ }
+ updateMoreState(linkContainer.getChildren().length > linkNumberLimit);
+ reflow();
+ }
+ public void remove(Object[] links) {
+ for (int i = 0; i < links.length; i++) {
+ disposeLink(links[i]);
+ }
+ updateMoreState(linkContainer.getChildren().length > linkNumberLimit);
+ reflow();
+ }
+ private void disposeLink(Object obj) {
+ Hyperlink link = find(obj);
+ if (link != null)
+ link.dispose();
+ }
+ private Hyperlink find(Object object) {
+ Control[] children = linkContainer.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ Control child = children[i];
+ if (child.getData().equals(object))
+ return (Hyperlink) child;
+ }
+ return null;
+ }
+ public void update(Object[] links) {
+ for (int i = 0; i < links.length; i++) {
+ update(links[i]);
+ }
+ reflow();
+ }
+ private void update(Object object) {
+ Hyperlink link = find(object);
+ if (link != null)
+ update(link, object);
+ }
+ private void update(Hyperlink hyperlink, Object object) {
+ String text = labelProvider != null
+ ? labelProvider.getText(object)
+ : object.toString();
+ Image image = labelProvider != null
+ ? labelProvider.getImage(object)
+ : null;
+ String tooltip = labelProvider != null ? labelProvider
+ .getToolTipText(object) : text;
+ hyperlink.setText(text);
+ hyperlink.setToolTipText(tooltip);
+ if (hyperlink instanceof ImageHyperlink)
+ ((ImageHyperlink) hyperlink).setImage(image);
+ reflow();
+ }
+ public void refresh() {
+ // dispose old links
+ Control[] children = linkContainer.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ children[i].dispose();
+ }
+ createLinks();
+ reflow();
+ }
+ private void reflow() {
+ linkContainer.layout();
+ container.layout();
+ getManagedForm().reflow(true);
+ }
+ private void createLinks() {
+ if (contentProvider == null)
+ return;
+ Object[] objects = contentProvider.getElements(getManagedForm().getInput());
+ for (int i = 0; i < objects.length; i++) {
+ if (i == linkNumberLimit)
+ break;
+ createLink(objects[i]);
+ }
+ if (objects.length > linkNumberLimit)
+ getManagedForm().getToolkit().createLabel(linkContainer, "...", SWT.NULL); //$NON-NLS-1$
+ updateMoreState(objects.length > linkNumberLimit);
+ }
+ private void updateMoreState(boolean needMore) {
+ if (needMore && moreButton == null) {
+ createMoreButton();
+ }
+ else if (!needMore && moreButton != null) {
+ moreButton.dispose();
+ moreButton = null;
+ }
+ }
+ private void createLink(Object object) {
+ Image image = labelProvider != null
+ ? labelProvider.getImage(object)
+ : null;
+ Hyperlink hyperlink;
+ if (image != null) {
+ hyperlink = getManagedForm().getToolkit().createImageHyperlink(
+ linkContainer, SWT.NULL);
+ ((ImageHyperlink) hyperlink).setImage(image);
+ } else
+ hyperlink = getManagedForm().getToolkit().createHyperlink(linkContainer,
+ null, SWT.NULL);
+ update(hyperlink, object);
+ hyperlink.setData(object);
+ hyperlink.addHyperlinkListener(linkHandler);
+ }
+ private void doEnter(Hyperlink link) {
+ String statusText = labelProvider != null ? labelProvider
+ .getStatusText(link.getData()) : link.getText();
+ getPage().getEditorSite().getActionBars().getStatusLineManager()
+ .setMessage(statusText);
+ }
+ private void doExit(Hyperlink link) {
+ getPage().getEditorSite().getActionBars().getStatusLineManager()
+ .setMessage(null);
+ }
+ protected void doLinkActivated(Hyperlink link) {
+ Object object = link.getData();
+ getPage().getEditor().setActivePage(morePageId, object);
+ }
+ public void setMorePageId(String id) {
+ this.morePageId = id;
+ }
+ public void setLinkNumberLimit(int limit) {
+ this.linkNumberLimit = limit;
+ }
+ public void setContentProvider(IStructuredContentProvider contentProvider) {
+ this.contentProvider = contentProvider;
+ }
+ public void setLabelProvider(ILinkLabelProvider provider) {
+ this.labelProvider = provider;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelDataTransfer.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelDataTransfer.java
new file mode 100755
index 0000000..74cc988
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelDataTransfer.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+
+import org.eclipse.swt.dnd.*;
+
+/**
+ * @version 1.0
+ * @author
+ */
+public class ModelDataTransfer extends ByteArrayTransfer {
+ /**
+ * Singleton instance.
+ */
+ private static final ModelDataTransfer instance =
+ new ModelDataTransfer();
+ // Create a unique ID to make sure that different Eclipse
+ // applications use different "types" of <code>ModelDataTransfer</code>
+
+ public static final String TYPE_PREFIX = "pde-model-transfer-format"; //$NON-NLS-1$
+ private static final String TYPE_NAME =
+ TYPE_PREFIX + ":" //$NON-NLS-1$
+ + System.currentTimeMillis()
+ + ":" //$NON-NLS-1$
+ + instance.hashCode();
+
+ private static final int TYPEID = registerType(TYPE_NAME);
+
+ public static ModelDataTransfer getInstance() {
+ return instance;
+ }
+
+ /**
+ * Constructor for ModelDataTransfer.
+ */
+ public ModelDataTransfer() {
+ super();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Transfer.
+ */
+ protected int[] getTypeIds() {
+ return new int[] { TYPEID };
+ }
+ /* (non-Javadoc)
+ * Returns the type names.
+ *
+ * @return the list of type names
+ */
+ protected String[] getTypeNames() {
+ return new String[] { TYPE_NAME };
+ }
+ /* (non-Javadoc)
+ * Method declared on Transfer.
+ */
+ protected void javaToNative(Object data, TransferData transferData) {
+ if (!(data instanceof Object[])) {
+ return;
+ }
+ Object[] objects = (Object[]) data;
+ int count = objects.length;
+
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream objectOut = new ObjectOutputStream(out);
+
+ //write the number of resources
+ objectOut.writeInt(count);
+
+ //write each object
+ for (int i = 0; i < objects.length; i++) {
+ objectOut.writeObject(objects[i]);
+ }
+
+ //cleanup
+ objectOut.close();
+ out.close();
+ byte[] bytes = out.toByteArray();
+ super.javaToNative(bytes, transferData);
+ } catch (IOException e) {
+ //it's best to send nothing if there were problems
+ System.out.println(e);
+ }
+
+ }
+ /* (non-Javadoc)
+ * Method declared on Transfer.
+ */
+ protected Object nativeToJava(TransferData transferData) {
+ byte[] bytes = (byte[]) super.nativeToJava(transferData);
+ if (bytes == null)
+ return null;
+ try {
+ ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
+
+ int count = in.readInt();
+ Object[] objects = new Object[count];
+ for (int i = 0; i < count; i++) {
+ objects[i] = in.readObject();
+ }
+ in.close();
+ return objects;
+ } catch (ClassNotFoundException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelUndoManager.java
new file mode 100755
index 0000000..8db3fb0
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelUndoManager.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.util.*;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.core.*;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.ui.forms.editor.IFormPage;
+
+/**
+ * @version 1.0
+ * @author
+ */
+public abstract class ModelUndoManager
+ implements IModelUndoManager, IModelChangedListener {
+ private boolean ignoreChanges;
+ private List operations;
+ private int undoLevelLimit = 10;
+ private int cursor = -1;
+ private IAction undoAction;
+ private IAction redoAction;
+ private PDEFormEditor editor;
+
+ public ModelUndoManager(PDEFormEditor editor) {
+ this.editor = editor;
+ operations = new Vector();
+ }
+
+ /*
+ * @see IModelUndoManager#connect(IModelChangeProvider)
+ */
+ public void connect(IModelChangeProvider provider) {
+ provider.addModelChangedListener(this);
+ if (operations==null) initialize();
+ }
+
+ /*
+ * @see IModelUndoManager#disconnect(IModelChangeProvider)
+ */
+ public void disconnect(IModelChangeProvider provider) {
+ provider.removeModelChangedListener(this);
+ }
+
+ private void initialize() {
+ operations = new Vector();
+ cursor = -1;
+ updateActions();
+ }
+
+ /*
+ * @see IModelUndoManager#isUndoable()
+ */
+ public boolean isUndoable() {
+ return cursor>=0;
+ }
+
+ /*
+ * @see IModelUndoManager#isRedoable()
+ */
+ public boolean isRedoable() {
+ if (operations == null) initialize();
+ return (cursor+1)<operations.size();
+ }
+
+ /*
+ * @see IModelUndoManager#undo()
+ */
+ public void undo() {
+ IModelChangedEvent op = getCurrentOperation();
+ if (op==null) return;
+ ignoreChanges = true;
+ openRelatedPage(op);
+ execute(op, true);
+ cursor --;
+ updateActions();
+ ignoreChanges = false;
+ }
+
+ /*
+ * @see IModelUndoManager#redo()
+ */
+ public void redo() {
+ cursor ++;
+ IModelChangedEvent op = getCurrentOperation();
+ if (op==null) return;
+ ignoreChanges = true;
+ openRelatedPage(op);
+ execute(op, false);
+ ignoreChanges = false;
+ updateActions();
+ }
+
+ protected abstract String getPageId(Object object);
+
+ protected abstract void execute(IModelChangedEvent op, boolean undo);
+
+ private void openRelatedPage(IModelChangedEvent op) {
+ Object obj = op.getChangedObjects()[0];
+ String pageId = getPageId(obj);
+ if (pageId!=null) {
+ IFormPage cpage = editor.getActivePageInstance();
+ IFormPage newPage = editor.findPage(pageId);
+ if (cpage != newPage)
+ editor.setActivePage(newPage.getId());
+ }
+ }
+
+ /*
+ * @see IModelChangedListener#modelChanged(IModelChangedEvent)
+ */
+ public void modelChanged(IModelChangedEvent event) {
+ if (ignoreChanges)
+ return;
+
+ if (event.getChangeType()==IModelChangedEvent.WORLD_CHANGED) {
+ initialize();
+ return;
+ }
+ addOperation(event);
+ }
+
+ private IModelChangedEvent getCurrentOperation() {
+ if (cursor == -1 || cursor == operations.size()) return null;
+ return (IModelChangedEvent)operations.get(cursor);
+ }
+
+ private IModelChangedEvent getNextOperation() {
+ int peekCursor = cursor+1;
+ if (peekCursor >= operations.size()) return null;
+ return (IModelChangedEvent)operations.get(peekCursor);
+ }
+
+ private void addOperation(IModelChangedEvent operation) {
+ operations.add(operation);
+ int size = operations.size();
+ if (size > undoLevelLimit) {
+ int extra = size-undoLevelLimit;
+ // trim
+ for (int i=0; i<extra; i++) {
+ operations.remove(i);
+ }
+ }
+ cursor = operations.size() -1;
+ updateActions();
+ }
+
+ public void setActions(IAction undoAction, IAction redoAction) {
+ this.undoAction = undoAction;
+ this.redoAction = redoAction;
+ updateActions();
+ }
+
+ private void updateActions() {
+ if (undoAction!=null && redoAction!=null) {
+ undoAction.setEnabled(isUndoable());
+ undoAction.setText(getUndoText());
+ redoAction.setEnabled(isRedoable());
+ redoAction.setText(getRedoText());
+ }
+ }
+
+ private String getUndoText() {
+ IModelChangedEvent op = getCurrentOperation();
+ if (op == null) {
+ return PDEUIMessages.UpdateManager_noUndo;
+ }
+ return NLS.bind(PDEUIMessages.UpdateManager_undo, getOperationText(op));
+ }
+
+ private String getRedoText() {
+ IModelChangedEvent op = getNextOperation();
+ if (op == null) {
+ return PDEUIMessages.UpdateManager_noRedo;
+ }
+ return NLS.bind(PDEUIMessages.UpdateManager_redo, getOperationText(op));
+ }
+
+ private String getOperationText(IModelChangedEvent op) {
+ String opText=""; //$NON-NLS-1$
+ switch (op.getChangeType()) {
+ case IModelChangedEvent.INSERT:
+ opText = PDEUIMessages.UpdateManager_op_add;
+ break;
+ case IModelChangedEvent.REMOVE:
+ opText = PDEUIMessages.UpdateManager_op_remove;
+ break;
+ case IModelChangedEvent.CHANGE:
+ opText = PDEUIMessages.UpdateManager_op_change;
+ break;
+ }
+ return opText;
+ }
+
+ public void setUndoLevelLimit(int limit) {
+ this.undoLevelLimit = limit;
+ }
+
+ public void setIgnoreChanges(boolean ignore) {
+ this.ignoreChanges = ignore;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/MultiSourceEditor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/MultiSourceEditor.java
new file mode 100755
index 0000000..84bd288
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/MultiSourceEditor.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.IFormPage;
+
+public abstract class MultiSourceEditor extends PDEFormEditor {
+ protected void addSourcePage(String contextId) {
+ InputContext context = inputContextManager.findContext(contextId);
+ if (context == null)
+ return;
+ PDESourcePage sourcePage;
+ // Don't duplicate
+ if (findPage(contextId)!=null) return;
+ sourcePage = createSourcePage(this, contextId, context.getInput().getName(), context.getId());
+ sourcePage.setInputContext(context);
+ try {
+ addPage(sourcePage, context.getInput());
+ } catch (PartInitException e) {
+ PDEPlugin.logException(e);
+ }
+ }
+
+ protected void removePage(String pageId) {
+ IFormPage page = findPage(pageId);
+ if (page == null)
+ return;
+ if (page.isDirty()) {
+ // need to ask the user about this
+ } else {
+ removePage(page.getIndex());
+ if (!page.isEditor())
+ page.dispose();
+ }
+ }
+
+ protected PDESourcePage createSourcePage(PDEFormEditor editor, String title, String name, String contextId) {
+ return new GenericSourcePage(editor, title, name);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/NullUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/NullUndoManager.java
new file mode 100644
index 0000000..0047549
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/NullUndoManager.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.pde.core.IModelChangeProvider;
+
+/**
+ * @version 1.0
+ * @author
+ */
+public class NullUndoManager implements IModelUndoManager {
+
+ /*
+ * @see IModelUndoManager#connect(IModelChangeProvider)
+ */
+ public void connect(IModelChangeProvider provider) {
+ }
+
+ /*
+ * @see IModelUndoManager#disconnect(IModelChangeProvider)
+ */
+ public void disconnect(IModelChangeProvider provider) {
+ }
+
+ /*
+ * @see IModelUndoManager#isUndoable()
+ */
+ public boolean isUndoable() {
+ return false;
+ }
+
+ /*
+ * @see IModelUndoManager#isRedoable()
+ */
+ public boolean isRedoable() {
+ return false;
+ }
+
+ /*
+ * @see IModelUndoManager#undo()
+ */
+ public void undo() {
+ }
+
+ /*
+ * @see IModelUndoManager#redo()
+ */
+ public void redo() {
+ }
+
+ /*
+ * @see IModelUndoManager#setUndoLevelLimit(int)
+ */
+ public void setUndoLevelLimit(int limit) {
+ }
+
+ /*
+ * @see IModelUndoManager#setIgnoreChanges(boolean)
+ */
+ public void setIgnoreChanges(boolean ignore) {
+ }
+
+ public void setActions(IAction undoAction, IAction redoAction) {
+ if (undoAction!=null) undoAction.setEnabled(false);
+ if (redoAction!=null) redoAction.setEnabled(false);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetails.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetails.java
new file mode 100755
index 0000000..637f5b6
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetails.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public abstract class PDEDetails extends AbstractFormPart implements IDetailsPage, IContextPart {
+
+ public PDEDetails() {
+ }
+
+ public boolean canPaste(Clipboard clipboard) {
+ return true;
+ }
+
+ public boolean doGlobalAction(String actionId) {
+ return false;
+ }
+
+ protected void markDetailsPart(Control control) {
+ control.setData("part", this); //$NON-NLS-1$
+ }
+
+ protected void createSpacer(FormToolkit toolkit, Composite parent, int span) {
+ Label spacer = toolkit.createLabel(parent, ""); //$NON-NLS-1$
+ GridData gd = new GridData();
+ gd.horizontalSpan = span;
+ spacer.setLayoutData(gd);
+ }
+ public void cancelEdit() {
+ super.refresh();
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetailsSections.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetailsSections.java
new file mode 100644
index 0000000..824cdac
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetailsSections.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.IFormPart;
+
+/**
+ * Wrapper for PDESections, implemens IDetailsPage for use in MasterDetailsBlock
+ */
+public abstract class PDEDetailsSections extends PDEDetails {
+ private PDESection sections[];
+
+ protected abstract PDESection[] createSections(PDEFormPage page,
+ Composite parent);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.forms.IDetailsPage#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ public void createContents(Composite parent) {
+ sections = createSections(getPage(), parent);
+ GridLayout layout = new GridLayout();
+ layout.verticalSpacing = 30;
+ parent.setLayout(layout);
+ for (int i = 0; i < sections.length; i++) {
+ getManagedForm().addPart(sections[i]);
+ }
+ }
+
+ public void dispose() {
+ for (int i = 0; i < sections.length; i++) {
+ sections[i].dispose();
+ }
+ }
+
+ public void fireSaveNeeded() {
+ markDirty();
+ getPage().getPDEEditor().fireSaveNeeded(getContextId(), false);
+ }
+
+ public abstract String getContextId();
+
+ public PDEFormPage getPage() {
+ return (PDEFormPage) getManagedForm().getContainer();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.forms.AbstractFormPart#isDirty()
+ */
+ public boolean isDirty() {
+ for (int i = 0; i < sections.length; i++) {
+ if (sections[i].isDirty()) {
+ return true;
+ }
+ }
+ return super.isDirty();
+ }
+
+ public boolean isEditable() {
+ return getPage().getPDEEditor().getAggregateModel().isEditable();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.forms.AbstractFormPart#isStale()
+ */
+ public boolean isStale() {
+ for (int i = 0; i < sections.length; i++) {
+ if (sections[i].isStale()) {
+ return true;
+ }
+ }
+ return super.isStale();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.pde.core.IModelChangedListener#modelChanged(org.eclipse.pde.core.IModelChangedEvent)
+ */
+ public void modelChanged(IModelChangedEvent event) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.forms.IDetailsPage#inputChanged(org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public void selectionChanged(IFormPart masterPart, ISelection selection) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.forms.IDetailsPage#setFocus()
+ */
+ public void setFocus() {
+ if (sections.length > 0) {
+ sections[0].setFocus();
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditor.java
new file mode 100755
index 0000000..28bc311
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditor.java
@@ -0,0 +1,757 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.context.IInputContextListener;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContextManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IWritable;
+import org.eclipse.pde.internal.ui.IPDEUIConstants;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.search.ui.text.ISearchEditorAccess;
+import org.eclipse.search.ui.text.Match;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.editors.text.ILocationProvider;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.part.MultiPageEditorPart;
+import org.eclipse.ui.part.MultiPageEditorSite;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+/**
+ * A simple multi-page form editor that uses Eclipse Forms support. Example
+ * plug-in is configured to create one instance of form colors that is shared
+ * between multiple editor instances.
+ */
+public abstract class PDEFormEditor extends FormEditor
+ implements
+ IInputContextListener,
+ IGotoMarker, ISearchEditorAccess {
+ /**
+ * Updates the OutlinePage selection.
+ *
+ * @since 3.0
+ */
+ private class PDEFormEditorChangeListener implements
+ ISelectionChangedListener {
+
+ /**
+ * Installs this selection changed listener with the given selection
+ * provider. If the selection provider is a post selection provider,
+ * post selection changed events are the preferred choice, otherwise
+ * normal selection changed events are requested.
+ *
+ * @param selectionProvider
+ */
+ public void install(ISelectionProvider selectionProvider) {
+ if (selectionProvider == null) {
+ return;
+ }
+
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+ provider.addPostSelectionChangedListener(this);
+ } else {
+ selectionProvider.addSelectionChangedListener(this);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (PDEPlugin.getDefault().getPreferenceStore().getBoolean(
+ "ToggleLinkWithEditorAction.isChecked")) //$NON-NLS-1$
+ if (getFormOutline() != null) {
+ getFormOutline().setSelection(event.getSelection());
+ }
+ }
+
+ /**
+ * Removes this selection changed listener from the given selection
+ * provider.
+ *
+ * @param selectionProviderstyle
+ */
+ public void uninstall(ISelectionProvider selectionProvider) {
+ if (selectionProvider == null) {
+ return;
+ }
+
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+ provider.removePostSelectionChangedListener(this);
+ } else {
+ selectionProvider.removeSelectionChangedListener(this);
+ }
+ }
+
+ }
+
+ /**
+ * The editor selection changed listener.
+ *
+ * @since 3.0
+ */
+ private PDEFormEditorChangeListener fEditorSelectionChangedListener;
+ private Clipboard clipboard;
+ private Menu contextMenu;
+ protected InputContextManager inputContextManager;
+ private ISortableContentOutlinePage formOutline;
+ private PDEMultiPagePropertySheet propertySheet;
+ private PDEMultiPageContentOutline contentOutline;
+ private String lastActivePageId;
+ private boolean lastDirtyState;
+
+ private static class PDEMultiPageEditorSite extends MultiPageEditorSite {
+ public PDEMultiPageEditorSite(MultiPageEditorPart multiPageEditor,
+ IEditorPart editor) {
+ super(multiPageEditor, editor);
+ }
+ public IEditorActionBarContributor getActionBarContributor() {
+ PDEFormEditor editor = (PDEFormEditor) getMultiPageEditor();
+ PDEFormEditorContributor contributor = editor.getContributor();
+ return contributor.getSourceContributor();
+ }
+
+ public IWorkbenchPart getPart() {
+ return getMultiPageEditor();
+ }
+ }
+ /**
+ *
+ */
+ public PDEFormEditor() {
+ PDEPlugin.getDefault().getLabelProvider().connect(this);
+ inputContextManager = createInputContextManager();
+ }
+ /**
+ * We must override nested site creation so that we properly pass the source
+ * editor contributor when asked.
+ */
+ protected IEditorSite createSite(IEditorPart editor) {
+ return new PDEMultiPageEditorSite(this, editor);
+ }
+ public IProject getCommonProject() {
+ return inputContextManager.getCommonProject();
+ }
+ public IBaseModel getAggregateModel() {
+ if (inputContextManager != null)
+ return inputContextManager.getAggregateModel();
+ return null;
+ }
+ protected abstract InputContextManager createInputContextManager();
+ /**
+ * Tests whether this editor has a context with a provided id. The test can
+ * be used to check whether to add certain pages.
+ *
+ * @param contextId
+ * @return <code>true</code> if provided context is present,
+ * <code>false</code> otherwise.
+ */
+ public boolean hasInputContext(String contextId) {
+ return inputContextManager.hasContext(contextId);
+ }
+ public InputContextManager getContextManager() {
+ return inputContextManager;
+ }
+ protected void createInputContexts(InputContextManager contextManager) {
+ IEditorInput input = getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ // resource - find the project
+ createResourceContexts(contextManager, (IFileEditorInput) input);
+ } else if (input instanceof SystemFileEditorInput) {
+ // system file - find the file system folder
+ createSystemFileContexts(contextManager,
+ (SystemFileEditorInput) input);
+ } else if (input instanceof IStorageEditorInput) {
+ createStorageContexts(contextManager, (IStorageEditorInput) input);
+ } else if (input instanceof ILocationProvider) {
+ IPath path = ((ILocationProvider) input).getPath(input);
+ File file = path.toFile();
+ SystemFileEditorInput sinput = new SystemFileEditorInput(file);
+ createSystemFileContexts(contextManager, sinput);
+ }
+ }
+ protected abstract void createResourceContexts(
+ InputContextManager contexts, IFileEditorInput input);
+ protected abstract void createSystemFileContexts(
+ InputContextManager contexts, SystemFileEditorInput input);
+ protected abstract void createStorageContexts(InputContextManager contexts,
+ IStorageEditorInput input);
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.forms.editor.FormEditor#createToolkit(org.eclipse.swt.widgets.Display)
+ */
+ protected FormToolkit createToolkit(Display display) {
+ // Create a toolkit that shares colors between editors.
+ return new FormToolkit(PDEPlugin.getDefault().getFormColors(display));
+ }
+ /*
+ * When subclassed, don't forget to call 'super'
+ */
+ protected void createPages() {
+ clipboard = new Clipboard(getContainer().getDisplay());
+ MenuManager manager = new MenuManager();
+ IMenuListener listener = new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ contextMenuAboutToShow(manager);
+ }
+ };
+ manager.setRemoveAllWhenShown(true);
+ manager.addMenuListener(listener);
+ contextMenu = manager.createContextMenu(getContainer());
+ getContainer().setMenu(contextMenu);
+ createInputContexts(inputContextManager);
+ super.createPages();
+ inputContextManager.addInputContextListener(this);
+ String pageToShow = computeInitialPageId();
+ if (pageToShow != null)
+ setActivePage(pageToShow);
+ updateTitle();
+ }
+ protected void pageChange(int newPageIndex) {
+ super.pageChange(newPageIndex);
+ IFormPage page = getActivePageInstance();
+ updateContentOutline(page);
+ updatePropertySheet(page);
+ if (page!=null)
+ lastActivePageId = page.getId();
+ }
+ public Clipboard getClipboard() {
+ return clipboard;
+ }
+ protected void contextMenuAboutToShow(IMenuManager manager) {
+ PDEFormEditorContributor contributor = getContributor();
+ IFormPage page = getActivePageInstance();
+ if (page instanceof PDEFormPage)
+ ((PDEFormPage) page).contextMenuAboutToShow(manager);
+ if (contributor != null)
+ contributor.contextMenuAboutToShow(manager);
+ }
+ public PDEFormEditorContributor getContributor() {
+ return (PDEFormEditorContributor) getEditorSite()
+ .getActionBarContributor();
+ }
+ protected String computeInitialPageId() {
+ String firstPageId = null;
+ String storedFirstPageId = loadDefaultPage();
+ if (storedFirstPageId != null)
+ firstPageId = storedFirstPageId;
+ // Regardless what is the stored value,
+ // use source page if model is not valid
+ String invalidContextId = getFirstInvalidContextId();
+ if (invalidContextId != null)
+ return invalidContextId;
+ return firstPageId;
+ }
+
+ private String getFirstInvalidContextId() {
+ InputContext[] invalidContexts = inputContextManager
+ .getInvalidContexts();
+ if (invalidContexts.length == 0)
+ return null;
+ // If primary context is among the invalid ones, return that.
+ for (int i = 0; i < invalidContexts.length; i++) {
+ if (invalidContexts[i].isPrimary())
+ return invalidContexts[i].getId();
+ }
+ // Return the first one
+ return invalidContexts[0].getId();
+ }
+
+ public String getTitle() {
+ if (inputContextManager == null)
+ return super.getTitle();
+ InputContext context = inputContextManager.getPrimaryContext();
+ if (context == null)
+ return super.getTitle();
+ return context.getInput().getName();
+ }
+
+ public void updateTitle() {
+ firePropertyChange(IWorkbenchPart.PROP_TITLE);
+ }
+
+ public String getTitleProperty() {
+ return ""; //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void doSave(IProgressMonitor monitor) {
+ commitFormPages(true);
+ inputContextManager.save(monitor);
+ editorDirtyStateChanged();
+ }
+ public void doRevert() {
+ IFormPage currentPage = getActivePageInstance();
+ if (currentPage != null && currentPage instanceof PDEFormPage)
+ ((PDEFormPage) currentPage).cancelEdit();
+ IFormPage[] pages = getPages();
+ for (int i = 0; i < pages.length; i++) {
+ if (pages[i] instanceof PDESourcePage) {
+ ((PDESourcePage) pages[i]).doRevertToSaved();
+ }
+ }
+ editorDirtyStateChanged();
+ }
+ public void doRevert(IEditorInput input) {
+ IFormPage currentPage = getActivePageInstance();
+ if (currentPage != null && currentPage instanceof PDEFormPage)
+ ((PDEFormPage) currentPage).cancelEdit();
+ InputContext context = inputContextManager.getContext(input);
+ IFormPage page = findPage(context.getId());
+ if (page!=null && page instanceof PDESourcePage) {
+ PDESourcePage spage = (PDESourcePage) page;
+ spage.doRevertToSaved();
+ }
+ editorDirtyStateChanged();
+ }
+ private void commitFormPages(boolean onSave) {
+ IFormPage[] pages = getPages();
+ for (int i = 0; i < pages.length; i++) {
+ IFormPage page = pages[i];
+ IManagedForm mform = page.getManagedForm();
+ if (mform != null && mform.isDirty())
+ mform.commit(true);
+ }
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.ISaveablePart#doSaveAs()
+ */
+ public void doSaveAs() {
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
+ */
+ public boolean isSaveAsAllowed() {
+ return false;
+ }
+
+ private void storeDefaultPage() {
+ IEditorInput input = getEditorInput();
+ String pageId = lastActivePageId;
+ if (pageId == null)
+ return;
+ if (input instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput) input).getFile();
+ if (file != null) {
+ //set the settings on the resouce
+ try {
+ file
+ .setPersistentProperty(
+ IPDEUIConstants.DEFAULT_EDITOR_PAGE_KEY_NEW,
+ pageId);
+ } catch (CoreException e) {
+ }
+ }
+ } else if (input instanceof SystemFileEditorInput) {
+ File file = (File) ((SystemFileEditorInput) input)
+ .getAdapter(File.class);
+ if (file == null)
+ return;
+ IDialogSettings section = getSettingsSection();
+ section.put(file.getPath(), pageId);
+ }
+ }
+ private String loadDefaultPage() {
+ IEditorInput input = getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ // load the setting from the resource
+ IFile file = ((IFileEditorInput) input).getFile();
+ try {
+ return file
+ .getPersistentProperty(IPDEUIConstants.DEFAULT_EDITOR_PAGE_KEY_NEW);
+ } catch (CoreException e) {
+ return null;
+ }
+ } else if (input instanceof SystemFileEditorInput) {
+ File file = (File) ((SystemFileEditorInput) input)
+ .getAdapter(File.class);
+ if (file == null)
+ return null;
+ IDialogSettings section = getSettingsSection();
+ String key = file.getPath();
+ return section.get(key);
+ }
+ return null;
+ }
+ public void dispose() {
+ storeDefaultPage();
+ if (fEditorSelectionChangedListener != null) {
+ fEditorSelectionChangedListener.uninstall(getSite().getSelectionProvider());
+ fEditorSelectionChangedListener= null;
+ }
+ //setSelection(new StructuredSelection());
+ PDEPlugin.getDefault().getLabelProvider().disconnect(this);
+ if (clipboard != null) {
+ clipboard.dispose();
+ clipboard = null;
+ }
+ super.dispose();
+ inputContextManager.dispose();
+ inputContextManager = null;
+ }
+ public boolean isDirty() {
+ lastDirtyState = computeDirtyState();
+ return lastDirtyState;
+ }
+
+ private boolean computeDirtyState() {
+ IFormPage page = getActivePageInstance();
+ if ((page != null && page.isDirty())
+ || (inputContextManager != null && inputContextManager
+ .isDirty()))
+ return true;
+ return super.isDirty();
+ }
+
+ public boolean getLastDirtyState() {
+ return lastDirtyState;
+ }
+
+ public void fireSaveNeeded(String contextId, boolean notify) {
+ if (contextId == null)
+ return;
+ InputContext context = inputContextManager.findContext(contextId);
+ if (context != null)
+ fireSaveNeeded(context.getInput(), notify);
+ }
+ public void fireSaveNeeded(IEditorInput input, boolean notify) {
+ if (notify)
+ editorDirtyStateChanged();
+ if (isDirty())
+ validateEdit(input);
+ }
+ public void editorDirtyStateChanged() {
+ super.editorDirtyStateChanged();
+ PDEFormEditorContributor contributor = getContributor();
+ if (contributor != null)
+ contributor.updateActions();
+ }
+ private void validateEdit(IEditorInput input) {
+ final InputContext context = inputContextManager.getContext(input);
+ if (!context.validateEdit()) {
+ getSite().getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ doRevert(context.getInput());
+ context.setValidated(false);
+ }
+ });
+ }
+ }
+ private IDialogSettings getSettingsSection() {
+ // store the setting in dialog settings
+ IDialogSettings root = PDEPlugin.getDefault().getDialogSettings();
+ IDialogSettings section = root.getSection("multi-page-editor"); //$NON-NLS-1$
+ if (section == null)
+ section = root.addNewSection("multi-page-editor"); //$NON-NLS-1$
+ return section;
+ }
+ public void gotoMarker(IMarker marker) {
+ IResource resource = marker.getResource();
+ InputContext context = inputContextManager.findContext(resource);
+ if (context == null)
+ return;
+ IFormPage page = getActivePageInstance();
+ if (!context.getId().equals(page.getId()))
+ page = setActivePage(context.getId());
+ IDE.gotoMarker(page, marker);
+ }
+
+ public void openToSourcePage(Object object, int offset, int length) {
+ InputContext context = getInputContext(object);
+ if (context != null) {
+ PDESourcePage page = (PDESourcePage)setActivePage(context.getId());
+ if (page != null)
+ page.selectAndReveal(offset, length);
+ }
+ }
+
+ public void setSelection(ISelection selection) {
+ getSite().getSelectionProvider().setSelection(selection);
+ getContributor().updateSelectableActions(selection);
+ }
+ public ISelection getSelection() {
+ return getSite().getSelectionProvider().getSelection();
+ }
+ public Object getAdapter(Class key) {
+ if (key.equals(IContentOutlinePage.class)) {
+ return getContentOutline();
+ }
+ if (key.equals(IPropertySheetPage.class)) {
+ return getPropertySheet();
+ }
+ if (key.equals(IGotoMarker.class)) {
+ return this;
+ }
+ if (key.equals(ISearchEditorAccess.class)) {
+ return this;
+ }
+ return super.getAdapter(key);
+ }
+ public Menu getContextMenu() {
+ return contextMenu;
+ }
+ public PDEMultiPageContentOutline getContentOutline() {
+ if (contentOutline == null || contentOutline.isDisposed()) {
+ contentOutline = new PDEMultiPageContentOutline(this);
+ updateContentOutline(getActivePageInstance());
+ }
+ return contentOutline;
+ }
+ public PDEMultiPagePropertySheet getPropertySheet() {
+ if (propertySheet == null || propertySheet.isDisposed()) {
+ propertySheet = new PDEMultiPagePropertySheet();
+ updatePropertySheet(getActivePageInstance());
+ }
+ return propertySheet;
+ }
+ /**
+ *
+ * @return outline page or null
+ */
+ protected ISortableContentOutlinePage getFormOutline() {
+ if (formOutline == null) {
+ formOutline = createContentOutline();
+ if (formOutline != null) {
+ fEditorSelectionChangedListener = new PDEFormEditorChangeListener();
+ fEditorSelectionChangedListener.install(getSite()
+ .getSelectionProvider());
+ }
+ }
+ return formOutline;
+ }
+ abstract protected ISortableContentOutlinePage createContentOutline();
+
+ private void updateContentOutline(IFormPage page) {
+ if (contentOutline == null)
+ return;
+ ISortableContentOutlinePage outline = null;
+ if (page instanceof PDESourcePage) {
+ outline = ((PDESourcePage) page).getContentOutline();
+ } else {
+ outline = getFormOutline();
+ if (outline != null && outline instanceof FormOutlinePage)
+ ((FormOutlinePage) outline).refresh();
+ }
+ contentOutline.setPageActive(outline);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.FormEditor#setActivePage(java.lang.String)
+ */
+ public IFormPage setActivePage(String pageId) {
+ IFormPage page = super.setActivePage(pageId);
+ if (page != null)
+ updateContentOutline(page);
+ return page;
+ }
+ protected IPropertySheetPage getPropertySheet(PDEFormPage page) {
+ return page.getPropertySheetPage();
+ }
+ void updatePropertySheet(IFormPage page) {
+ if (propertySheet == null)
+ return;
+ if (page instanceof PDEFormPage) {
+ IPropertySheetPage propertySheetPage = getPropertySheet((PDEFormPage) page);
+ if (propertySheetPage != null) {
+ propertySheet.setPageActive(propertySheetPage);
+ }
+ } else
+ propertySheet.setDefaultPageActive();
+ }
+ /* package */IFormPage[] getPages() {
+ ArrayList formPages = new ArrayList();
+ for (int i = 0; i < pages.size(); i++) {
+ Object page = pages.get(i);
+ if (page instanceof IFormPage)
+ formPages.add(page);
+ }
+ return (IFormPage[]) formPages.toArray(new IFormPage[formPages.size()]);
+ }
+ protected void performGlobalAction(String id) {
+ // preserve selection
+ ISelection selection = getSelection();
+ boolean handled = ((PDEFormPage) getActivePageInstance())
+ .performGlobalAction(id);
+ if (!handled) {
+ IFormPage page = getActivePageInstance();
+ if (page instanceof PDEFormPage) {
+ if (id.equals(ActionFactory.UNDO.getId())) {
+ inputContextManager.undo();
+ return;
+ }
+ if (id.equals(ActionFactory.REDO.getId())) {
+ inputContextManager.redo();
+ return;
+ }
+ if (id.equals(ActionFactory.CUT.getId())
+ || id.equals(ActionFactory.COPY.getId())) {
+ copyToClipboard(selection);
+ return;
+ }
+ }
+ }
+ }
+ private void copyToClipboard(ISelection selection) {
+ Object[] objects = null;
+ String textVersion = null;
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ if (ssel == null || ssel.size() == 0)
+ return;
+ objects = ssel.toArray();
+ StringWriter writer = new StringWriter();
+ PrintWriter pwriter = new PrintWriter(writer);
+ Class objClass = null;
+ for (int i = 0; i < objects.length; i++) {
+ Object obj = objects[i];
+ if (objClass == null)
+ objClass = obj.getClass();
+ else if (objClass.equals(obj.getClass()) == false)
+ return;
+ if (obj instanceof IWritable) {
+ ((IWritable) obj).write("", pwriter); //$NON-NLS-1$
+ }
+ }
+ pwriter.flush();
+ textVersion = writer.toString();
+ try {
+ pwriter.close();
+ writer.close();
+ } catch (IOException e) {
+ }
+ } else if (selection instanceof ITextSelection) {
+ textVersion = ((ITextSelection) selection).getText();
+ }
+ if ((textVersion == null || textVersion.length() == 0) && objects == null)
+ return;
+ // set the clipboard contents
+ Object[]o = null;
+ Transfer[] t = null;
+ if (objects == null ) {
+ o = new Object[] {textVersion};
+ t = new Transfer[] {TextTransfer.getInstance()};
+ } else if (textVersion == null || textVersion.length() == 0) {
+ o = new Object[] {objects};
+ t = new Transfer[] {ModelDataTransfer.getInstance()};
+ } else {
+ o = new Object[] {objects, textVersion};
+ t = new Transfer[] {ModelDataTransfer.getInstance(), TextTransfer.getInstance()};
+ }
+ clipboard.setContents(o, t);
+ }
+ public boolean canPasteFromClipboard() {
+ IFormPage page = getActivePageInstance();
+ if (page instanceof PDEFormPage) {
+ return ((PDEFormPage) page).canPaste(getClipboard());
+ }
+ return false;
+ }
+ public boolean canCopy(ISelection selection) {
+ if (selection == null)
+ return false;
+ if (selection instanceof IStructuredSelection)
+ return !selection.isEmpty();
+ if (selection instanceof ITextSelection) {
+ ITextSelection textSelection = (ITextSelection) selection;
+ return textSelection.getLength() > 0;
+ }
+ return false;
+ }
+ void updateUndo(IAction undoAction, IAction redoAction) {
+ IModelUndoManager undoManager = inputContextManager.getUndoManager();
+ if (undoManager != null)
+ undoManager.setActions(undoAction, redoAction);
+ }
+ void synchronizeOutlinePage() {
+ if (getFormOutline() != null) {
+ getFormOutline().setSelection(getSelection());
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.ISearchEditorAccess#getDocument(org.eclipse.search.ui.text.Match)
+ */
+ public IDocument getDocument(Match match) {
+ InputContext context = getInputContext(match.getElement());
+ return context == null ? null : context.getDocumentProvider().getDocument(context.getInput());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.ISearchEditorAccess#getAnnotationModel(org.eclipse.search.ui.text.Match)
+ */
+ public IAnnotationModel getAnnotationModel(Match match) {
+ InputContext context = getInputContext(match.getElement());
+ return context == null ? null : context.getDocumentProvider().getAnnotationModel(context.getInput());
+ }
+
+ protected abstract InputContext getInputContext(Object object);
+
+ public int getOrientation() {
+ return SWT.LEFT_TO_RIGHT;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditorContributor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditorContributor.java
new file mode 100755
index 0000000..39f5455
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditorContributor.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.util.*;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.core.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.ui.*;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.editors.text.TextEditorActionContributor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.ide.IDEActionFactory;
+import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
+import org.eclipse.ui.texteditor.IUpdate;
+
+public class PDEFormEditorContributor
+ extends
+ MultiPageEditorActionBarContributor {
+ private SubActionBars sourceActionBars;
+ private PDEFormEditor editor;
+ private IFormPage page;
+ private SaveAction saveAction;
+ private RevertAction revertAction;
+ private ClipboardAction cutAction;
+ private ClipboardAction copyAction;
+ private ClipboardAction pasteAction;
+ private Hashtable globalActions = new Hashtable();
+ private TextEditorActionContributor sourceContributor;
+ class GlobalAction extends Action implements IUpdate {
+ private String id;
+ public GlobalAction(String id) {
+ this.id = id;
+ }
+ public void run() {
+ editor.performGlobalAction(id);
+ updateSelectableActions(editor.getSelection());
+ }
+ public void update() {
+ getActionBars().updateActionBars();
+ }
+ }
+ class ClipboardAction extends GlobalAction {
+ public ClipboardAction(String id) {
+ super(id);
+ setEnabled(false);
+ }
+ public void selectionChanged(ISelection selection) {
+ }
+ public boolean isEditable() {
+ if (editor == null)
+ return false;
+ IBaseModel model = editor.getAggregateModel();
+ if (model instanceof IEditable)
+ return ((IEditable) model).isEditable();
+ return false;
+ }
+ }
+ class CutAction extends ClipboardAction {
+ public CutAction() {
+ super(ActionFactory.CUT.getId());
+ setText(PDEUIMessages.EditorActions_cut);
+ }
+ public void selectionChanged(ISelection selection) {
+ setEnabled(isEditable() && editor.canCopy(selection));
+ }
+ }
+ class CopyAction extends ClipboardAction {
+ public CopyAction() {
+ super(ActionFactory.COPY.getId());
+ setText(PDEUIMessages.EditorActions_copy);
+ }
+ public void selectionChanged(ISelection selection) {
+ setEnabled(editor.canCopy(selection));
+ }
+ }
+ class PasteAction extends ClipboardAction {
+ public PasteAction() {
+ super(ActionFactory.PASTE.getId());
+ setText(PDEUIMessages.EditorActions_paste);
+ //selectionChanged(null);
+ }
+ public void selectionChanged(ISelection selection) {
+ setEnabled(isEditable() && editor.canPasteFromClipboard());
+ }
+ }
+ class SaveAction extends Action implements IUpdate {
+ public SaveAction() {
+ }
+ public void run() {
+ if (editor != null)
+ PDEPlugin.getActivePage().saveEditor(editor, false);
+ }
+ public void update() {
+ if (editor != null) {
+ setEnabled(editor.isDirty());
+ } else
+ setEnabled(false);
+ }
+ }
+ class RevertAction extends Action implements IUpdate {
+ public RevertAction() {
+ }
+ public void run() {
+ if (editor != null)
+ editor.doRevert();
+ }
+ public void update() {
+ if (editor != null) {
+ setEnabled(editor.isDirty());
+ } else
+ setEnabled(false);
+ }
+ }
+ public PDEFormEditorContributor(String menuName) {
+ sourceContributor = new TextEditorActionContributor();
+ makeActions();
+ }
+
+ public IEditorActionBarContributor getSourceContributor() {
+ return sourceContributor;
+ }
+ private void addGlobalAction(String id) {
+ GlobalAction action = new GlobalAction(id);
+ addGlobalAction(id, action);
+ }
+ private void addGlobalAction(String id, Action action) {
+ globalActions.put(id, action);
+ }
+ public void addClipboardActions(IMenuManager mng) {
+ mng.add(cutAction);
+ mng.add(copyAction);
+ mng.add(pasteAction);
+ mng.add(new Separator());
+ mng.add(revertAction);
+ }
+ public void contextMenuAboutToShow(IMenuManager mng) {
+ contextMenuAboutToShow(mng, true);
+ }
+ public void contextMenuAboutToShow(IMenuManager mng, boolean addClipboard) {
+ if (editor != null)
+ updateSelectableActions(editor.getSelection());
+ if (addClipboard) {
+ addClipboardActions(mng);
+ }
+ mng.add(saveAction);
+ }
+ public void contributeToMenu(IMenuManager mm) {
+ }
+ public void contributeToStatusLine(IStatusLineManager slm) {
+ }
+ public void contributeToToolBar(IToolBarManager tbm) {
+ }
+ public void contributeToCoolBar(ICoolBarManager cbm) {
+ }
+ public void dispose() {
+ sourceContributor.dispose();
+ sourceActionBars.dispose();
+ super.dispose();
+ }
+ public void init(IActionBars bars) {
+ super.init(bars);
+ sourceActionBars = new SubActionBars(bars);
+ sourceContributor.init(sourceActionBars);
+ }
+
+ public PDEFormEditor getEditor() {
+ return editor;
+ }
+ public IAction getGlobalAction(String id) {
+ return (IAction) globalActions.get(id);
+ }
+ public IAction getSaveAction() {
+ return saveAction;
+ }
+ public IAction getRevertAction() {
+ return revertAction;
+ }
+ public IStatusLineManager getStatusLineManager() {
+ return getActionBars().getStatusLineManager();
+ }
+ protected void makeActions() {
+ // clipboard actions
+ cutAction = new CutAction();
+ copyAction = new CopyAction();
+ pasteAction = new PasteAction();
+ addGlobalAction(ActionFactory.CUT.getId(), cutAction);
+ addGlobalAction(ActionFactory.COPY.getId(), copyAction);
+ addGlobalAction(ActionFactory.PASTE.getId(), pasteAction);
+ addGlobalAction(ActionFactory.DELETE.getId());
+ // undo/redo
+ addGlobalAction(ActionFactory.UNDO.getId());
+ addGlobalAction(ActionFactory.REDO.getId());
+ // select/find
+ addGlobalAction(ActionFactory.SELECT_ALL.getId());
+ addGlobalAction(ActionFactory.FIND.getId());
+ // bookmark
+ addGlobalAction(IDEActionFactory.BOOKMARK.getId());
+ // save/revert
+ saveAction = new SaveAction();
+ saveAction.setText(PDEUIMessages.EditorActions_save);
+ revertAction = new RevertAction();
+ revertAction.setText(PDEUIMessages.EditorActions_revert);
+ }
+ public void setActiveEditor(IEditorPart targetEditor) {
+ //if (editor != null)
+ // editor.updateUndo(null, null);
+ if (targetEditor instanceof PDESourcePage) {
+ // Fixing the 'goto line' problem -
+ // the action is thinking that source page
+ // is a standalone editor and tries to activate it
+ // #19361
+ PDESourcePage page = (PDESourcePage) targetEditor;
+ PDEPlugin.getActivePage().activate(page.getEditor());
+ return;
+ }
+ if (targetEditor instanceof PDEFormEditor)
+ this.editor = (PDEFormEditor) targetEditor;
+ else
+ return;
+ editor.updateUndo(getGlobalAction(ActionFactory.UNDO.getId()),
+ getGlobalAction(ActionFactory.REDO.getId()));
+ IEditorPart page = editor.getActiveEditor();
+ setActivePage(page);
+ updateSelectableActions(editor.getSelection());
+ }
+ public void setActivePage(IEditorPart newEditor) {
+ if (editor == null)
+ return;
+ IFormPage oldPage = page;
+ IFormPage newPage = editor.getActivePageInstance();
+ this.page = newPage;
+ if (newPage == null)
+ return;
+ updateActions();
+ if (oldPage != null && oldPage.isEditor() == false
+ && newPage.isEditor() == false) {
+ getActionBars().updateActionBars();
+ return;
+ }
+ PDESourcePage sourcePage = null;
+ if (newPage instanceof PDESourcePage)
+ sourcePage = (PDESourcePage) newPage;
+ if (sourcePage != null && sourcePage.equals(oldPage))
+ return;
+ sourceContributor.setActiveEditor(sourcePage);
+ setSourceActionBarsActive(sourcePage != null);
+ }
+ private void setSourceActionBarsActive(boolean active) {
+ IActionBars rootBars = getActionBars();
+ rootBars.clearGlobalActionHandlers();
+ //PlatformUI.getWorkbench().getCommandSupport().removeHandlerSubmissions(new ArrayList());
+ rootBars.updateActionBars();
+ if (active) {
+ sourceActionBars.activate();
+ Map handlers = sourceActionBars.getGlobalActionHandlers();
+ if (handlers != null) {
+ Set keys = handlers.keySet();
+ for (Iterator iter = keys.iterator(); iter.hasNext();) {
+ String id = (String) iter.next();
+ rootBars.setGlobalActionHandler(id, (IAction) handlers
+ .get(id));
+ }
+ }
+ } else {
+ sourceActionBars.deactivate();
+ registerGlobalActionHandlers();
+ }
+ rootBars.updateActionBars();
+ }
+ private void registerGlobalActionHandlers() {
+ registerGlobalAction(ActionFactory.DELETE.getId());
+ registerGlobalAction(ActionFactory.UNDO.getId());
+ registerGlobalAction(ActionFactory.REDO.getId());
+ registerGlobalAction(ActionFactory.CUT.getId());
+ registerGlobalAction(ActionFactory.COPY.getId());
+ registerGlobalAction(ActionFactory.PASTE.getId());
+ registerGlobalAction(ActionFactory.SELECT_ALL.getId());
+ registerGlobalAction(ActionFactory.FIND.getId());
+ // hook revert
+ getActionBars().setGlobalActionHandler(ActionFactory.REVERT.getId(), revertAction);
+ }
+ private void registerGlobalAction(String id) {
+ IAction action = getGlobalAction(id);
+ getActionBars().setGlobalActionHandler(id, action);
+ }
+ public void updateActions() {
+ saveAction.update();
+ revertAction.update();
+ }
+ public void updateSelectableActions(ISelection selection) {
+ if (editor != null) {
+ cutAction.selectionChanged(selection);
+ copyAction.selectionChanged(selection);
+ pasteAction.selectionChanged(selection);
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormPage.java
new file mode 100755
index 0000000..352badb
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormPage.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+
+public abstract class PDEFormPage extends FormPage {
+ /**
+ * @param editor
+ * @param id
+ * @param title
+ */
+ public PDEFormPage(FormEditor editor, String id, String title) {
+ super(editor, id, title);
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ final ScrolledForm form = managedForm.getForm();
+ //form.setBackgroundImage(PDEPlugin.getDefault().getLabelProvider().get(
+ // PDEPluginImages.DESC_FORM_BANNER));
+ final String href = getHelpResource();
+ if (href != null) {
+ IToolBarManager manager = form.getToolBarManager();
+ Action helpAction = new Action("help") { //$NON-NLS-1$
+ public void run() {
+ BusyIndicator.showWhile(form.getDisplay(), new Runnable() {
+ public void run() {
+ PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(href);
+ }
+ });
+ }
+ };
+ helpAction.setToolTipText(PDEUIMessages.PDEFormPage_help);
+ helpAction.setImageDescriptor(PDEPluginImages.DESC_HELP);
+ manager.add(helpAction);
+ form.updateToolBar();
+ }
+ }
+ public PDEFormEditor getPDEEditor() {
+ return (PDEFormEditor) getEditor();
+ }
+ protected String getHelpResource() {
+ return null;
+ }
+ public IBaseModel getModel() {
+ return getPDEEditor().getAggregateModel();
+ }
+ public void contextMenuAboutToShow(IMenuManager menu) {
+ }
+
+ protected Control getFocusControl() {
+ IManagedForm form = getManagedForm();
+ if (form == null)
+ return null;
+ Control control = form.getForm();
+ if (control == null || control.isDisposed())
+ return null;
+ Display display = control.getDisplay();
+ Control focusControl = display.getFocusControl();
+ if (focusControl == null || focusControl.isDisposed())
+ return null;
+ return focusControl;
+ }
+ public boolean performGlobalAction(String actionId) {
+ Control focusControl = getFocusControl();
+ if (focusControl == null)
+ return false;
+
+ if (canPerformDirectly(actionId, focusControl))
+ return true;
+ AbstractFormPart focusPart = getFocusSection();
+ if (focusPart!=null) {
+ if (focusPart instanceof PDESection)
+ return ((PDESection)focusPart).doGlobalAction(actionId);
+ if (focusPart instanceof PDEDetails)
+ return ((PDEDetails)focusPart).doGlobalAction(actionId);
+ }
+ return false;
+ }
+
+ public boolean canPaste(Clipboard clipboard) {
+ AbstractFormPart focusPart = getFocusSection();
+ if (focusPart != null) {
+ if (focusPart instanceof PDESection) {
+ return ((PDESection)focusPart).canPaste(clipboard);
+ }
+ if (focusPart instanceof PDEDetails) {
+ return ((PDEDetails)focusPart).canPaste(clipboard);
+ }
+ }
+ return false;
+ }
+
+ private AbstractFormPart getFocusSection() {
+ Control focusControl = getFocusControl();
+ if (focusControl == null)
+ return null;
+ Composite parent = focusControl.getParent();
+ AbstractFormPart targetPart = null;
+ while (parent != null) {
+ Object data = parent.getData("part"); //$NON-NLS-1$
+ if (data != null && data instanceof AbstractFormPart) {
+ targetPart = (AbstractFormPart) data;
+ break;
+ }
+ parent = parent.getParent();
+ }
+ return targetPart;
+ }
+ public IPropertySheetPage getPropertySheetPage() {
+ return null;
+ }
+ protected boolean canPerformDirectly(String id, Control control) {
+ if (control instanceof Text) {
+ Text text = (Text) control;
+ if (id.equals(ActionFactory.CUT.getId())) {
+ text.cut();
+ return true;
+ }
+ if (id.equals(ActionFactory.COPY.getId())) {
+ text.copy();
+ return true;
+ }
+ if (id.equals(ActionFactory.PASTE.getId())) {
+ text.paste();
+ return true;
+ }
+ if (id.equals(ActionFactory.SELECT_ALL.getId())) {
+ text.selectAll();
+ return true;
+ }
+ if (id.equals(ActionFactory.DELETE.getId())) {
+ int count = text.getSelectionCount();
+ if (count == 0) {
+ int caretPos = text.getCaretPosition();
+ text.setSelection(caretPos, caretPos + 1);
+ }
+ text.insert(""); //$NON-NLS-1$
+ return true;
+ }
+ }
+ return false;
+ }
+ public void cancelEdit() {
+ IFormPart [] parts = getManagedForm().getParts();
+ for (int i=0; i<parts.length; i++) {
+ IFormPart part = parts[i];
+ if (part instanceof IContextPart)
+ ((IContextPart)part).cancelEdit();
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMasterDetailsBlock.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMasterDetailsBlock.java
new file mode 100644
index 0000000..4dd4c4a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMasterDetailsBlock.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.*;
+import org.eclipse.ui.forms.widgets.*;
+
+public abstract class PDEMasterDetailsBlock extends MasterDetailsBlock {
+ private PDEFormPage page;
+
+ public PDEMasterDetailsBlock(PDEFormPage page) {
+ this.page = page;
+ }
+
+ public PDEFormPage getPage() {
+ return page;
+ }
+
+ protected abstract PDESection createMasterSection(IManagedForm managedForm, Composite parent);
+
+ protected void createMasterPart(final IManagedForm managedForm,
+ Composite parent) {
+ PDESection section = createMasterSection(managedForm, parent);
+ managedForm.addPart(section);
+ Section sc = section.getSection();
+ sc.marginWidth = 5;
+ sc.marginHeight = 5;
+ }
+ protected void createToolBarActions(IManagedForm managedForm) {
+ final ScrolledForm form = managedForm.getForm();
+
+ Action haction = new Action("hor", Action.AS_RADIO_BUTTON) { //$NON-NLS-1$
+ public void run() {
+ sashForm.setOrientation(SWT.HORIZONTAL);
+ form.reflow(true);
+ }
+ };
+ haction.setChecked(true);
+ haction.setToolTipText(PDEUIMessages.DetailsBlock_horizontal);
+ haction.setImageDescriptor(PDEPluginImages.DESC_HORIZONTAL);
+ haction.setDisabledImageDescriptor(PDEPluginImages.DESC_HORIZONTAL_DISABLED);
+
+ Action vaction = new Action("ver", Action.AS_RADIO_BUTTON) { //$NON-NLS-1$
+ public void run() {
+ sashForm.setOrientation(SWT.VERTICAL);
+ form.reflow(true);
+ }
+ };
+ vaction.setChecked(false);
+ vaction.setToolTipText(PDEUIMessages.DetailsBlock_vertical);
+ vaction.setImageDescriptor(PDEPluginImages.DESC_VERTICAL);
+ vaction.setDisabledImageDescriptor(PDEPluginImages.DESC_VERTICAL_DISABLED);
+ form.getToolBarManager().add(haction);
+ form.getToolBarManager().add(vaction);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPageContentOutline.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPageContentOutline.java
new file mode 100755
index 0000000..375ab50
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPageContentOutline.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.pde.internal.ui.IHelpContextIds;
+import org.eclipse.pde.internal.ui.IPreferenceConstants;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.Page;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+public class PDEMultiPageContentOutline extends Page
+ implements IContentOutlinePage, ISelectionProvider, ISelectionChangedListener, IPreferenceConstants {
+ private PageBook pagebook;
+ private ISelection selection;
+ private ArrayList listeners;
+ private ISortableContentOutlinePage currentPage;
+ private ISortableContentOutlinePage emptyPage;
+ private IActionBars actionBars;
+ private boolean sortingOn;
+ private PDEFormEditor editor;
+
+ public PDEMultiPageContentOutline(PDEFormEditor editor) {
+ this.editor=editor;
+ listeners = new ArrayList();
+ sortingOn= PDEPlugin.getDefault().getPreferenceStore().getBoolean("PDEMultiPageContentOutline.SortingAction.isChecked"); //$NON-NLS-1$
+
+ }
+
+ public void addFocusListener(FocusListener listener) {
+ }
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ listeners.add(listener);
+ }
+ public void createControl(Composite parent) {
+ pagebook = new PageBook(parent, SWT.NONE);
+ }
+
+ public void dispose() {
+ if (pagebook != null && !pagebook.isDisposed())
+ pagebook.dispose();
+ if (emptyPage!=null) {
+ emptyPage.dispose();
+ emptyPage=null;
+ }
+ pagebook = null;
+ listeners = null;
+ }
+
+ public boolean isDisposed() {
+ return listeners==null;
+ }
+
+ public Control getControl() {
+ return pagebook;
+ }
+ public PageBook getPagebook() {
+ return pagebook;
+ }
+ public ISelection getSelection() {
+ return selection;
+ }
+ public void makeContributions(
+ IMenuManager menuManager,
+ IToolBarManager toolBarManager,
+ IStatusLineManager statusLineManager) {
+ }
+ public void removeFocusListener(FocusListener listener) {
+ }
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+ listeners.remove(listener);
+ }
+ public void selectionChanged(SelectionChangedEvent event) {
+ setSelection(event.getSelection());
+ }
+
+ public void setActionBars(IActionBars actionBars) {
+ this.actionBars = actionBars;
+ registerToolbarActions(actionBars);
+ if (currentPage != null)
+ setPageActive(currentPage);
+
+ }
+ public IActionBars getActionBars() {
+ return actionBars;
+ }
+ public void setFocus() {
+ if (currentPage != null)
+ currentPage.setFocus();
+ }
+ private ISortableContentOutlinePage getEmptyPage() {
+ if (emptyPage==null)
+ emptyPage = new EmptyOutlinePage();
+ return emptyPage;
+ }
+ public void setPageActive(ISortableContentOutlinePage page) {
+ if (page==null) {
+ page = getEmptyPage();
+ }
+ if (currentPage != null) {
+ currentPage.removeSelectionChangedListener(this);
+ }
+ //page.init(getSite());
+ page.sort(sortingOn);
+ page.addSelectionChangedListener(this);
+ this.currentPage = page;
+ if (pagebook == null) {
+ // still not being made
+ return;
+ }
+ Control control = page.getControl();
+ if (control == null || control.isDisposed()) {
+ // first time
+ page.createControl(pagebook);
+ page.setActionBars(getActionBars());
+ control = page.getControl();
+ }
+ pagebook.showPage(control);
+ this.currentPage = page;
+ }
+ /**
+ * Set the selection.
+ */
+ public void setSelection(ISelection selection) {
+ this.selection =selection;
+ if (listeners == null)
+ return;
+ SelectionChangedEvent e = new SelectionChangedEvent(this, selection);
+ for (int i=0; i<listeners.size(); i++) {
+ ((ISelectionChangedListener)listeners.get(i)).selectionChanged(e);
+ }
+ }
+ private void registerToolbarActions(IActionBars actionBars) {
+
+ IToolBarManager toolBarManager= actionBars.getToolBarManager();
+ if (toolBarManager != null) {
+ toolBarManager.add(new ToggleLinkWithEditorAction(editor));
+ toolBarManager.add(new SortingAction());
+ }
+ }
+
+ class SortingAction extends Action {
+
+ public SortingAction() {
+ super();
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IHelpContextIds.OUTLINE_SORT_ACTION);
+ setText(PDEUIMessages.PDEMultiPageContentOutline_SortingAction_label);
+ setImageDescriptor(PDEPluginImages.DESC_ALPHAB_SORT_CO);
+ setDisabledImageDescriptor(PDEPluginImages.DESC_ALPHAB_SORT_CO_DISABLED);
+ setToolTipText(PDEUIMessages.PDEMultiPageContentOutline_SortingAction_tooltip);
+ setDescription(PDEUIMessages.PDEMultiPageContentOutline_SortingAction_description);
+ setChecked(sortingOn);
+ }
+
+ public void run() {
+ setChecked(isChecked());
+ valueChanged(isChecked());
+ }
+ private void valueChanged(final boolean on) {
+ sortingOn=on;
+ if(currentPage!=null)
+ currentPage.sort(on);
+ PDEPlugin.getDefault().getPreferenceStore().setValue("PDEMultiPageContentOutline.SortingAction.isChecked", on); //$NON-NLS-1$
+ }
+
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPagePropertySheet.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPagePropertySheet.java
new file mode 100755
index 0000000..fa51492
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPagePropertySheet.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ui.*;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.ui.part.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.views.properties.*;
+import org.eclipse.swt.*;
+import java.util.*;
+
+public class PDEMultiPagePropertySheet implements IPropertySheetPage {
+ private PageBook pagebook;
+ private Hashtable recMap = new Hashtable();
+ private PropertySheetPage defaultPage;
+ private IActionBars actionBars;
+ private IPropertySheetPage currentPage;
+ private boolean disposed = false;
+
+ class PageRec {
+ IPropertySheetPage page;
+ SubActionBars bars;
+ void setBarsActive(boolean active) {
+ if (active)
+ bars.activate();
+ else
+ bars.deactivate();
+ }
+ void dispose() {
+ if (bars!=null) {
+ bars.dispose();
+ bars = null;
+ }
+ if (page!=null) {
+ page.dispose();
+ page = null;
+ }
+ }
+ }
+
+ public PDEMultiPagePropertySheet() {
+ defaultPage = new PropertySheetPage();
+ }
+
+ public void createControl(Composite parent) {
+ disposed = false;
+ pagebook = new PageBook(parent, SWT.NULL);
+ defaultPage.createControl(pagebook);
+ if (currentPage != null)
+ setPageActive(currentPage);
+ }
+ private PageRec createPageRec(IPropertySheetPage page) {
+ if (actionBars == null)
+ return null;
+ PageRec rec = new PageRec();
+ rec.page = page;
+
+ rec.bars = new SubActionBars(actionBars);
+ getPageControl(page);
+
+ page.setActionBars(rec.bars);
+ recMap.put(page, rec);
+ return rec;
+ }
+ public void dispose() {
+ updateActionBars();
+
+ for (Enumeration enm=recMap.elements(); enm.hasMoreElements();) {
+ PageRec rec = (PageRec)enm.nextElement();
+ rec.dispose();
+ }
+ recMap.clear();
+
+ if (pagebook != null && !pagebook.isDisposed()) {
+ pagebook.dispose();
+ }
+ if (defaultPage!=null) {
+ defaultPage.dispose();
+ defaultPage=null;
+ }
+ pagebook = null;
+ disposed = true;
+ }
+
+ public boolean isDisposed() {
+ return disposed;
+ }
+
+ public Control getControl() {
+ return pagebook;
+ }
+
+ public void closeActiveEditor() {
+ if (currentPage==null) return;
+ }
+
+ private Control getPageControl(IPropertySheetPage page) {
+ Control control = page.getControl();
+ if (control == null || control.isDisposed()) {
+ // first time
+ page.createControl(pagebook);
+ control = page.getControl();
+ }
+ return control;
+ }
+ public void selectionChanged(IWorkbenchPart part, ISelection sel) {
+ if (currentPage != null)
+ currentPage.selectionChanged(part, sel);
+ }
+ public void setActionBars(IActionBars bars) {
+ this.actionBars = bars;
+
+ createPageRec(defaultPage);
+
+ if (currentPage != null) {
+ PageRec rec = createPageRec(currentPage);
+ setPageActive(rec);
+ updateActionBars();
+ }
+ }
+ public void setDefaultPageActive() {
+ setPageActive(defaultPage);
+ }
+ public void setFocus() {
+ if (currentPage != null)
+ currentPage.setFocus();
+ }
+ private void setPageActive(PageRec pageRec) {
+ IPropertySheetPage page = pageRec.page;
+ Control control = getPageControl(page);
+ pagebook.showPage(control);
+ pageRec.setBarsActive(true);
+ }
+ public void setPageActive(IPropertySheetPage page) {
+ IPropertySheetPage oldPage = currentPage;
+ this.currentPage = page;
+ if (pagebook == null) {
+ // still not being made
+ return;
+ }
+ if (oldPage != null) {
+ PageRec oldRec = (PageRec) recMap.get(oldPage);
+ if (oldRec != null) {
+ oldRec.setBarsActive(false);
+ }
+ }
+ PageRec rec = (PageRec) recMap.get(page);
+ if (rec == null) {
+ rec = createPageRec(page);
+ }
+ if (rec != null) {
+ setPageActive(rec);
+ updateActionBars();
+ }
+ }
+ private void updateActionBars() {
+ refreshGlobalActionHandlers();
+ actionBars.updateActionBars();
+ }
+ private void refreshGlobalActionHandlers() {
+ // Clear old actions.
+ actionBars.clearGlobalActionHandlers();
+
+ // Set new actions.
+ if (recMap == null || currentPage == null)
+ return;
+ PageRec activeRec = (PageRec) recMap.get(currentPage);
+ Map newActionHandlers = activeRec.bars.getGlobalActionHandlers();
+ if (newActionHandlers != null) {
+ Set keys = newActionHandlers.entrySet();
+ Iterator iter = keys.iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ actionBars.setGlobalActionHandler(
+ (String) entry.getKey(),
+ (IAction) entry.getValue());
+ }
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESection.java
new file mode 100755
index 0000000..83bbb80
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESection.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.pde.core.*;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.SectionPart;
+import org.eclipse.ui.forms.widgets.*;
+
+public abstract class PDESection extends SectionPart implements IModelChangedListener, IContextPart {
+ public static final int CLIENT_VSPACING = 4;
+ private PDEFormPage page;
+ public PDESection(PDEFormPage page, Composite parent, int style) {
+ this(page, parent, style, true);
+ }
+ /**
+ * @param section
+ *
+ */
+ public PDESection(PDEFormPage page, Composite parent, int style, boolean titleBar) {
+ super(parent, page.getManagedForm().getToolkit(), titleBar?(ExpandableComposite.TITLE_BAR | style): style);
+ this.page = page;
+ initialize(page.getManagedForm());
+ getSection().clientVerticalSpacing = CLIENT_VSPACING;
+ getSection().setData("part", this); //$NON-NLS-1$
+ //createClient(getSection(), page.getManagedForm().getToolkit());
+ }
+
+ protected abstract void createClient(Section section, FormToolkit toolkit);
+
+ public PDEFormPage getPage() {
+ return page;
+ }
+
+ public boolean doGlobalAction(String actionId) {
+ return false;
+ }
+
+ public void modelChanged(IModelChangedEvent e) {
+ if (e.getChangeType()==IModelChangedEvent.WORLD_CHANGED)
+ markStale();
+ }
+
+ public String getContextId() {
+ return null;
+ }
+ public void fireSaveNeeded() {
+ markDirty();
+ if (getContextId()!=null)
+ getPage().getPDEEditor().fireSaveNeeded(getContextId(), false);
+ }
+ public boolean isEditable() {
+ return getPage().getPDEEditor().getAggregateModel().isEditable();
+ }
+ public boolean canPaste(Clipboard clipboard) {
+ return false;
+ }
+ public void cancelEdit() {
+ super.refresh();
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESourcePage.java
new file mode 100755
index 0000000..7b6057b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESourcePage.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Jan 26, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.pde.internal.core.text.IDocumentRange;
+import org.eclipse.pde.internal.core.text.IEditingModel;
+import org.eclipse.pde.internal.ui.IHelpContextIds;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.DefaultRangeIndicator;
+
+public abstract class PDESourcePage extends TextEditor implements IFormPage, IGotoMarker {
+ /**
+ * Updates the OutlinePage selection and this editor's range indicator.
+ *
+ * @since 3.0
+ */
+ private class PDESourcePageChangedListener implements
+ ISelectionChangedListener {
+
+ /**
+ * Installs this selection changed listener with the given selection
+ * provider. If the selection provider is a post selection provider,
+ * post selection changed events are the preferred choice, otherwise
+ * normal selection changed events are requested.
+ *
+ * @param selectionProvider
+ */
+ public void install(ISelectionProvider selectionProvider) {
+ if (selectionProvider == null) {
+ return;
+ }
+
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+ provider.addPostSelectionChangedListener(this);
+ } else {
+ selectionProvider.addSelectionChangedListener(this);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if (!selection.isEmpty() && selection instanceof ITextSelection) {
+ IDocumentRange rangeElement = getRangeElement((ITextSelection) selection);
+ if (rangeElement != null) {
+ setHighlightRange(rangeElement, false);
+ } else {
+ resetHighlightRange();
+ }
+ // notify outline page
+ if (PDEPlugin.getDefault().getPreferenceStore().getBoolean(
+ "ToggleLinkWithEditorAction.isChecked")) { //$NON-NLS-1$
+ outlinePage
+ .removeSelectionChangedListener(outlineSelectionChangedListener);
+ if (rangeElement != null) {
+ outlinePage.setSelection(new StructuredSelection(
+ rangeElement));
+ } else {
+ outlinePage.setSelection(StructuredSelection.EMPTY);
+ }
+ outlinePage
+ .addSelectionChangedListener(outlineSelectionChangedListener);
+ }
+ }
+ }
+
+ /**
+ * Removes this selection changed listener from the given selection
+ * provider.
+ *
+ * @param selectionProviderstyle
+ */
+ public void uninstall(ISelectionProvider selectionProvider) {
+ if (selectionProvider == null) {
+ return;
+ }
+
+ if (selectionProvider instanceof IPostSelectionProvider) {
+ IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+ provider.removePostSelectionChangedListener(this);
+ } else {
+ selectionProvider.removeSelectionChangedListener(this);
+ }
+ }
+
+ }
+
+ /**
+ * The editor selection changed listener.
+ *
+ * @since 3.0
+ */
+ private PDESourcePageChangedListener fEditorSelectionChangedListener;
+ private PDEFormEditor editor;
+ private Control control;
+ private int index;
+ private String id;
+ private InputContext inputContext;
+ private ISortableContentOutlinePage outlinePage;
+ private ISelectionChangedListener outlineSelectionChangedListener;
+ /**
+ *
+ */
+ public PDESourcePage(PDEFormEditor editor, String id, String title) {
+ this.id = id;
+ initialize(editor);
+ IPreferenceStore[] stores = new IPreferenceStore[2];
+ stores[0] = PDEPlugin.getDefault().getPreferenceStore();
+ stores[1] = EditorsUI.getPreferenceStore();
+ setPreferenceStore(new ChainedPreferenceStore(stores));
+ setRangeIndicator(new DefaultRangeIndicator());
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#initialize(org.eclipse.ui.forms.editor.FormEditor)
+ */
+ public void initialize(FormEditor editor) {
+ this.editor = (PDEFormEditor)editor;
+ }
+ public void dispose() {
+ if (fEditorSelectionChangedListener != null) {
+ fEditorSelectionChangedListener.uninstall(getSelectionProvider());
+ fEditorSelectionChangedListener= null;
+ }
+ if (outlinePage != null) {
+ outlinePage.dispose();
+ outlinePage = null;
+ }
+ super.dispose();
+ }
+
+ protected void editorSaved() {
+ super.editorSaved();
+ }
+
+ protected abstract ILabelProvider createOutlineLabelProvider();
+ protected abstract ITreeContentProvider createOutlineContentProvider();
+ protected abstract ViewerSorter createOutlineSorter();
+ protected abstract void outlineSelectionChanged(SelectionChangedEvent e);
+ protected ViewerSorter createDefaultOutlineSorter() {
+ return null;
+ }
+ protected ISortableContentOutlinePage createOutlinePage() {
+ SourceOutlinePage sourceOutlinePage=
+ new SourceOutlinePage(
+ (IEditingModel) getInputContext().getModel(),
+ createOutlineLabelProvider(), createOutlineContentProvider(),
+ createDefaultOutlineSorter(), createOutlineSorter());
+ outlinePage = sourceOutlinePage;
+ outlineSelectionChangedListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ outlineSelectionChanged(event);
+ }
+ };
+ outlinePage.addSelectionChangedListener(outlineSelectionChangedListener);
+ getSelectionProvider().addSelectionChangedListener(sourceOutlinePage);
+ fEditorSelectionChangedListener= new PDESourcePageChangedListener();
+ fEditorSelectionChangedListener.install(getSelectionProvider());
+ return outlinePage;
+ }
+
+ public ISortableContentOutlinePage getContentOutline() {
+ if (outlinePage==null)
+ outlinePage = createOutlinePage();
+ return outlinePage;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#getEditor()
+ */
+ public FormEditor getEditor() {
+ return editor;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#getManagedForm()
+ */
+ public IManagedForm getManagedForm() {
+ // not a form page
+ return null;
+ }
+ protected void firePropertyChange(int type) {
+ if (type == PROP_DIRTY) {
+ editor.fireSaveNeeded(getEditorInput(), true);
+ } else
+ super.firePropertyChange(type);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#setActive(boolean)
+ */
+ public void setActive(boolean active) {
+ inputContext.setSourceEditingMode(active);
+ }
+
+ public boolean canLeaveThePage() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#isActive()
+ */
+ public boolean isActive() {
+ return this.equals(editor.getActivePageInstance());
+ }
+ public void createPartControl(Composite parent) {
+ super.createPartControl(parent);
+ Control[] children = parent.getChildren();
+ control = children[children.length - 1];
+
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(control, IHelpContextIds.MANIFEST_SOURCE_PAGE);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#getPartControl()
+ */
+ public Control getPartControl() {
+ return control;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#getId()
+ */
+ public String getId() {
+ return id;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#getIndex()
+ */
+ public int getIndex() {
+ return index;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#setIndex(int)
+ */
+ public void setIndex(int index) {
+ this.index = index;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#isSource()
+ */
+ public boolean isEditor() {
+ return true;
+ }
+ /**
+ * @return Returns the inputContext.
+ */
+ public InputContext getInputContext() {
+ return inputContext;
+ }
+ /**
+ * @param inputContext The inputContext to set.
+ */
+ public void setInputContext(InputContext inputContext) {
+ this.inputContext = inputContext;
+ setDocumentProvider(inputContext.getDocumentProvider());
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.editor.IFormPage#focusOn(java.lang.Object)
+ */
+ public boolean selectReveal(Object object) {
+ if (object instanceof IMarker) {
+ IDE.gotoMarker(this, (IMarker)object);
+ return true;
+ }
+ return false;
+ }
+
+ protected IDocumentRange getRangeElement(ITextSelection selection) {
+ return null;
+ }
+
+ public void setHighlightRange(IDocumentRange node, boolean moveCursor) {
+ ISourceViewer sourceViewer = getSourceViewer();
+ if (sourceViewer == null)
+ return;
+
+ IDocument document = sourceViewer.getDocument();
+ if (document == null)
+ return;
+
+ int offset = node.getOffset();
+ int length = node.getLength();
+ setHighlightRange(offset, length == -1 ? 1 : length, moveCursor);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PropertiesAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PropertiesAction.java
new file mode 100644
index 0000000..602a699
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PropertiesAction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.ui.*;
+
+public class PropertiesAction extends Action {
+ private PDEFormEditor editor;
+ public PropertiesAction(PDEFormEditor editor) {
+ this.editor = editor;
+ setText(PDEUIMessages.Actions_properties_label);
+ setImageDescriptor(PDEPluginImages.DESC_PROPERTIES);
+ setDisabledImageDescriptor(PDEPluginImages.DESC_PROPERTIES_DISABLED);
+ }
+ public void run() {
+ try {
+ String viewId = IPageLayout.ID_PROP_SHEET;
+ IWorkbenchPage perspective = PDEPlugin.getActivePage();
+ IViewPart view = perspective.showView(viewId);
+ editor.updatePropertySheet(editor.getActivePageInstance());
+ perspective.activate(editor);
+ perspective.bringToTop(view);
+ } catch (PartInitException e) {
+ PDEPlugin.logException(e);
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SourceOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SourceOutlinePage.java
new file mode 100755
index 0000000..461a9ba
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SourceOutlinePage.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.pde.internal.core.text.IEditingModel;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.part.IPageSite;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+/**
+ * Content outline page for the XML editor.
+ */
+public class SourceOutlinePage extends ContentOutlinePage implements IReconcilingParticipant, ISortableContentOutlinePage{
+
+ private IEditingModel fModel;
+ private IBaseLabelProvider fLabelProvider;
+ private IContentProvider fContentProvider;
+ private ViewerSorter fDefaultSorter;
+ private ViewerSorter fViewerSorter;
+ private boolean sorted;
+ TreeViewer viewer;
+
+ public SourceOutlinePage(IEditingModel model, IBaseLabelProvider lProvider,
+ IContentProvider cProvider, ViewerSorter defaultSorter,
+ ViewerSorter sorter) {
+ super();
+ fModel = model;
+ fLabelProvider = lProvider;
+ fContentProvider = cProvider;
+ fDefaultSorter = defaultSorter;
+ fViewerSorter = sorter;
+ }
+
+ /**
+ * Creates the control for this outline page.
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ viewer= getTreeViewer();
+ viewer.setContentProvider(fContentProvider);
+ viewer.setLabelProvider(fLabelProvider);
+ if(sorted)
+ viewer.setSorter(fViewerSorter);
+ else
+ viewer.setSorter(fDefaultSorter);
+ viewer.setInput(fModel);
+ viewer.expandAll();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.views.contentoutline.ContentOutlinePage#init(org.eclipse.ui.part.IPageSite)
+ */
+ public void init(IPageSite pageSite) {
+ super.init(pageSite);
+ }
+
+ public void makeContributions(
+ IMenuManager menuManager,
+ IToolBarManager toolBarManager,
+ IStatusLineManager statusLineManager) {
+ //Create actions and contribute into the provided managers
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.editor.text.IReconcilingParticipant#reconciled(org.eclipse.jface.text.IDocument)
+ */
+ public void reconciled(IDocument document) {
+ final Control control = getControl();
+ if (control == null)
+ return;
+ control.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if(control.isDisposed()){
+ return;
+ }
+ control.setRedraw(false);
+ getTreeViewer().refresh();
+ getTreeViewer().expandAll();
+ control.setRedraw(true);
+ }
+ });
+ }
+ public void sort (boolean sorting){
+ sorted = sorting;
+ if(viewer!=null)
+ if(sorting)
+ viewer.setSorter(fViewerSorter);
+ else
+ viewer.setSorter(fDefaultSorter);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StorageDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StorageDocumentProvider.java
new file mode 100644
index 0000000..4eae315
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StorageDocumentProvider.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.ui.IStorageEditorInput;
+
+public class StorageDocumentProvider extends StreamDocumentProvider {
+
+ public StorageDocumentProvider(IDocumentPartitioner partitioner) {
+ this(partitioner, null);
+ }
+
+ public StorageDocumentProvider(
+ IDocumentPartitioner partitioner,
+ String encoding) {
+ super(partitioner, encoding);
+ }
+
+ protected IDocument createDocument(Object element) throws CoreException {
+ if (element instanceof IStorageEditorInput) {
+ IDocument document = createEmptyDocument();
+ IDocumentPartitioner part = getPartitioner();
+ if (part != null) {
+ part.connect(document);
+ document.setDocumentPartitioner(part);
+ }
+ IStorage storage = ((IStorageEditorInput)element).getStorage();
+ setDocumentContent(document, storage);
+ return document;
+ }
+ return null;
+ }
+ protected void setDocumentContent(IDocument document, IStorage storage) {
+ try {
+ InputStream contentStream = storage.getContents();
+ setDocumentContent(document, contentStream);
+ contentStream.close();
+ } catch (Exception e) {
+ PDEPlugin.logException(e);
+ }
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StreamDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StreamDocumentProvider.java
new file mode 100644
index 0000000..fe5defe
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StreamDocumentProvider.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+
+import org.eclipse.jface.operation.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.text.source.*;
+import org.eclipse.ui.texteditor.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public abstract class StreamDocumentProvider extends AbstractDocumentProvider {
+ private IDocumentPartitioner partitioner;
+
+ private String enc;
+
+ public StreamDocumentProvider(IDocumentPartitioner partitioner,
+ String encoding) {
+ this.partitioner = partitioner;
+ this.enc = encoding;
+ }
+
+ protected IDocumentPartitioner getPartitioner() {
+ return partitioner;
+ }
+
+ protected String getEncoding() {
+ return enc;
+ }
+
+ protected IAnnotationModel createAnnotationModel(Object element)
+ throws CoreException {
+ return new SystemFileMarkerAnnotationModel();
+ }
+
+ protected void doSaveDocument(IProgressMonitor monitor, Object element,
+ IDocument document, boolean force) throws CoreException {
+ }
+
+ protected void setDocumentContent(IDocument document,
+ InputStream contentStream) {
+ try {
+ Reader in;
+ if (enc == null)
+ in = new InputStreamReader(contentStream);
+ else
+ in = new InputStreamReader(contentStream, enc);
+ int chunkSize = contentStream.available();
+ StringBuffer buffer = new StringBuffer(chunkSize);
+ char[] readBuffer = new char[chunkSize];
+ int n = in.read(readBuffer);
+ while (n > 0) {
+ buffer.append(readBuffer);
+ n = in.read(readBuffer);
+ }
+ in.close();
+ document.set(buffer.toString());
+
+ } catch (IOException e) {
+ PDEPlugin.logException(e);
+ }
+ }
+
+ public long getSynchronizationStamp(Object element) {
+ return 0;
+ }
+
+ public long getModificationStamp(Object element) {
+ return 0;
+ }
+
+ public boolean isDeleted(Object element) {
+ return false;
+ }
+
+ protected IDocument createEmptyDocument() {
+ return new Document();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getOperationRunner(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
+ // TODO figure out what this method does
+ return null;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StructuredViewerSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StructuredViewerSection.java
new file mode 100755
index 0000000..78ec361
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StructuredViewerSection.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * @version 1.0
+ * @author
+ */
+public abstract class StructuredViewerSection extends PDESection {
+ protected StructuredViewerPart viewerPart;
+ /**
+ * Constructor for StructuredViewerSection.
+ * @param formPage
+ */
+ public StructuredViewerSection(PDEFormPage formPage, Composite parent, int style, String [] buttonLabels) {
+ this(formPage, parent, style, true, buttonLabels);
+ }
+
+ /**
+ * Constructor for StructuredViewerSection.
+ * @param formPage
+ */
+ public StructuredViewerSection(PDEFormPage formPage, Composite parent, int style, boolean titleBar, String [] buttonLabels) {
+ super(formPage, parent, style, titleBar);
+ viewerPart = createViewerPart(buttonLabels);
+ viewerPart.setMinimumSize(50, 50);
+ FormToolkit toolkit = formPage.getManagedForm().getToolkit();
+ createClient(getSection(), toolkit);
+ }
+
+ protected void createViewerPartControl(Composite parent, int style, int span, FormToolkit toolkit) {
+ viewerPart.createControl(parent, style, span, toolkit);
+ MenuManager popupMenuManager = new MenuManager();
+ IMenuListener listener = new IMenuListener() {
+ public void menuAboutToShow(IMenuManager mng) {
+ fillContextMenu(mng);
+ }
+ };
+ popupMenuManager.addMenuListener(listener);
+ popupMenuManager.setRemoveAllWhenShown(true);
+ Control control = viewerPart.getControl();
+ Menu menu = popupMenuManager.createContextMenu(control);
+ control.setMenu(menu);
+ }
+
+ protected Composite createClientContainer(Composite parent, int span, FormToolkit toolkit) {
+ Composite container = toolkit.createComposite(parent);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = layout.marginHeight = 2;
+ layout.numColumns = span;
+ container.setLayout(layout);
+ return container;
+ }
+
+ protected abstract StructuredViewerPart createViewerPart(String [] buttonLabels);
+
+ protected void fillContextMenu(IMenuManager manager) {
+ }
+
+ protected void buttonSelected(int index) {
+ }
+
+ protected void doPaste() {
+ ISelection selection = getViewerSelection();
+ IStructuredSelection ssel = (IStructuredSelection)selection;
+ if (ssel.size()>1) return;
+
+ Object target = ssel.getFirstElement();
+
+ Clipboard clipboard = getPage().getPDEEditor().getClipboard();
+ ModelDataTransfer modelTransfer = ModelDataTransfer.getInstance();
+ Object [] objects = (Object[])clipboard.getContents(modelTransfer);
+ if (objects!=null) {
+ doPaste(target, objects);
+ }
+ }
+ public boolean canPaste(Clipboard clipboard) {
+ ISelection selection = getViewerSelection();
+ IStructuredSelection ssel = (IStructuredSelection)selection;
+ if (ssel.size()>1) return false;
+
+ Object target = ssel.getFirstElement();
+ ModelDataTransfer modelTransfer = ModelDataTransfer.getInstance();
+ Object [] objects = (Object[])clipboard.getContents(modelTransfer);
+ if (objects!=null && objects.length>0) {
+ return canPaste(target, objects);
+ }
+ return clipboard.getContents(TextTransfer.getInstance()) != null;
+ }
+ protected ISelection getViewerSelection() {
+ return viewerPart.getViewer().getSelection();
+ }
+ protected void doPaste(Object target, Object[] objects) {
+ }
+
+ protected boolean canPaste(Object target, Object [] objects) {
+ return false;
+ }
+ public void setFocus() {
+ viewerPart.getControl().setFocus();
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileDocumentProvider.java
new file mode 100644
index 0000000..1f3eb55
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileDocumentProvider.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public class SystemFileDocumentProvider extends StreamDocumentProvider {
+
+ public SystemFileDocumentProvider(IDocumentPartitioner partitioner) {
+ this(partitioner, null);
+ }
+
+ public SystemFileDocumentProvider(
+ IDocumentPartitioner partitioner,
+ String encoding) {
+ super(partitioner, encoding);
+ }
+ /*
+ * @see AbstractDocumentProvider#createAnnotationModel(Object)
+ */
+ protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
+ if (element instanceof SystemFileEditorInput) {
+ SystemFileEditorInput input= (SystemFileEditorInput) element;
+ File file = (File)input.getAdapter(File.class);
+ if (file!=null) {
+ return new SystemFileMarkerAnnotationModel();
+ }
+ }
+ return super.createAnnotationModel(element);
+ }
+
+ protected IDocument createDocument(Object element) throws CoreException {
+ if (element instanceof SystemFileEditorInput) {
+ IDocument document = createEmptyDocument();
+ IDocumentPartitioner part = getPartitioner();
+ if (part != null) {
+ part.connect(document);
+ document.setDocumentPartitioner(part);
+ }
+ File file =
+ (File) ((SystemFileEditorInput) element).getAdapter(File.class);
+ setDocumentContent(document, file);
+ return document;
+ }
+ return null;
+ }
+ protected void doSaveDocument(
+ IProgressMonitor monitor,
+ Object element,
+ IDocument document,
+ boolean force)
+ throws CoreException {
+ }
+ protected void setDocumentContent(IDocument document, File file) {
+ try {
+ InputStream contentStream = new FileInputStream(file);
+ setDocumentContent(document, contentStream);
+ contentStream.close();
+ } catch (IOException e) {
+ PDEPlugin.logException(e);
+ }
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInput.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInput.java
new file mode 100755
index 0000000..348898c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInput.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import org.eclipse.ui.*;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public class SystemFileEditorInput implements IStorageEditorInput, IPersistableElement {
+ private SystemFileStorage storage;
+ private static final String FACTORY_ID = PDEPlugin.getPluginId()+".systemFileEditorInputFactory"; //$NON-NLS-1$
+
+ public SystemFileEditorInput(File file) {
+ storage = new SystemFileStorage(file);
+ }
+ public boolean exists() {
+ return storage.getFile().exists();
+ }
+ public Object getAdapter(Class adapter) {
+ if (adapter.equals(File.class))
+ return storage.getFile();
+ return null;
+ }
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+ public String getName() {
+ return storage.getFile().getName();
+ }
+ public IPersistableElement getPersistable() {
+ return this;
+ }
+ public void saveState(IMemento memento) {
+ memento.putString("path", storage.getFile().getAbsolutePath()); //$NON-NLS-1$
+ }
+ public String getFactoryId() {
+ return FACTORY_ID;
+ }
+ public IStorage getStorage() {
+ return storage;
+ }
+ public String getToolTipText() {
+ return storage.getFile().getAbsolutePath();
+ }
+ public boolean equals(Object object) {
+ return object instanceof SystemFileEditorInput &&
+ getStorage().equals(((SystemFileEditorInput)object).getStorage());
+ }
+
+ public int hashCode() {
+ return getStorage().hashCode();
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInputFactory.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInputFactory.java
new file mode 100644
index 0000000..9398501
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInputFactory.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ui.IElementFactory;
+import org.eclipse.ui.IMemento;
+import org.eclipse.core.runtime.IAdaptable;
+import java.io.*;
+
+/**
+ * Insert the type's description here.
+ */
+public class SystemFileEditorInputFactory implements IElementFactory {
+ /**
+ * The constructor.
+ */
+ public SystemFileEditorInputFactory() {
+ }
+
+ public IAdaptable createElement (IMemento memento) {
+ String path = memento.getString("path"); //$NON-NLS-1$
+ File file = new File(path);
+ SystemFileEditorInput input = new SystemFileEditorInput(file);
+ return input;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileMarkerAnnotationModel.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileMarkerAnnotationModel.java
new file mode 100644
index 0000000..464f397
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileMarkerAnnotationModel.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ui.texteditor.*;
+
+/**
+ * A marker annotation model whose underlying source of markers is
+ * a resource in the workspace.
+ * <p>
+ * This class may be instantiated; it is not intended to be subclassed.
+ * </p>
+ */
+public class SystemFileMarkerAnnotationModel
+ extends AbstractMarkerAnnotationModel {
+
+ protected IMarker[] retrieveMarkers() throws CoreException {
+ return null;
+ }
+
+ protected void deleteMarkers(IMarker[] markers) throws CoreException {
+ }
+
+ protected void listenToMarkerChanges(boolean listen) {
+ }
+
+ protected boolean isAcceptable(IMarker marker) {
+ return true;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileStorage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileStorage.java
new file mode 100755
index 0000000..871324f
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileStorage.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public class SystemFileStorage extends PlatformObject implements IStorage {
+ private File file;
+ /**
+ * Constructor for SystemFileStorage.
+ */
+ public SystemFileStorage(File file) {
+ this.file = file;
+ }
+
+ public File getFile() {
+ return file;
+ }
+ public InputStream getContents() throws CoreException {
+ try {
+ return new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ IStatus status =
+ new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.OK, null, e);
+ throw new CoreException(status);
+ }
+ }
+ public IPath getFullPath() {
+ return new Path(file.getAbsolutePath());
+ }
+ public String getName() {
+ return file.getName();
+ }
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public boolean equals(Object object) {
+ return object instanceof SystemFileStorage
+ && getFile().equals(((SystemFileStorage) object).getFile());
+ }
+
+ public int hashCode() {
+ return getFile().hashCode();
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TableSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TableSection.java
new file mode 100755
index 0000000..247bec8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TableSection.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+/**
+ * @version 1.0
+ * @author
+ */
+public abstract class TableSection extends StructuredViewerSection {
+ protected boolean handleDefaultButton = true;
+ class PartAdapter extends EditableTablePart {
+ public PartAdapter(String[] buttonLabels) {
+ super(buttonLabels);
+ }
+ public void entryModified(Object entry, String value) {
+ TableSection.this.entryModified(entry, value);
+ }
+ public void selectionChanged(IStructuredSelection selection) {
+ getManagedForm().fireSelectionChanged(TableSection.this, selection);
+ TableSection.this.selectionChanged(selection);
+ }
+ public void handleDoubleClick(IStructuredSelection selection) {
+ TableSection.this.handleDoubleClick(selection);
+ }
+ public void buttonSelected(Button button, int index) {
+ TableSection.this.buttonSelected(index);
+ if (handleDefaultButton)
+ button.getShell().setDefaultButton(null);
+ }
+ protected void createButtons(Composite parent, FormToolkit toolkit) {
+ super.createButtons(parent, toolkit);
+ enableButtons();
+ }
+ }
+ /**
+ * Constructor for TableSection.
+ *
+ * @param formPage
+ */
+ public TableSection(PDEFormPage formPage, Composite parent, int style,
+ String[] buttonLabels) {
+ this (formPage, parent, style, true, buttonLabels);
+ }
+ /**
+ * Constructor for TableSection.
+ *
+ * @param formPage
+ */
+ public TableSection(PDEFormPage formPage, Composite parent, int style,
+ boolean titleBar, String[] buttonLabels) {
+ super(formPage, parent, style, titleBar, buttonLabels);
+ }
+ protected StructuredViewerPart createViewerPart(String[] buttonLabels) {
+ return new PartAdapter(buttonLabels);
+ }
+ protected IAction getRenameAction() {
+ return getTablePart().getRenameAction();
+ }
+ protected EditableTablePart getTablePart() {
+ return (EditableTablePart) viewerPart;
+ }
+ protected void entryModified(Object entry, String value) {
+ }
+ protected void selectionChanged(IStructuredSelection selection) {
+ }
+ protected void handleDoubleClick(IStructuredSelection selection) {
+ }
+ protected void enableButtons() {
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ToggleLinkWithEditorAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ToggleLinkWithEditorAction.java
new file mode 100755
index 0000000..4f4d7c8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ToggleLinkWithEditorAction.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+
+/**
+ * This action toggles whether the Outline page links its selection to the
+ * active editor.
+ *
+ * @since 3.0
+ */
+public class ToggleLinkWithEditorAction extends Action {
+
+ PDEFormEditor fEditor;
+
+ public ToggleLinkWithEditorAction(PDEFormEditor editor) {
+ super(PDEUIMessages.ToggleLinkWithEditorAction_label);
+ boolean isLinkingEnabled = PDEPlugin.getDefault().getPreferenceStore()
+ .getBoolean("ToggleLinkWithEditorAction.isChecked"); //$NON-NLS-1$
+ setChecked(isLinkingEnabled);
+ fEditor = editor;
+ setToolTipText(PDEUIMessages.ToggleLinkWithEditorAction_toolTip);
+ setDescription(PDEUIMessages.ToggleLinkWithEditorAction_description);
+ setImageDescriptor(PDEPluginImages.DESC_LINK_WITH_EDITOR);
+ setDisabledImageDescriptor(PDEPluginImages.DESC_LINK_WITH_EDITOR_DISABLED);
+ }
+
+ public void run() {
+ PDEPlugin.getDefault().getPreferenceStore().setValue(
+ "ToggleLinkWithEditorAction.isChecked", isChecked()); //$NON-NLS-1$
+ if (isChecked())
+ fEditor.synchronizeOutlinePage();
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TreeSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TreeSection.java
new file mode 100644
index 0000000..e3bdf8b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TreeSection.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * @version 1.0
+ * @author
+ */
+public abstract class TreeSection extends StructuredViewerSection {
+ protected boolean handleDefaultButton=true;
+ class PartAdapter extends TreePart {
+ public PartAdapter(String[] buttonLabels) {
+ super(buttonLabels);
+ }
+ public void selectionChanged(IStructuredSelection selection) {
+ getManagedForm().fireSelectionChanged(TreeSection.this, selection);
+ TreeSection.this.selectionChanged(selection);
+ }
+ public void handleDoubleClick(IStructuredSelection selection) {
+ TreeSection.this.handleDoubleClick(selection);
+ }
+ public void buttonSelected(Button button, int index) {
+ TreeSection.this.buttonSelected(index);
+ if (handleDefaultButton)
+ button.getShell().setDefaultButton(null);
+ }
+ protected void createButtons(Composite parent, FormToolkit toolkit) {
+ super.createButtons(parent, toolkit);
+ enableButtons();
+ }
+ }
+ /**
+ * Constructor for TableSection.
+ * @param formPage
+ */
+ public TreeSection(PDEFormPage formPage, Composite parent, int style, String[] buttonLabels) {
+ super(formPage, parent, style, buttonLabels);
+ }
+
+ protected StructuredViewerPart createViewerPart(String[] buttonLabels) {
+ return new PartAdapter(buttonLabels);
+ }
+
+ protected TreePart getTreePart() {
+ return (TreePart) viewerPart;
+ }
+
+ protected void selectionChanged(IStructuredSelection selection) {
+ }
+ protected void handleDoubleClick(IStructuredSelection selection) {
+ }
+ protected void enableButtons() {
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLConfiguration.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLConfiguration.java
new file mode 100644
index 0000000..d757fbf
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLConfiguration.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+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.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.editor.text.AnnotationHover;
+import org.eclipse.pde.internal.ui.editor.text.BasePDEScanner;
+import org.eclipse.pde.internal.ui.editor.text.ChangeAwareSourceViewerConfiguration;
+import org.eclipse.pde.internal.ui.editor.text.IColorManager;
+import org.eclipse.pde.internal.ui.editor.text.IPDEColorConstants;
+import org.eclipse.pde.internal.ui.editor.text.MultilineDamagerRepairer;
+import org.eclipse.pde.internal.ui.editor.text.XMLPartitionScanner;
+import org.eclipse.pde.internal.ui.editor.text.XMLScanner;
+import org.eclipse.pde.internal.ui.editor.text.XMLTagScanner;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+
+
+public class XMLConfiguration extends ChangeAwareSourceViewerConfiguration {
+ private AnnotationHover fAnnotationHover;
+ private XMLDoubleClickStrategy fDoubleClickStrategy;
+ private XMLTagScanner fTagScanner;
+ private XMLScanner fPdeScanner;
+ private IColorManager fColorManager;
+
+ private TextAttribute fXMLCommentAttr;
+ private MultilineDamagerRepairer fDamagerRepairer;
+
+ public XMLConfiguration(IColorManager colorManager) {
+ super(PDEPlugin.getDefault().getPreferenceStore());
+ fColorManager = colorManager;
+ }
+
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ return new String[] {
+ IDocument.DEFAULT_CONTENT_TYPE,
+ XMLPartitionScanner.XML_COMMENT,
+ XMLPartitionScanner.XML_TAG };
+ }
+
+ public ITextDoubleClickStrategy getDoubleClickStrategy(
+ ISourceViewer sourceViewer,
+ String contentType) {
+ if (fDoubleClickStrategy == null)
+ fDoubleClickStrategy = new XMLDoubleClickStrategy();
+ return fDoubleClickStrategy;
+ }
+
+ protected XMLScanner getPDEScanner() {
+ if (fPdeScanner == null)
+ fPdeScanner = new XMLScanner(fColorManager);
+ return fPdeScanner;
+ }
+
+ protected XMLTagScanner getPDETagScanner() {
+ if (fTagScanner == null)
+ fTagScanner = new XMLTagScanner(fColorManager);
+ return fTagScanner;
+ }
+
+ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+
+ MultilineDamagerRepairer dr = new MultilineDamagerRepairer(getPDEScanner());
+ reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+ dr = new MultilineDamagerRepairer(getPDETagScanner());
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_TAG);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_TAG);
+
+ // TODO: 3.2M3+
+// fXMLCommentAttr = BasePDEScanner.createTextAttribute(fColorManager, IPDEColorConstants.P_XML_COMMENT);
+ fDamagerRepairer = new MultilineDamagerRepairer(null, fXMLCommentAttr);
+ reconciler.setDamager(fDamagerRepairer, XMLPartitionScanner.XML_COMMENT);
+ reconciler.setRepairer(fDamagerRepairer, XMLPartitionScanner.XML_COMMENT);
+
+ return reconciler;
+ }
+
+ public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+ if (fAnnotationHover == null)
+ fAnnotationHover = new AnnotationHover();
+ return fAnnotationHover;
+ }
+
+ public IColorManager getColorManager(){
+ return fColorManager;
+ }
+
+ /**
+ * Preference colors or fonts have changed.
+ * Update the default tokens of the scanners.
+ */
+ public void adaptToPreferenceChange(PropertyChangeEvent event) {
+ if (fTagScanner == null)
+ return; //property change before the editor is fully created
+ if (affectsColorPresentation(event))
+ fColorManager.handlePropertyChangeEvent(event);
+ fTagScanner.adaptToPreferenceChange(event);
+ fPdeScanner.adaptToPreferenceChange(event);
+ String property= event.getProperty();
+ if (property.startsWith(IPDEColorConstants.P_XML_COMMENT)) {
+ adaptTextAttribute(event);
+ }
+ }
+
+ private void adaptTextAttribute(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.endsWith(IPDEColorConstants.P_BOLD_SUFFIX)) {
+ fXMLCommentAttr = adaptToStyleChange(event, SWT.BOLD, fXMLCommentAttr);
+ } else if (property.endsWith(IPDEColorConstants.P_ITALIC_SUFFIX)) {
+ fXMLCommentAttr = adaptToStyleChange(event, SWT.ITALIC, fXMLCommentAttr);
+ } else {
+ fXMLCommentAttr = new TextAttribute(fColorManager.getColor(event.getProperty()),
+ fXMLCommentAttr.getBackground(),
+ fXMLCommentAttr.getStyle());
+ }
+ fDamagerRepairer.setDefaultTextAttribute(fXMLCommentAttr);
+ }
+
+ private TextAttribute adaptToStyleChange(PropertyChangeEvent event, int styleAttribute, TextAttribute textAttribute) {
+ boolean eventValue = false;
+ Object value = event.getNewValue();
+ if (value instanceof Boolean)
+ eventValue = ((Boolean)value).booleanValue();
+
+ boolean activeValue = (textAttribute.getStyle() & styleAttribute) == styleAttribute;
+ if (activeValue != eventValue) {
+ Color foreground = textAttribute.getForeground();
+ Color background = textAttribute.getBackground();
+ int style = eventValue ? textAttribute.getStyle() | styleAttribute : textAttribute.getStyle() & ~styleAttribute;
+ textAttribute= new TextAttribute(foreground, background, style);
+ }
+ return textAttribute;
+ }
+
+ public boolean affectsTextPresentation(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ return property.startsWith(IPDEColorConstants.P_DEFAULT) ||
+ property.startsWith(IPDEColorConstants.P_PROC_INSTR) ||
+ property.startsWith(IPDEColorConstants.P_STRING) ||
+ property.startsWith(IPDEColorConstants.P_TAG) ||
+ property.startsWith(IPDEColorConstants.P_XML_COMMENT);
+ }
+
+ public boolean affectsColorPresentation(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ return property.equals(IPDEColorConstants.P_DEFAULT) ||
+ property.equals(IPDEColorConstants.P_PROC_INSTR) ||
+ property.equals(IPDEColorConstants.P_STRING) ||
+ property.equals(IPDEColorConstants.P_TAG) ||
+ property.equals(IPDEColorConstants.P_XML_COMMENT);
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLDoubleClickStrategy.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLDoubleClickStrategy.java
new file mode 100644
index 0000000..7a6d829
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLDoubleClickStrategy.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.text.*;
+
+public class XMLDoubleClickStrategy implements ITextDoubleClickStrategy {
+ protected ITextViewer fText;
+
+ public void doubleClicked(ITextViewer part) {
+ int pos = part.getSelectedRange().x;
+ if (pos > 0) {
+ fText = part;
+ selectWord(pos);
+ }
+ }
+
+ protected boolean selectWord(int caretPos) {
+
+ IDocument doc = fText.getDocument();
+ int startPos, endPos;
+
+ try {
+
+ int pos = caretPos;
+ char c;
+
+ while (pos >= 0) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c) && c != '.')
+ break;
+ --pos;
+ }
+
+ startPos = pos;
+
+ pos = caretPos;
+ int length = doc.getLength();
+
+ while (pos < length) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c) && c != '.')
+ break;
+ ++pos;
+ }
+
+ endPos = pos;
+ selectRange(startPos, endPos);
+ return true;
+
+ } catch (BadLocationException x) {
+ }
+
+ return false;
+ }
+
+ private void selectRange(int startPos, int stopPos) {
+ int offset = startPos+1;
+ int length = stopPos - offset;
+ fText.setSelectedRange(offset, length);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLSourcePage.java
new file mode 100644
index 0000000..bbbd3a1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLSourcePage.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.pde.internal.ui.editor.text.ColorManager;
+import org.eclipse.pde.internal.ui.editor.text.IColorManager;
+import org.eclipse.pde.internal.ui.editor.text.IPDEColorConstants;
+import org.eclipse.pde.internal.ui.editor.text.ReconcilingStrategy;
+import org.eclipse.pde.internal.ui.editor.text.XMLConfiguration;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.DefaultRangeIndicator;
+
+public abstract class XMLSourcePage extends PDESourcePage {
+
+ class XMLSourceViewerConfiguration extends XMLConfiguration {
+ private MonoReconciler fReconciler;
+
+ public XMLSourceViewerConfiguration(IColorManager colorManager) {
+ super(colorManager);
+ }
+
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ if (fReconciler == null) {
+ IBaseModel model = getInputContext().getModel();
+ if (model instanceof IReconcilingParticipant) {
+ ReconcilingStrategy strategy = new ReconcilingStrategy();
+ strategy.addParticipant((IReconcilingParticipant)model);
+ ISortableContentOutlinePage outline = getContentOutline();
+ if (outline instanceof IReconcilingParticipant)
+ strategy.addParticipant((IReconcilingParticipant)outline);
+ fReconciler = new MonoReconciler(strategy, false);
+ fReconciler.setDelay(500);
+ }
+ }
+ return fReconciler;
+ }
+ }
+
+ protected IColorManager fColorManager;
+
+ public XMLSourcePage(PDEFormEditor editor, String id, String title) {
+ super(editor, id, title);
+ fColorManager = ColorManager.getDefault();
+ setSourceViewerConfiguration(new XMLSourceViewerConfiguration(fColorManager));
+ setRangeIndicator(new DefaultRangeIndicator());
+ }
+
+ public void dispose() {
+ super.dispose();
+ fColorManager.dispose();
+ }
+
+ public boolean canLeaveThePage() {
+ boolean cleanModel = getInputContext().isModelCorrect();
+ if (!cleanModel) {
+ Display.getCurrent().beep();
+ String title = getEditor().getSite().getRegisteredName();
+ MessageDialog.openError(
+ PDEPlugin.getActiveWorkbenchShell(),
+ title,
+ PDEUIMessages.SourcePage_errorMessage);
+ }
+ return cleanModel;
+ }
+
+ protected boolean affectsTextPresentation(PropertyChangeEvent event){
+ String property = event.getProperty();
+ return property.startsWith(IPDEColorConstants.P_DEFAULT)
+ || property.startsWith(IPDEColorConstants.P_PROC_INSTR)
+ || property.startsWith(IPDEColorConstants.P_STRING)
+ || property.startsWith(IPDEColorConstants.P_TAG)
+ || property.startsWith(IPDEColorConstants.P_XML_COMMENT);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#handlePreferenceStoreChanged(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ XMLSourceViewerConfiguration sourceViewerConfiguration= (XMLSourceViewerConfiguration)getSourceViewerConfiguration();
+ if (affectsTextPresentation(event)) {
+ sourceViewerConfiguration.adaptToPreferenceChange(event);
+ setSourceViewerConfiguration(sourceViewerConfiguration);
+ }
+ super.handlePreferenceStoreChanged(event);
+ }
+
+ protected String[] collectContextMenuPreferencePages() {
+ String[] ids= super.collectContextMenuPreferencePages();
+ String[] more= new String[ids.length + 1];
+ more[0]= "org.eclipse.pde.ui.EditorPreferencePage"; //$NON-NLS-1$
+ System.arraycopy(ids, 0, more, 1, ids.length);
+ return more;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/DocumentReader.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/DocumentReader.java
new file mode 100644
index 0000000..122ce83
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/DocumentReader.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+
+
+/**
+ * A <code>Reader</code> that reads from an <code>IDocument</code>.
+ * The reader ensures that its content is the same as the document
+ * content when the stream was created.
+ * <p>
+ * Note that {@link #close()} must be called to release any acquired
+ * resources.
+ * </p>
+ *
+ * @since 3.1
+ */
+// copied from same class in org.eclipse.ui.editors.text - no changes
+class DocumentReader extends Reader {
+
+ /**
+ * Document based character sequence.
+ */
+ private static class DocumentCharSequence implements CharSequence {
+
+ /** Document */
+ private IDocument fDocument;
+
+ /**
+ * Initialize with the sequence of characters in the given
+ * document.
+ *
+ * @param document the document
+ */
+ public DocumentCharSequence(IDocument document) {
+ fDocument= document;
+ }
+
+ /*
+ * @see java.lang.CharSequence#length()
+ */
+ public int length() {
+ return fDocument.getLength();
+ }
+
+ /*
+ * @see java.lang.CharSequence#charAt(int)
+ */
+ public char charAt(int index) {
+ try {
+ return fDocument.getChar(index);
+ } catch (BadLocationException x) {
+ throw new IndexOutOfBoundsException(x.getLocalizedMessage());
+ }
+ }
+
+ /*
+ * @see java.lang.CharSequence#subSequence(int, int)
+ */
+ public CharSequence subSequence(int start, int end) {
+ try {
+ return fDocument.get(start, end - start);
+ } catch (BadLocationException x) {
+ throw new IndexOutOfBoundsException(x.getLocalizedMessage());
+ }
+ }
+ }
+
+ /**
+ * Internal document listener.
+ */
+ private class InternalDocumentListener implements IDocumentListener {
+
+ /*
+ * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ handleDocumentAboutToBeChanged();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ }
+ }
+
+ /** The character sequence. */
+ private volatile CharSequence fCharSequence;
+
+ /** Document length. */
+ private int fLength;
+
+ /** The current offset. */
+ private int fOffset= 0;
+
+ /** The document. */
+ private IDocument fDocument;
+
+ /** The document listener. */
+ private IDocumentListener fDocumentListener= new InternalDocumentListener();
+
+ /**
+ * Creates a new document input stream and initializes
+ * the stream to read from the given document.
+ *
+ * @param document the document
+ */
+ public DocumentReader(IDocument document) {
+ Assert.isNotNull(document);
+ fDocument= document;
+ fCharSequence= new DocumentCharSequence(fDocument);
+ fDocument.addDocumentListener(fDocumentListener);
+ fLength= fCharSequence.length();
+ }
+
+ /*
+ * @see java.io.InputStream#close()
+ */
+ public void close() throws IOException {
+ synchronized (this) {
+ fCharSequence= null;
+ }
+ releaseDocument();
+ }
+
+ /**
+ * Copies the document prior to modification and removes the document listener.
+ */
+ private void handleDocumentAboutToBeChanged() {
+ IDocument document= fDocument;
+ if (fCharSequence == null || document == null)
+ return;
+ String content= document.get();
+ synchronized (this) {
+ if (fCharSequence == null)
+ return;
+ fCharSequence= content;
+ }
+ releaseDocument();
+ }
+
+ /**
+ * Removes the document listener.
+ */
+ private synchronized void releaseDocument() {
+ if (fDocument != null)
+ fDocument.removeDocumentListener(fDocumentListener);
+ fDocument= null;
+ fDocumentListener= null;
+ }
+
+ /*
+ * @see java.io.Reader#read(char[], int, int)
+ * @since 3.1
+ */
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ int i= 0;
+ try {
+ for (; i < len && fOffset < fLength; i++)
+ cbuf[off + i]= fCharSequence.charAt(fOffset++);
+ if (i > 0)
+ return i;
+
+ return -1;
+ } catch (NullPointerException x) {
+ throw new IOException(TextEditorMessages.DocumentInputStream_error_streamClosed);
+ } catch (IndexOutOfBoundsException x) {
+ return i-1;
+ }
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/FileDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/FileDocumentProvider.java
new file mode 100644
index 0000000..003c28c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/FileDocumentProvider.java
@@ -0,0 +1,1182 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.filebuffers.manipulation.ContainerCreator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IResourceRuleFactory;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.StorageDocumentProvider;
+import org.eclipse.ui.internal.editors.text.NLSUtility;
+import org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
+import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
+
+
+/**
+ * Shared document provider specialized for file resources (<code>IFile</code>).
+ * <p>
+ * This class may be instantiated or be subclassed.</p>
+ */
+// copied from same class in org.eclipse.ui.editors.text
+// as part of the fix for 86467 - changes marked // AspectJ Change
+public class FileDocumentProvider extends StorageDocumentProvider {
+
+ /**
+ * Qualified name for the encoding key.
+ *
+ * @since 2.1
+ */
+ private static final QualifiedName ENCODING_KEY = new QualifiedName(EditorsUI.PLUGIN_ID, "encoding"); //$NON-NLS-1$
+ /**
+ * Constant denoting UTF-8 encoding.
+ * @since 3.0
+ */
+ private static final String CHARSET_UTF_8= "UTF-8"; //$NON-NLS-1$
+
+
+ /**
+ * The runnable context for that provider.
+ * @since 3.0
+ */
+ private WorkspaceOperationRunner fOperationRunner;
+ /**
+ * The scheduling rule factory.
+ * @since 3.0
+ */
+ private IResourceRuleFactory fResourceRuleFactory;
+
+ /**
+ * Runnable encapsulating an element state change. This runnable ensures
+ * that a element change failed message is sent out to the element state listeners
+ * in case an exception occurred.
+ *
+ * @since 2.0
+ */
+ protected class SafeChange implements Runnable {
+
+ /** The input that changes. */
+ private IFileEditorInput fInput;
+
+ /**
+ * Creates a new safe runnable for the given input.
+ *
+ * @param input the input
+ */
+ public SafeChange(IFileEditorInput input) {
+ fInput= input;
+ }
+
+ /**
+ * Execute the change.
+ * Subclass responsibility.
+ *
+ * @param input the input
+ * @throws Exception an exception in case of error
+ */
+ protected void execute(IFileEditorInput input) throws Exception {
+ }
+
+ /*
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+
+ if (getElementInfo(fInput) == null) {
+ fireElementStateChangeFailed(fInput);
+ return;
+ }
+
+ try {
+ execute(fInput);
+ } catch (Exception e) {
+ fireElementStateChangeFailed(fInput);
+ }
+ }
+ }
+
+
+ /**
+ * Synchronizes the document with external resource changes.
+ */
+ protected class FileSynchronizer implements IResourceChangeListener, IResourceDeltaVisitor {
+
+ /** The file editor input. */
+ protected IFileEditorInput fFileEditorInput;
+ /**
+ * A flag indicating whether this synchronizer is installed or not.
+ *
+ * @since 2.1
+ */
+ protected boolean fIsInstalled= false;
+
+ /**
+ * Creates a new file synchronizer. Is not yet installed on a resource.
+ *
+ * @param fileEditorInput the editor input to be synchronized
+ */
+ public FileSynchronizer(IFileEditorInput fileEditorInput) {
+ fFileEditorInput= fileEditorInput;
+ }
+
+ /**
+ * Creates a new file synchronizer which is not yet installed on a resource.
+ *
+ * @param fileEditorInput the editor input to be synchronized
+ * @deprecated use <code>FileSynchronizer(IFileEditorInput)</code>
+ */
+ public FileSynchronizer(FileEditorInput fileEditorInput) {
+ fFileEditorInput= fileEditorInput;
+ }
+
+ /**
+ * Returns the file wrapped by the file editor input.
+ *
+ * @return the file wrapped by the editor input associated with that synchronizer
+ */
+ protected IFile getFile() {
+ return fFileEditorInput.getFile();
+ }
+
+ /**
+ * Installs the synchronizer on the input's file.
+ */
+ public void install() {
+ getFile().getWorkspace().addResourceChangeListener(this);
+ fIsInstalled= true;
+ }
+
+ /**
+ * Uninstalls the synchronizer from the input's file.
+ */
+ public void uninstall() {
+ getFile().getWorkspace().removeResourceChangeListener(this);
+ fIsInstalled= false;
+ }
+
+ /*
+ * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
+ */
+ public void resourceChanged(IResourceChangeEvent e) {
+ IResourceDelta delta= e.getDelta();
+ try {
+ if (delta != null && fIsInstalled)
+ delta.accept(this);
+ } catch (CoreException x) {
+ handleCoreException(x, "FileDocumentProvider.resourceChanged"); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * @see IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+ */
+ public boolean visit(IResourceDelta delta) throws CoreException {
+ if (delta == null)
+ return false;
+
+ delta= delta.findMember(getFile().getFullPath());
+
+ if (delta == null)
+ return false;
+
+ Runnable runnable= null;
+
+ switch (delta.getKind()) {
+ case IResourceDelta.CHANGED:
+ FileInfo info= (FileInfo) getElementInfo(fFileEditorInput);
+ if (info == null || info.fCanBeSaved)
+ break;
+
+ boolean isSynchronized= computeModificationStamp(getFile()) == info.fModificationStamp;
+ if ((IResourceDelta.ENCODING & delta.getFlags()) != 0 && isSynchronized) {
+ runnable= new SafeChange(fFileEditorInput) {
+ protected void execute(IFileEditorInput input) throws Exception {
+ handleElementContentChanged(input);
+ }
+ };
+ }
+ // AspectJ Change
+ if ((IResourceDelta.CONTENT & delta.getFlags()) != 0 && !isSynchronized) {
+ runnable= new SafeChange(fFileEditorInput) {
+ protected void execute(IFileEditorInput input) throws Exception {
+ handleElementContentChanged(input);
+ }
+ };
+ }
+ break;
+
+ case IResourceDelta.REMOVED:
+ if ((IResourceDelta.MOVED_TO & delta.getFlags()) != 0) {
+ final IPath path= delta.getMovedToPath();
+ runnable= new SafeChange(fFileEditorInput) {
+ protected void execute(IFileEditorInput input) throws Exception {
+ handleElementMoved(input, path);
+ }
+ };
+ } else {
+ info= (FileInfo) getElementInfo(fFileEditorInput);
+ if (info != null && !info.fCanBeSaved) {
+ runnable= new SafeChange(fFileEditorInput) {
+ protected void execute(IFileEditorInput input) throws Exception {
+ handleElementDeleted(input);
+ }
+ };
+ }
+ }
+ break;
+ }
+
+ if (runnable != null)
+ update(runnable);
+
+ return false;
+ }
+
+ /**
+ * Posts the update code "behind" the running operation.
+ *
+ * @param runnable the update code
+ */
+ protected void update(Runnable runnable) {
+
+ if (runnable instanceof SafeChange)
+ fireElementStateChanging(fFileEditorInput);
+
+ IWorkbench workbench= PlatformUI.getWorkbench();
+ IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
+ if (windows != null && windows.length > 0) {
+ Display display= windows[0].getShell().getDisplay();
+ display.asyncExec(runnable);
+ } else {
+ runnable.run();
+ }
+ }
+ }
+
+
+
+ /**
+ * Bundle of all required information to allow files as underlying document resources.
+ */
+ protected class FileInfo extends StorageInfo {
+
+ /** The file synchronizer. */
+ public FileSynchronizer fFileSynchronizer;
+ /** The time stamp at which this provider changed the file. */
+ public long fModificationStamp= IResource.NULL_STAMP;
+ /**
+ * Tells whether the file on disk has a BOM.
+ */
+ private boolean fHasBOM;
+
+ /**
+ * Creates and returns a new file info.
+ *
+ * @param document the document
+ * @param model the annotation model
+ * @param fileSynchronizer the file synchronizer
+ */
+ public FileInfo(IDocument document, IAnnotationModel model, FileSynchronizer fileSynchronizer) {
+ super(document, model);
+ fFileSynchronizer= fileSynchronizer;
+ }
+ }
+
+
+ /**
+ * Creates and returns a new document provider.
+ */
+ public FileDocumentProvider() {
+ super();
+ fResourceRuleFactory= ResourcesPlugin.getWorkspace().getRuleFactory();
+ }
+
+ /**
+ * Overrides <code>StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput)</code>.
+ *
+ * @see StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput)
+ * @deprecated use file encoding based version
+ * @since 2.0
+ */
+ protected boolean setDocumentContent(IDocument document, IEditorInput editorInput) throws CoreException {
+ if (editorInput instanceof IFileEditorInput) {
+ IFile file= ((IFileEditorInput) editorInput).getFile();
+ InputStream stream= file.getContents(false);
+ try {
+ setDocumentContent(document, stream);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException x) {
+ }
+ }
+ return true;
+ }
+ return super.setDocumentContent(document, editorInput);
+ }
+
+ /*
+ * @see StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput, String)
+ * @since 2.0
+ */
+ protected boolean setDocumentContent(IDocument document, IEditorInput editorInput, String encoding) throws CoreException {
+ if (editorInput instanceof IFileEditorInput) {
+ IFile file= ((IFileEditorInput) editorInput).getFile();
+ // AspectJ Change - stop errors in the log when a new project is created
+ if(file.exists()) {
+ InputStream contentStream= file.getContents(false);
+ try {
+
+ FileInfo info= (FileInfo)getElementInfo(editorInput);
+
+ /*
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ */
+ if (info != null && info.fHasBOM && CHARSET_UTF_8.equals(encoding)) {
+ int n= 0;
+ do {
+ int bytes= contentStream.read(new byte[IContentDescription.BOM_UTF_8.length]);
+ if (bytes == -1)
+ throw new IOException();
+ n += bytes;
+ } while (n < IContentDescription.BOM_UTF_8.length);
+ }
+
+ setDocumentContent(document, contentStream, encoding);
+
+ } catch (IOException ex) {
+ String message= (ex.getMessage() != null ? ex.getMessage() : ""); //$NON-NLS-1$
+ IStatus s= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, message, ex);
+ throw new CoreException(s);
+ } finally {
+ try {
+ contentStream.close();
+ } catch (IOException e1) {
+ }
+ }
+ }
+ return true;
+ }
+ return super.setDocumentContent(document, editorInput, encoding);
+ }
+
+ /*
+ * @see AbstractDocumentProvider#createAnnotationModel(Object)
+ */
+ protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ return new ResourceMarkerAnnotationModel(input.getFile());
+ }
+
+ return super.createAnnotationModel(element);
+ }
+
+ /**
+ * Checks whether the given resource has been changed on the
+ * local file system by comparing the actual time stamp with the
+ * cached one. If the resource has been changed, a <code>CoreException</code>
+ * is thrown.
+ *
+ * @param cachedModificationStamp the cached modification stamp
+ * @param resource the resource to check
+ * @throws org.eclipse.core.runtime.CoreException if resource has been changed on the file system
+ */
+ protected void checkSynchronizationState(long cachedModificationStamp, IResource resource) throws CoreException {
+ if (cachedModificationStamp != computeModificationStamp(resource)) {
+ Status status= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IResourceStatus.OUT_OF_SYNC_LOCAL, TextEditorMessages.FileDocumentProvider_error_out_of_sync, null);
+ throw new CoreException(status);
+ }
+ }
+
+ /**
+ * Computes the initial modification stamp for the given resource.
+ *
+ * @param resource the resource
+ * @return the modification stamp
+ */
+ protected long computeModificationStamp(IResource resource) {
+ long modificationStamp= resource.getModificationStamp();
+
+ IPath path= resource.getLocation();
+ if (path == null)
+ return modificationStamp;
+
+ modificationStamp= path.toFile().lastModified();
+ return modificationStamp;
+ }
+
+ /*
+ * @see IDocumentProvider#getModificationStamp(Object)
+ */
+ public long getModificationStamp(Object element) {
+
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ return computeModificationStamp(input.getFile());
+ }
+
+ return super.getModificationStamp(element);
+ }
+
+ /*
+ * @see IDocumentProvider#getSynchronizationStamp(Object)
+ */
+ public long getSynchronizationStamp(Object element) {
+
+ if (element instanceof IFileEditorInput) {
+ FileInfo info= (FileInfo) getElementInfo(element);
+ if (info != null)
+ return info.fModificationStamp;
+ }
+
+ return super.getSynchronizationStamp(element);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSynchronize(java.lang.Object)
+ * @since 3.0
+ */
+ protected void doSynchronize(Object element, IProgressMonitor monitor) throws CoreException {
+ if (element instanceof IFileEditorInput) {
+
+ IFileEditorInput input= (IFileEditorInput) element;
+
+ FileInfo info= (FileInfo) getElementInfo(element);
+ if (info != null) {
+
+ if (info.fFileSynchronizer != null) {
+ info.fFileSynchronizer.uninstall();
+ refreshFile(input.getFile(), monitor);
+ info.fFileSynchronizer.install();
+ } else {
+ refreshFile(input.getFile(), monitor);
+ }
+
+ handleElementContentChanged((IFileEditorInput) element);
+ }
+ return;
+
+ }
+ super.doSynchronize(element, monitor);
+ }
+
+ /*
+ * @see IDocumentProvider#isDeleted(Object)
+ */
+ public boolean isDeleted(Object element) {
+
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+
+ IPath path= input.getFile().getLocation();
+ if (path == null)
+ return true;
+
+ return !path.toFile().exists();
+ }
+
+ return super.isDeleted(element);
+ }
+
+ /*
+ * @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument, boolean)
+ */
+ protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
+ if (element instanceof IFileEditorInput) {
+
+ IFileEditorInput input= (IFileEditorInput) element;
+ String encoding= null;
+ try {
+ FileInfo info= (FileInfo) getElementInfo(element);
+ IFile file= input.getFile();
+ encoding= getCharsetForNewFile(file, document, info);
+
+ byte[] bytes= document.get().getBytes(encoding);
+
+ /*
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ */
+ if (info != null && info.fHasBOM && CHARSET_UTF_8.equals(encoding)) {
+ int bomLength= IContentDescription.BOM_UTF_8.length;
+ byte[] bytesWithBOM= new byte[bytes.length + bomLength];
+ System.arraycopy(IContentDescription.BOM_UTF_8, 0, bytesWithBOM, 0, bomLength);
+ System.arraycopy(bytes, 0, bytesWithBOM, bomLength, bytes.length);
+ bytes= bytesWithBOM;
+ }
+
+ InputStream stream= new ByteArrayInputStream(bytes);
+
+ if (file.exists()) {
+
+ if (info != null && !overwrite)
+ checkSynchronizationState(info.fModificationStamp, file);
+
+ // inform about the upcoming content change
+ fireElementStateChanging(element);
+ try {
+ file.setContents(stream, overwrite, true, monitor);
+ } catch (CoreException x) {
+ // inform about failure
+ fireElementStateChangeFailed(element);
+ throw x;
+ } catch (RuntimeException x) {
+ // inform about failure
+ fireElementStateChangeFailed(element);
+ throw x;
+ }
+
+ // If here, the editor state will be flipped to "not dirty".
+ // Thus, the state changing flag will be reset.
+
+ if (info != null) {
+
+ ResourceMarkerAnnotationModel model= (ResourceMarkerAnnotationModel) info.fModel;
+ model.updateMarkers(info.fDocument);
+
+ info.fModificationStamp= computeModificationStamp(file);
+ }
+
+ } else {
+ try {
+ monitor.beginTask(TextEditorMessages.FileDocumentProvider_task_saving, 2000);
+ ContainerCreator creator = new ContainerCreator(file.getWorkspace(), file.getParent().getFullPath());
+ creator.createContainer(new SubProgressMonitor(monitor, 1000));
+ file.create(stream, false, new SubProgressMonitor(monitor, 1000));
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ } catch (UnsupportedEncodingException x) {
+ String message= NLSUtility.format(TextEditorMessages.Editor_error_unsupported_encoding_message_arg, encoding);
+ IStatus s= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, message, x);
+ throw new CoreException(s);
+ }
+
+ } else {
+ super.doSaveDocument(monitor, element, document, overwrite);
+ }
+ }
+
+ /*
+ * @since 3.0
+ */
+ private String getCharsetForNewFile(IFile targetFile, IDocument document, FileInfo info) {
+ // User-defined encoding has first priority
+ String encoding;
+ try {
+ encoding= targetFile.getCharset(false);
+ } catch (CoreException ex) {
+ encoding= null;
+ }
+ if (encoding != null)
+ return encoding;
+
+ // Probe content
+ Reader reader= new DocumentReader(document);
+ try {
+ QualifiedName[] options= new QualifiedName[] { IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK };
+ IContentDescription description= Platform.getContentTypeManager().getDescriptionFor(reader, targetFile.getName(), options);
+ if (description != null) {
+ encoding= description.getCharset();
+ if (encoding != null)
+ return encoding;
+ }
+ } catch (IOException ex) {
+ // continue with next strategy
+ } finally {
+ try {
+ if (reader != null)
+ reader.close();
+ } catch (IOException x) {
+ }
+ }
+
+ // Use file's encoding if the file has a BOM
+ if (info != null && info.fHasBOM)
+ return info.fEncoding;
+
+ // Use parent chain
+ try {
+ return targetFile.getParent().getDefaultCharset();
+ } catch (CoreException ex) {
+ // Use global default
+ return ResourcesPlugin.getEncoding();
+ }
+ }
+
+ /*
+ * @see AbstractDocumentProvider#createElementInfo(Object)
+ */
+ protected ElementInfo createElementInfo(Object element) throws CoreException {
+ if (element instanceof IFileEditorInput) {
+
+ IFileEditorInput input= (IFileEditorInput) element;
+
+ try {
+ refreshFile(input.getFile());
+ } catch (CoreException x) {
+ handleCoreException(x, TextEditorMessages.FileDocumentProvider_createElementInfo);
+ }
+
+ IDocument d= null;
+ IStatus s= null;
+
+ try {
+ d= createDocument(element);
+ } catch (CoreException x) {
+ handleCoreException(x, TextEditorMessages.FileDocumentProvider_createElementInfo);
+ s= x.getStatus();
+ d= createEmptyDocument();
+ }
+
+ // Set the initial line delimiter
+ if (d instanceof IDocumentExtension4) {
+ String initalLineDelimiter= getLineDelimiterPreference(input.getFile());
+ if (initalLineDelimiter != null)
+ ((IDocumentExtension4)d).setInitialLineDelimiter(initalLineDelimiter);
+ }
+
+ IAnnotationModel m= createAnnotationModel(element);
+ FileSynchronizer f= new FileSynchronizer(input);
+ f.install();
+
+ FileInfo info= new FileInfo(d, m, f);
+ info.fModificationStamp= computeModificationStamp(input.getFile());
+ info.fStatus= s;
+ cacheEncodingState(element);
+
+ return info;
+ }
+
+ return super.createElementInfo(element);
+ }
+
+ /**
+ * Returns the default line delimiter preference for the given file.
+ *
+ * @param file the file
+ * @return the default line delimiter
+ * @since 3.1
+ */
+ private String getLineDelimiterPreference(IFile file) {
+ IScopeContext[] scopeContext;
+ if (file != null && file.getProject() != null) {
+ // project preference
+ scopeContext= new IScopeContext[] { new ProjectScope(file.getProject()) };
+ String lineDelimiter= Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+ if (lineDelimiter != null)
+ return lineDelimiter;
+ }
+ // workspace preference
+ scopeContext= new IScopeContext[] { new InstanceScope() };
+ return Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+ }
+
+ /*
+ * @see AbstractDocumentProvider#disposeElementInfo(Object, ElementInfo)
+ */
+ protected void disposeElementInfo(Object element, ElementInfo info) {
+ if (info instanceof FileInfo) {
+ FileInfo fileInfo= (FileInfo) info;
+ if (fileInfo.fFileSynchronizer != null)
+ fileInfo.fFileSynchronizer.uninstall();
+ }
+
+ super.disposeElementInfo(element, info);
+ }
+
+ /**
+ * Updates the element info to a change of the file content and sends out
+ * appropriate notifications.
+ *
+ * @param fileEditorInput the input of an text editor
+ */
+ protected void handleElementContentChanged(IFileEditorInput fileEditorInput) {
+ FileInfo info= (FileInfo) getElementInfo(fileEditorInput);
+ if (info == null)
+ return;
+
+ IDocument document= createEmptyDocument();
+ IStatus status= null;
+
+ try {
+
+ try {
+ refreshFile(fileEditorInput.getFile());
+ } catch (CoreException x) {
+ handleCoreException(x, "FileDocumentProvider.handleElementContentChanged"); //$NON-NLS-1$
+ }
+
+ cacheEncodingState(fileEditorInput);
+ setDocumentContent(document, fileEditorInput, info.fEncoding);
+
+ } catch (CoreException x) {
+ status= x.getStatus();
+ }
+
+ String newContent= document.get();
+
+ if ( !newContent.equals(info.fDocument.get())) {
+
+ // set the new content and fire content related events
+ fireElementContentAboutToBeReplaced(fileEditorInput);
+
+ removeUnchangedElementListeners(fileEditorInput, info);
+
+ info.fDocument.removeDocumentListener(info);
+ info.fDocument.set(newContent);
+ info.fCanBeSaved= false;
+ info.fModificationStamp= computeModificationStamp(fileEditorInput.getFile());
+ info.fStatus= status;
+
+ addUnchangedElementListeners(fileEditorInput, info);
+
+ fireElementContentReplaced(fileEditorInput);
+
+ } else {
+
+ removeUnchangedElementListeners(fileEditorInput, info);
+
+ // fires only the dirty state related event
+ info.fCanBeSaved= false;
+ info.fModificationStamp= computeModificationStamp(fileEditorInput.getFile());
+ info.fStatus= status;
+
+ addUnchangedElementListeners(fileEditorInput, info);
+
+ fireElementDirtyStateChanged(fileEditorInput, false);
+ }
+ }
+
+ /**
+ * Sends out the notification that the file serving as document input has been moved.
+ *
+ * @param fileEditorInput the input of an text editor
+ * @param path the path of the new location of the file
+ */
+ protected void handleElementMoved(IFileEditorInput fileEditorInput, IPath path) {
+ IWorkspace workspace= ResourcesPlugin.getWorkspace();
+ IFile newFile= workspace.getRoot().getFile(path);
+ fireElementMoved(fileEditorInput, newFile == null ? null : new FileEditorInput(newFile));
+ }
+
+ /**
+ * Sends out the notification that the file serving as document input has been deleted.
+ *
+ * @param fileEditorInput the input of an text editor
+ */
+ protected void handleElementDeleted(IFileEditorInput fileEditorInput) {
+ fireElementDeleted(fileEditorInput);
+ }
+
+ /*
+ * @see AbstractDocumentProvider#getElementInfo(Object)
+ * It's only here to circumvent visibility issues with certain compilers.
+ */
+ protected ElementInfo getElementInfo(Object element) {
+ return super.getElementInfo(element);
+ }
+
+ /*
+ * @see AbstractDocumentProvider#doValidateState(Object, Object)
+ * @since 2.0
+ */
+ protected void doValidateState(Object element, Object computationContext) throws CoreException {
+
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ FileInfo info= (FileInfo) getElementInfo(input);
+ if (info != null) {
+ IFile file= input.getFile();
+ if (file.isReadOnly()) { // do not use cached state here
+ IWorkspace workspace= file.getWorkspace();
+ workspace.validateEdit(new IFile[] { file }, computationContext);
+ }
+ }
+ }
+
+ super.doValidateState(element, computationContext);
+ }
+
+ /*
+ * @see IDocumentProviderExtension#isModifiable(Object)
+ * @since 2.0
+ */
+ public boolean isModifiable(Object element) {
+ if (!isStateValidated(element)) {
+ if (element instanceof IFileEditorInput)
+ return true;
+ }
+ return super.isModifiable(element);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doResetDocument(java.lang.Object, org.eclipse.core.runtime.IProgressMonitor)
+ * @since 3.0
+ */
+ protected void doResetDocument(Object element, IProgressMonitor monitor) throws CoreException {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ try {
+ refreshFile(input.getFile(), monitor);
+ cacheEncodingState(element);
+ } catch (CoreException x) {
+ handleCoreException(x,TextEditorMessages.FileDocumentProvider_resetDocument);
+ }
+ }
+
+ super.doResetDocument(element, monitor);
+
+ IAnnotationModel model= getAnnotationModel(element);
+ if (model instanceof AbstractMarkerAnnotationModel) {
+ AbstractMarkerAnnotationModel markerModel= (AbstractMarkerAnnotationModel) model;
+ markerModel.resetMarkers();
+ }
+ }
+
+ /**
+ * Refreshes the given file resource.
+ *
+ * @param file
+ * @throws CoreException if the refresh fails
+ * @since 2.1
+ */
+ protected void refreshFile(IFile file) throws CoreException {
+ refreshFile(file, getProgressMonitor());
+ }
+
+ /**
+ * Refreshes the given file resource.
+ *
+ * @param file the file to be refreshed
+ * @param monitor the progress monitor
+ * @throws org.eclipse.core.runtime.CoreException if the refresh fails
+ * @since 3.0
+ */
+ protected void refreshFile(IFile file, IProgressMonitor monitor) throws CoreException {
+ try {
+ file.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+ } catch (OperationCanceledException x) {
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IDocumentProviderExtension3#isSynchronized(java.lang.Object)
+ * @since 3.0
+ */
+ public boolean isSynchronized(Object element) {
+ if (element instanceof IFileEditorInput) {
+ if (getElementInfo(element) != null) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ IResource resource= input.getFile();
+ return resource.isSynchronized(IResource.DEPTH_ZERO);
+ }
+ return false;
+ }
+ return super.isSynchronized(element);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IDocumentProviderExtension4#getContentType(java.lang.Object)
+ * @since 3.1
+ */
+ public IContentType getContentType(Object element) throws CoreException {
+ IContentType contentType= null;
+ if (!canSaveDocument(element) && element instanceof IFileEditorInput)
+ contentType= getContentType((IFileEditorInput) element);
+
+ if (contentType == null)
+ contentType= super.getContentType(element);
+
+ if (contentType == null && element instanceof IFileEditorInput)
+ contentType= getContentType((IFileEditorInput) element);
+
+ return contentType;
+ }
+
+ /**
+ * Returns the content type of for the given file editor input or
+ * <code>null</code> if none could be determined.
+ *
+ * @param input the element
+ * @return the content type or <code>null</code>
+ * @throws CoreException if reading or accessing the underlying store
+ * fails
+ * @since 3.1
+ */
+ private IContentType getContentType(IFileEditorInput input) throws CoreException {
+ IContentDescription desc= input.getFile().getContentDescription();
+ if (desc != null)
+ return desc.getContentType();
+ return null;
+ }
+
+ // --------------- Encoding support ---------------
+
+ /**
+ * Returns the persisted encoding for the given element.
+ *
+ * @param element the element for which to get the persisted encoding
+ * @return the persisted encoding
+ * @since 2.1
+ */
+ protected String getPersistedEncoding(Object element) {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput editorInput= (IFileEditorInput)element;
+ IFile file= editorInput.getFile();
+ // AspectJ Change - check file exists
+ if (file != null && file.exists()) {
+ String encoding= null;
+ try {
+ encoding= file.getPersistentProperty(ENCODING_KEY);
+ } catch (CoreException x) {
+ // we ignore exceptions here because we support the ENCODING_KEY property only for compatibility reasons
+ }
+ if (encoding != null) {
+ // if we found an old encoding property, we try to migrate it to the new core.resources encoding support
+ try {
+ file.setCharset(encoding, getProgressMonitor());
+ // if successful delete old property
+ file.setPersistentProperty(ENCODING_KEY, null);
+ } catch (CoreException ex) {
+ handleCoreException(ex, TextEditorMessages.FileDocumentProvider_getPersistedEncoding);
+ }
+ } else {
+ try {
+ encoding= file.getCharset();
+ } catch (CoreException e) {
+ encoding= null;
+ }
+ }
+ return encoding;
+ }
+ }
+ return super.getPersistedEncoding(element);
+ }
+
+ /**
+ * Persists the given encoding for the given element.
+ *
+ * @param element the element for which to store the persisted encoding
+ * @param encoding the encoding
+ * @throws org.eclipse.core.runtime.CoreException if persisting the encoding fails
+ * @since 2.1
+ */
+ protected void persistEncoding(Object element, String encoding) throws CoreException {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput editorInput= (IFileEditorInput)element;
+ IFile file= editorInput.getFile();
+ if (file != null) {
+ file.setCharset(encoding, getProgressMonitor());
+ StorageInfo info= (StorageInfo)getElementInfo(element);
+ if (info != null) {
+ if (encoding == null)
+ info.fEncoding= file.getCharset();
+ if (info instanceof FileInfo)
+ ((FileInfo)info).fHasBOM= hasBOM(element);
+ }
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getOperationRunner(org.eclipse.core.runtime.IProgressMonitor)
+ * @since 3.0
+ */
+ protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
+ if (fOperationRunner == null)
+ fOperationRunner = new WorkspaceOperationRunner();
+ fOperationRunner.setProgressMonitor(monitor);
+ return fOperationRunner;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getResetRule(java.lang.Object)
+ * @since 3.0
+ */
+ protected ISchedulingRule getResetRule(Object element) {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ return fResourceRuleFactory.modifyRule(input.getFile());
+ }
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getSaveRule(java.lang.Object)
+ * @since 3.0
+ */
+ protected ISchedulingRule getSaveRule(Object element) {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ return computeSchedulingRule(input.getFile());
+ }
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getSynchronizeRule(java.lang.Object)
+ * @since 3.0
+ */
+ protected ISchedulingRule getSynchronizeRule(Object element) {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ return fResourceRuleFactory.refreshRule(input.getFile());
+ }
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getValidateStateRule(java.lang.Object)
+ * @since 3.0
+ */
+ protected ISchedulingRule getValidateStateRule(Object element) {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput input= (IFileEditorInput) element;
+ return fResourceRuleFactory.validateEditRule(new IResource[] { input.getFile() });
+ }
+ return null;
+ }
+
+ /**
+ * Returns whether the underlying file has a BOM.
+ *
+ * @param element the element, or <code>null</code>
+ * @return <code>true</code> if the underlying file has BOM
+ */
+ private boolean hasBOM(Object element) {
+ if (element instanceof IFileEditorInput) {
+ IFile file= ((IFileEditorInput)element).getFile();
+ if (file != null) {
+ try {
+ IContentDescription description= file.getContentDescription();
+ return description != null && description.getProperty(IContentDescription.BYTE_ORDER_MARK) != null;
+ } catch (CoreException ex) {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Reads the file's UTF-8 BOM if any and stores it.
+ * <p>
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ * </p>
+ * @param file the file
+ * @param encoding the encoding
+ * @param element the element, or <code>null</code>
+ * @throws org.eclipse.core.runtime.CoreException if reading the BOM fails
+ * @since 3.0
+ * @deprecated as of 3.0 this method is no longer in use and does nothing
+ */
+ protected void readUTF8BOM(IFile file, String encoding, Object element) throws CoreException {
+ }
+
+ /**
+ * Internally caches the file's encoding data.
+ *
+ * @param element the element, or <code>null</code>
+ * @throws CoreException if the encoding cannot be retrieved
+ * @since 3.1
+ */
+ protected void cacheEncodingState(Object element) throws CoreException {
+ if (element instanceof IFileEditorInput) {
+ IFileEditorInput editorInput= (IFileEditorInput)element;
+ IFile file= editorInput.getFile();
+ if (file != null) {
+ ElementInfo info= getElementInfo(element);
+ if (info instanceof StorageInfo)
+ ((StorageInfo)info).fEncoding= getPersistedEncoding(element);
+
+ if (info instanceof FileInfo)
+ ((FileInfo)info).fHasBOM= hasBOM(element);
+ }
+ }
+ }
+
+ /**
+ * Computes the scheduling rule needed to create or modify a resource. If
+ * the resource exists, its modify rule is returned. If it does not, the
+ * resource hierarchy is iterated towards the workspace root to find the
+ * first parent of <code>toCreateOrModify</code> that exists. Then the
+ * 'create' rule for the last non-existing resource is returned.
+ *
+ * @param toCreateOrModify the resource to create or modify
+ * @return the minimal scheduling rule needed to modify or create a resource
+ */
+ private ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) {
+ if (toCreateOrModify.exists())
+ return fResourceRuleFactory.modifyRule(toCreateOrModify);
+
+ IResource parent= toCreateOrModify;
+ do {
+ /*
+ * XXX This is a workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=67601
+ * IResourceRuleFactory.createRule should iterate the hierarchy itself.
+ */
+ toCreateOrModify= parent;
+ parent= toCreateOrModify.getParent();
+ } while (parent != null && !parent.exists());
+
+ return fResourceRuleFactory.createRule(toCreateOrModify);
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/IInputContextListener.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/IInputContextListener.java
new file mode 100755
index 0000000..7e584aa
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/IInputContextListener.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import org.eclipse.core.resources.IFile;
+
+public interface IInputContextListener {
+/**
+ * Informs the listener that a new context has been added.
+ * This should result in a new source tab.
+ * @param context
+ */
+ void contextAdded(InputContext context);
+/**
+ * Informs the listener that the context has been removed.
+ * This should result in removing the source tab.
+ * @param context
+ */
+ void contextRemoved(InputContext context);
+/**
+ * Informs the listener that a monitored file has
+ * been added.
+ * @param monitoredFile the file we were monitoring
+ */
+ void monitoredFileAdded(IFile monitoredFile);
+/**
+ * Informs the listener that a monitored file has
+ * been removed.
+ * @param monitoredFile
+ * @return <code>true</code> if it is OK to remove
+ * the associated context, <code>false</code> otherwise.
+ */
+ boolean monitoredFileRemoved(IFile monitoredFile);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContext.java
new file mode 100755
index 0000000..4c1e042
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContext.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+import java.util.ArrayList;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.StorageDocumentProvider;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileDocumentProvider;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileEditorInput;
+import org.eclipse.core.filebuffers.*;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IEditable;
+import org.eclipse.pde.core.IModelChangeProvider;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.IModelChangedListener;
+import org.eclipse.pde.internal.core.text.IEditingModel;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MoveSourceEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.editors.text.*;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.IElementStateListener;
+/**
+ * This class maintains objects associated with a single editor input.
+ */
+/*
+ * Changes marked // AspectJ change
+ */
+public abstract class InputContext {
+
+ private PDEFormEditor fEditor;
+ private IEditorInput fEditorInput;
+ private IBaseModel fModel;
+ private IModelChangedListener fModelListener;
+ private IDocumentProvider fDocumentProvider;
+ private IElementStateListener fElementListener;
+ protected ArrayList fEditOperations = new ArrayList();
+
+ private boolean fValidated;
+ private boolean fPrimary;
+ private boolean fIsSourceMode;
+ private boolean fMustSynchronize;
+
+ class ElementListener implements IElementStateListener {
+ public void elementContentAboutToBeReplaced(Object element) {
+ }
+ public void elementContentReplaced(Object element) {
+ doRevert();
+ }
+ public void elementDeleted(Object element) {
+ dispose();
+ }
+ public void elementDirtyStateChanged(Object element, boolean isDirty) {
+ fMustSynchronize=true;
+ }
+ public void elementMoved(Object originalElement, Object movedElement) {
+ dispose();
+ fEditor.close(true);
+ }
+ }
+ public InputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+ this.fEditor = editor;
+ this.fEditorInput = input;
+ setPrimary(primary);
+ }
+ public abstract String getId();
+
+ public IEditorInput getInput() {
+ return fEditorInput;
+ }
+ public PDEFormEditor getEditor() {
+ return fEditor;
+ }
+ public IBaseModel getModel() {
+ return fModel;
+ }
+ public IDocumentProvider getDocumentProvider() {
+ return fDocumentProvider;
+ }
+ private IDocumentProvider createDocumentProvider(IEditorInput input) {
+ if (input instanceof IFileEditorInput) {
+ return createFileDocumentProvider();
+ } else if (input instanceof SystemFileEditorInput) {
+ return new SystemFileDocumentProvider(createDocumentPartitioner(), getDefaultCharset());
+ } else if (input instanceof IStorageEditorInput) {
+ return new StorageDocumentProvider(createDocumentPartitioner(), getDefaultCharset());
+ }
+ return null;
+ }
+
+ private IDocumentProvider createFileDocumentProvider() {
+ // AspectJ change begin
+ // use our own document provider
+ return new FileDocumentProvider() {
+ public IDocument createDocument(Object element) throws CoreException {
+ IDocument document = super.createDocument(element);
+ if (document != null) {
+ IDocumentPartitioner partitioner = createDocumentPartitioner();
+ if (partitioner != null) {
+ partitioner.connect(document);
+ document.setDocumentPartitioner(partitioner);
+ }
+ }
+ return document;
+ }
+ };
+// return new ForwardingDocumentProvider(getPartitionName(),
+// getDocumentSetupParticipant(), new TextFileDocumentProvider());
+ // AspectJ change end
+ }
+
+ protected IDocumentSetupParticipant getDocumentSetupParticipant() {
+ return new IDocumentSetupParticipant() {
+ public void setup(IDocument document) {
+ }
+ };
+ }
+
+ protected abstract String getPartitionName();
+
+ protected IDocumentPartitioner createDocumentPartitioner() {
+ return null;
+ }
+
+ protected abstract String getDefaultCharset();
+
+ protected abstract IBaseModel createModel(IEditorInput input) throws CoreException;
+
+ protected void create() {
+ fDocumentProvider = createDocumentProvider(fEditorInput);
+ if (fDocumentProvider == null)
+ return;
+ try {
+ fDocumentProvider.connect(fEditorInput);
+ fModel = createModel(fEditorInput);
+ if (fModel instanceof IModelChangeProvider) {
+ fModelListener = new IModelChangedListener() {
+ public void modelChanged(IModelChangedEvent e) {
+ if (e.getChangeType() != IModelChangedEvent.WORLD_CHANGED) {
+ if (!fEditor.getLastDirtyState())
+ fEditor.fireSaveNeeded(fEditorInput, true);
+ if (!fIsSourceMode) {
+ IModelChangeProvider provider = e.getChangeProvider();
+ if (provider instanceof IEditingModel) {
+ // this is to guard against false notifications
+ // when a revert operation is performed, focus is taken away from a FormEntry
+ // and a text edit operation is falsely requested
+ if (((IEditingModel)provider).isDirty())
+ addTextEditOperation(fEditOperations, e);
+ }
+ }
+ }
+ }
+ };
+ ((IModelChangeProvider) fModel).addModelChangedListener(fModelListener);
+ }
+
+ IAnnotationModel amodel = fDocumentProvider
+ .getAnnotationModel(fEditorInput);
+ if (amodel != null)
+ amodel.connect(fDocumentProvider.getDocument(fEditorInput));
+ fElementListener = new ElementListener();
+ fDocumentProvider.addElementStateListener(fElementListener);
+ } catch (CoreException e) {
+ PDEPlugin.logException(e);
+ }
+
+ }
+
+ public synchronized boolean validateEdit() {
+ if (!fValidated) {
+ if (fEditorInput instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput) fEditorInput).getFile();
+ if (file.isReadOnly()) {
+ Shell shell = fEditor.getEditorSite().getShell();
+ IStatus validateStatus = PDEPlugin.getWorkspace().validateEdit(
+ new IFile[]{file}, shell);
+ fValidated=true; // to prevent loops
+ if (validateStatus.getSeverity() != IStatus.OK)
+ ErrorDialog.openError(shell, fEditor.getTitle(), null,
+ validateStatus);
+ return validateStatus.getSeverity() == IStatus.OK;
+ }
+ }
+ }
+ return true;
+ }
+ public void doSave(IProgressMonitor monitor) {
+ try {
+ IDocument doc = fDocumentProvider.getDocument(fEditorInput);
+ fDocumentProvider.aboutToChange(fEditorInput);
+ flushModel(doc);
+ fDocumentProvider.saveDocument(monitor, fEditorInput, doc, true);
+ fDocumentProvider.changed(fEditorInput);
+ fValidated=false;
+ }
+ catch (CoreException e) {
+ PDEPlugin.logException(e);
+ }
+ }
+
+ protected abstract void addTextEditOperation(ArrayList ops, IModelChangedEvent event);
+
+ protected void flushModel(IDocument doc) {
+ if (fEditOperations.size() > 0) {
+ try {
+ MultiTextEdit edit = new MultiTextEdit();
+ for (int i = 0; i < fEditOperations.size(); i++) {
+ insert(edit, (TextEdit)fEditOperations.get(i));
+ }
+ if (fModel instanceof IEditingModel)
+ ((IEditingModel)fModel).setStale(true);
+ edit.apply(doc);
+ fEditOperations.clear();
+ if (fModel instanceof IEditable)
+ ((IEditable)fModel).setDirty(false);
+ } catch (MalformedTreeException e) {
+ PDEPlugin.logException(e);
+ } catch (BadLocationException e) {
+ PDEPlugin.logException(e);
+ }
+ }
+ }
+
+ protected static void insert(TextEdit parent, TextEdit edit) {
+ if (!parent.hasChildren()) {
+ parent.addChild(edit);
+ if (edit instanceof MoveSourceEdit) {
+ parent.addChild(((MoveSourceEdit)edit).getTargetEdit());
+ }
+ return;
+ }
+ TextEdit[] children= parent.getChildren();
+ // First dive down to find the right parent.
+ for (int i= 0; i < children.length; i++) {
+ TextEdit child= children[i];
+ if (covers(child, edit)) {
+ insert(child, edit);
+ return;
+ }
+ }
+ // We have the right parent. Now check if some of the children have to
+ // be moved under the new edit since it is covering it.
+ for (int i= children.length - 1; i >= 0; i--) {
+ TextEdit child= children[i];
+ if (covers(edit, child)) {
+ parent.removeChild(i);
+ edit.addChild(child);
+ }
+ }
+ parent.addChild(edit);
+ if (edit instanceof MoveSourceEdit) {
+ parent.addChild(((MoveSourceEdit)edit).getTargetEdit());
+ }
+ }
+
+ protected static boolean covers(TextEdit thisEdit, TextEdit otherEdit) {
+ if (thisEdit.getLength() == 0) // an insertion point can't cover anything
+ return false;
+
+ int thisOffset= thisEdit.getOffset();
+ int thisEnd= thisEdit.getExclusiveEnd();
+ if (otherEdit.getLength() == 0) {
+ int otherOffset= otherEdit.getOffset();
+ return thisOffset < otherOffset && otherOffset < thisEnd;
+ }
+ int otherOffset= otherEdit.getOffset();
+ int otherEnd= otherEdit.getExclusiveEnd();
+ return thisOffset <= otherOffset && otherEnd <= thisEnd;
+ }
+
+ public boolean mustSave() {
+ if (!fIsSourceMode) {
+ if (fModel instanceof IEditable) {
+ if (((IEditable)fModel).isDirty()) {
+ return true;
+ }
+ }
+ }
+ return fDocumentProvider.canSaveDocument(fEditorInput);
+ }
+
+ public void dispose() {
+ IAnnotationModel amodel = fDocumentProvider.getAnnotationModel(fEditorInput);
+ if (amodel != null)
+ amodel.disconnect(fDocumentProvider.getDocument(fEditorInput));
+ fDocumentProvider.removeElementStateListener(fElementListener);
+ fDocumentProvider.disconnect(fEditorInput);
+ if (fModelListener != null && fModel instanceof IModelChangeProvider) {
+ ((IModelChangeProvider) fModel)
+ .removeModelChangedListener(fModelListener);
+ //if (undoManager != null)
+ //undoManager.disconnect((IModelChangeProvider) model);
+ }
+ if (fModel!=null)
+ fModel.dispose();
+ }
+ /**
+ * @return Returns the primary.
+ */
+ public boolean isPrimary() {
+ return fPrimary;
+ }
+ /**
+ * @param primary The primary to set.
+ */
+ public void setPrimary(boolean primary) {
+ this.fPrimary = primary;
+ }
+
+ public boolean setSourceEditingMode(boolean sourceMode) {
+ fIsSourceMode = sourceMode;
+ if (sourceMode) {
+ // entered source editing mode; in this mode,
+ // this context's document will be edited directly
+ // in the source editor. All changes in the model
+ // are caused by reconciliation and should not be
+ // fired to the world.
+ flushModel(fDocumentProvider.getDocument(fEditorInput));
+ fMustSynchronize=true;
+ return true;
+ }
+ // leaving source editing mode; if the document
+ // has been modified while in this mode,
+ // fire the 'world changed' event from the model
+ // to cause all the model listeners to become stale.
+ return synchronizeModelIfNeeded();
+ }
+
+ private boolean synchronizeModelIfNeeded() {
+ if (fMustSynchronize) {
+ boolean result = synchronizeModel(fDocumentProvider.getDocument(fEditorInput));
+ fMustSynchronize=false;
+ return result;
+ }
+ return true;
+ }
+
+ public void doRevert() {
+ fMustSynchronize=true;
+ synchronizeModelIfNeeded();
+ /*
+ if (model instanceof IEditable) {
+ ((IEditable)model).setDirty(false);
+ }
+ */
+ }
+
+ public boolean isInSourceMode() {
+ return fIsSourceMode;
+ }
+
+ public boolean isModelCorrect() {
+ synchronizeModelIfNeeded();
+ return fModel!=null ? fModel.isValid() : false;
+ }
+
+ protected boolean synchronizeModel(IDocument doc) {
+ return true;
+ }
+ public boolean matches(IResource resource) {
+ if (fEditorInput instanceof IFileEditorInput) {
+ IFileEditorInput finput = (IFileEditorInput)fEditorInput;
+ IFile file = finput.getFile();
+ if (file.equals(resource))
+ return true;
+ }
+ return false;
+ }
+ /**
+ * @return Returns the validated.
+ */
+ public boolean isValidated() {
+ return fValidated;
+ }
+ /**
+ * @param validated The validated to set.
+ */
+ public void setValidated(boolean validated) {
+ this.fValidated = validated;
+ }
+
+ public String getLineDelimiter() {
+ if (fDocumentProvider != null) {
+ IDocument document = fDocumentProvider.getDocument(fEditorInput);
+ if (document != null) {
+ return TextUtilities.getDefaultLineDelimiter(document);
+ }
+ }
+ return System.getProperty("line.separator"); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContextManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContextManager.java
new file mode 100755
index 0000000..2198ef9
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContextManager.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.IModelUndoManager;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IModelChangeProvider;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+
+public abstract class InputContextManager implements IResourceChangeListener {
+ private PDEFormEditor editor;
+ private Hashtable inputContexts;
+ private ArrayList monitoredFiles;
+ private ArrayList listeners;
+ private IModelUndoManager undoManager;
+ /**
+ *
+ */
+ public InputContextManager(PDEFormEditor editor) {
+ this.editor = editor;
+ inputContexts = new Hashtable();
+ listeners = new ArrayList();
+ PDEPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
+ }
+
+ public void addInputContextListener(IInputContextListener listener) {
+ if (!listeners.contains(listener))
+ listeners.add(listener);
+ }
+ public void removeInputContextListener(IInputContextListener listener) {
+ listeners.remove(listener);
+ }
+ /**
+ *
+ *
+ */
+ public void dispose() {
+ PDEPlugin.getWorkspace().removeResourceChangeListener(this);
+ // dispose input contexts
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ unhookUndo(context);
+ context.dispose();
+ }
+ inputContexts.clear();
+ undoManager = null;
+ }
+ /**
+ * Saves dirty contexts.
+ * @param monitor
+ */
+ public void save(IProgressMonitor monitor) {
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ if (context.mustSave())
+ context.doSave(monitor);
+ }
+ }
+ public IProject getCommonProject() {
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ IEditorInput input = context.getInput();
+ if (input instanceof IFileEditorInput)
+ return ((IFileEditorInput)input).getFile().getProject();
+ }
+ return null;
+ }
+ public boolean hasContext(String id) {
+ return findContext(id) != null;
+ }
+ public InputContext findContext(String id) {
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ if (context.getId().equals(id))
+ return context;
+ }
+ return null;
+ }
+ public InputContext findContext(IResource resource) {
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ if (context.matches(resource))
+ return context;
+ }
+ return null;
+ }
+
+ public abstract IBaseModel getAggregateModel();
+
+ public InputContext getContext(IEditorInput input) {
+ return (InputContext)inputContexts.get(input);
+ }
+ public void putContext(IEditorInput input, InputContext context) {
+ inputContexts.put(input, context);
+ fireContextChange(context, true);
+ }
+ public InputContext getPrimaryContext() {
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ if (context.isPrimary())
+ return context;
+ }
+ return null;
+ }
+ public InputContext [] getInvalidContexts() {
+ ArrayList result = new ArrayList();
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ if (context.isModelCorrect()==false)
+ result.add(context);
+ }
+ return (InputContext[])result.toArray(new InputContext[result.size()]);
+ }
+
+ public boolean isDirty() {
+ for (Enumeration contexts=inputContexts.elements(); contexts.hasMoreElements();) {
+ InputContext context = (InputContext)contexts.nextElement();
+ if (context.mustSave())
+ return true;
+ }
+ return false;
+ }
+
+ public void monitorFile(IFile file) {
+ if (monitoredFiles==null) monitoredFiles = new ArrayList();
+ monitoredFiles.add(file);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+ */
+ public void resourceChanged(IResourceChangeEvent event) {
+ IResourceDelta delta = event.getDelta();
+
+ try {
+ delta.accept(new IResourceDeltaVisitor() {
+ public boolean visit(IResourceDelta delta) {
+ int kind = delta.getKind();
+ IResource resource = delta.getResource();
+ if (resource instanceof IFile) {
+ if (kind == IResourceDelta.ADDED)
+ asyncStructureChanged((IFile)resource, true);
+ else if (kind==IResourceDelta.REMOVED)
+ asyncStructureChanged((IFile)resource, false);
+ return false;
+ }
+ return true;
+ }
+ });
+ } catch (CoreException e) {
+ PDEPlugin.logException(e);
+ }
+ }
+
+ private void asyncStructureChanged(final IFile file, final boolean added) {
+ if (editor == null || editor.getEditorSite() == null)
+ return;
+ Shell shell = editor.getEditorSite().getShell();
+ Display display = shell != null ? shell.getDisplay() : Display.getDefault();
+
+ display.asyncExec(new Runnable() {
+ public void run() {
+ structureChanged(file, added);
+ }
+ });
+ }
+
+ private void structureChanged(IFile file, boolean added) {
+ if (monitoredFiles==null) return;
+ for (int i=0; i<monitoredFiles.size(); i++) {
+ IFile ifile = (IFile)monitoredFiles.get(i);
+ if (ifile.equals(file)) {
+ if (added) {
+ fireStructureChange(file, true);
+ }
+ else {
+ fireStructureChange(file, false);
+ removeContext(file);
+ }
+ }
+ }
+ }
+
+ private void removeContext(IFile file) {
+ for (Enumeration contexts = inputContexts.elements(); contexts
+ .hasMoreElements();) {
+ InputContext context = (InputContext) contexts.nextElement();
+ IEditorInput input = context.getInput();
+ if (input instanceof IFileEditorInput) {
+ IFileEditorInput fileInput = (IFileEditorInput)input;
+ if (file.equals(fileInput.getFile())) {
+ inputContexts.remove(input);
+ fireContextChange(context, false);
+ return;
+ }
+ }
+ }
+ }
+ protected void fireStructureChange(IFile file, boolean added) {
+ for (int i=0; i<listeners.size(); i++) {
+ IInputContextListener listener = (IInputContextListener)listeners.get(i);
+ if (added)
+ listener.monitoredFileAdded(file);
+ else
+ listener.monitoredFileRemoved(file);
+ }
+ }
+ protected void fireContextChange(InputContext context, boolean added) {
+ for (int i=0; i<listeners.size(); i++) {
+ IInputContextListener listener = (IInputContextListener)listeners.get(i);
+ if (added)
+ listener.contextAdded(context);
+ else
+ listener.contextRemoved(context);
+ }
+ if (added)
+ hookUndo(context);
+ else
+ unhookUndo(context);
+ }
+ public void undo() {
+ if (undoManager!=null && undoManager.isUndoable())
+ undoManager.undo();
+ }
+
+ public void redo() {
+ if (undoManager!=null && undoManager.isRedoable())
+ undoManager.redo();
+ }
+
+ private void hookUndo(InputContext context) {
+ if (undoManager==null) return;
+ IBaseModel model = context.getModel();
+ if (model instanceof IModelChangeProvider)
+ undoManager.connect((IModelChangeProvider)model);
+ }
+
+ private void unhookUndo(InputContext context) {
+ if (undoManager==null) return;
+ IBaseModel model = context.getModel();
+ if (model instanceof IModelChangeProvider)
+ undoManager.disconnect((IModelChangeProvider)model);
+ }
+ /**
+ * @return Returns the undoManager.
+ */
+ public IModelUndoManager getUndoManager() {
+ return undoManager;
+ }
+ /**
+ * @param undoManager The undoManager to set.
+ */
+ public void setUndoManager(IModelUndoManager undoManager) {
+ this.undoManager = undoManager;
+ }
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.java
new file mode 100644
index 0000000..aad1d27
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Helper class to get NLSed messages.
+ */
+//copied from same class in org.eclipse.ui.editors.text - no changes
+final class TextEditorMessages extends NLS {
+
+ private static final String BUNDLE_FOR_CONSTRUCTED_KEYS= "org.eclipse.ui.editors.text.ConstructedTextEditorMessages";//$NON-NLS-1$
+ private static ResourceBundle fgBundleForConstructedKeys= ResourceBundle.getBundle(BUNDLE_FOR_CONSTRUCTED_KEYS);
+
+ /**
+ * Returns the message bundle which contains constructed keys.
+ *
+ * @since 3.1
+ * @return the message bundle
+ */
+ public static ResourceBundle getBundleForConstructedKeys() {
+ return fgBundleForConstructedKeys;
+ }
+
+ private static final String BUNDLE_NAME= TextEditorMessages.class.getName();
+
+ private TextEditorMessages() {
+ // Do not instantiate
+ }
+
+ public static String PreferencePage_description;
+ public static String PreferencePage_fontEditor;
+ public static String FileDocumentProvider_createElementInfo;
+ public static String FileDocumentProvider_error_out_of_sync;
+ public static String FileDocumentProvider_task_saving;
+ public static String FileDocumentProvider_resetDocument;
+ public static String FileDocumentProvider_getPersistedEncoding;
+ public static String StorageDocumentProvider_updateCache;
+ public static String StorageDocumentProvider_isReadOnly;
+ public static String StorageDocumentProvider_isModifiable;
+ public static String StorageDocumentProvider_getContentDescriptionFor;
+ public static String StorageDocumentProvider_getContentDescription;
+ public static String TextFileDocumentProvider_beginTask_saving;
+ public static String TextFileDocumentProvider_error_doesNotExist;
+ public static String TextFileDocumentProvider_saveAsTargetOpenInEditor;
+ public static String Editor_error_save_message;
+ public static String Editor_error_save_title;
+ public static String Editor_warning_save_delete;
+ public static String Editor_error_unreadable_encoding_header;
+ public static String Editor_error_unreadable_encoding_banner;
+ public static String Editor_error_unreadable_encoding_message_arg;
+ public static String Editor_error_unreadable_encoding_message;
+ public static String Editor_error_unsupported_encoding_header;
+ public static String Editor_error_unsupported_encoding_banner;
+ public static String Editor_error_unsupported_encoding_message_arg;
+ public static String Editor_error_unsupported_encoding_message;
+ public static String Editor_ConvertEncoding_submenu_label;
+ public static String Editor_ConvertEncoding_Custom_dialog_title;
+ public static String Editor_ConvertEncoding_Custom_dialog_message;
+ public static String NullProvider_error;
+ public static String FileBufferOperationAction_collectionFiles_label;
+ public static String FileBufferOperationHandler_collectionFiles_label;
+ public static String ResourceInfo_fileContentEncodingFormat;
+ public static String ResourceInfo_fileContainerEncodingFormat;
+ public static String WorkbenchPreference_encoding_BOM_UTF_8;
+ public static String WorkbenchPreference_encoding_BOM_UTF_16BE;
+ public static String WorkbenchPreference_encoding_BOM_UTF_16LE;
+ public static String DocumentInputStream_error_read;
+ public static String DocumentInputStream_error_streamClosed;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, TextEditorMessages.class);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.properties b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.properties
new file mode 100644
index 0000000..3159244
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.properties
@@ -0,0 +1,65 @@
+###############################################################################
+# Copyright (c) 2000, 2005 IBM Corporation and others.
+# 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:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+# copied from same file in org.eclipse.ui.editors.text - no changes
+
+PreferencePage_description=Default Text Editor Settings
+PreferencePage_fontEditor=Text Font:
+
+FileDocumentProvider_createElementInfo=FileDocumentProvider.createElementInfo
+FileDocumentProvider_error_out_of_sync=Has been changed on the file system
+FileDocumentProvider_task_saving=Saving
+FileDocumentProvider_resetDocument=FileDocumentProvider.resetDocument
+FileDocumentProvider_getPersistedEncoding=Cannot migrate encoding property
+
+StorageDocumentProvider_updateCache=StorageDocumentProvider.updateCache
+StorageDocumentProvider_isReadOnly=StorageDocumentProvider.isReadOnly
+StorageDocumentProvider_isModifiable=StorageDocumentProvider.isModifiable
+StorageDocumentProvider_getContentDescriptionFor= Could not query content description for: {0}
+StorageDocumentProvider_getContentDescription= Could not query content description.
+
+TextFileDocumentProvider_beginTask_saving= Saving
+TextFileDocumentProvider_error_doesNotExist= File {0} does not exist.
+TextFileDocumentProvider_saveAsTargetOpenInEditor=Target file is already open in another editor.
+
+Editor_error_save_message=Save could not be completed. {0}
+Editor_error_save_title=Problems During Save As...
+Editor_warning_save_delete=The original file ''{0}'' has been deleted.
+
+Editor_error_unreadable_encoding_header=Character Encoding Problems
+Editor_error_unreadable_encoding_banner=
+Editor_error_unreadable_encoding_message_arg=This file is unreadable using the \"{0}\" character encoding.
+Editor_error_unreadable_encoding_message=This file is unreadable using the current character encoding.
+
+Editor_error_unsupported_encoding_header=Unsupported Character Encoding
+Editor_error_unsupported_encoding_banner=
+Editor_error_unsupported_encoding_message_arg=Character encoding \"{0}\" is not supported by this platform.
+Editor_error_unsupported_encoding_message= The current character encoding is not supported by this platform.
+
+Editor_ConvertEncoding_submenu_label=Enc&oding
+
+Editor_ConvertEncoding_Custom_dialog_title=Character Encoding
+Editor_ConvertEncoding_Custom_dialog_message=Enter the name of the character encoding:
+
+NullProvider_error= ERROR
+
+FileBufferOperationAction_collectionFiles_label=collecting files
+FileBufferOperationHandler_collectionFiles_label=collecting files
+
+# Copied from org.eclipse.ui.ide/org/eclipse/ui/internal/ide/messages.properties
+ResourceInfo_fileContentEncodingFormat= Default (determined from content: {0})
+ResourceInfo_fileContainerEncodingFormat= Default (inherited from container: {0})
+WorkbenchPreference_encoding_BOM_UTF_8= UTF-8 (BOM)
+WorkbenchPreference_encoding_BOM_UTF_16BE= UTF-16 Big-Endian (BOM)
+WorkbenchPreference_encoding_BOM_UTF_16LE= UTF-16 Little-Endian (BOM)
+
+DocumentInputStream_error_read= Could not read document:\n{0}
+DocumentInputStream_error_streamClosed= Stream closed
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/UTF8InputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/UTF8InputContext.java
new file mode 100644
index 0000000..5aab356
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/UTF8InputContext.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Jan 27, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+import org.eclipse.ajdt.pde.internal.ui.editor.*;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ui.*;
+
+
+public abstract class UTF8InputContext extends InputContext {
+ /**
+ * @param editor
+ * @param input
+ */
+ public UTF8InputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+ super(editor, input, primary);
+ }
+
+ protected String getDefaultCharset() {
+ return "UTF-8"; //$NON-NLS-1$
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLDocumentSetupParticpant.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLDocumentSetupParticpant.java
new file mode 100644
index 0000000..35a5b19
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLDocumentSetupParticpant.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import org.eclipse.core.filebuffers.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.rules.*;
+import org.eclipse.pde.internal.ui.editor.text.*;
+
+public class XMLDocumentSetupParticpant implements IDocumentSetupParticipant {
+
+ public void setup(IDocument document) {
+ IDocumentPartitioner partitioner = createDocumentPartitioner();
+ if (partitioner != null) {
+ partitioner.connect(document);
+ document.setDocumentPartitioner(partitioner);
+ }
+ }
+
+ private IDocumentPartitioner createDocumentPartitioner() {
+ FastPartitioner partitioner = new FastPartitioner(
+ new XMLPartitionScanner(), new String[]{
+ XMLPartitionScanner.XML_TAG,
+ XMLPartitionScanner.XML_COMMENT});
+ return partitioner;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLInputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLInputContext.java
new file mode 100644
index 0000000..1ae70f9
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLInputContext.java
@@ -0,0 +1,453 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.internal.core.text.IDocumentAttribute;
+import org.eclipse.pde.internal.core.text.IDocumentNode;
+import org.eclipse.pde.internal.core.text.IDocumentTextNode;
+import org.eclipse.pde.internal.core.util.CoreUtility;
+import org.eclipse.pde.internal.ui.editor.text.XMLPartitionScanner;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MoveSourceEdit;
+import org.eclipse.text.edits.MoveTargetEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorInput;
+
+public abstract class XMLInputContext extends UTF8InputContext {
+ protected HashMap fOperationTable = new HashMap();
+ protected HashMap fMoveOperations = new HashMap();
+
+ /**
+ * @param editor
+ * @param input
+ */
+ public XMLInputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+ super(editor, input, primary);
+ }
+
+ protected IDocumentPartitioner createDocumentPartitioner() {
+ FastPartitioner partitioner = new FastPartitioner(
+ new XMLPartitionScanner(), new String[]{
+ XMLPartitionScanner.XML_TAG,
+ XMLPartitionScanner.XML_COMMENT});
+ return partitioner;
+ }
+
+ protected IDocumentSetupParticipant getDocumentSetupParticipant() {
+ return new XMLDocumentSetupParticpant();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#addTextEditOperation(java.util.ArrayList, org.eclipse.pde.core.IModelChangedEvent)
+ */
+ protected void addTextEditOperation(ArrayList ops, IModelChangedEvent event) {
+ Object[] objects = event.getChangedObjects();
+ if (objects != null) {
+ for (int i = 0; i < objects.length; i++) {
+ Object object = objects[i];
+ switch (event.getChangeType()) {
+ case IModelChangedEvent.REMOVE :
+ if (object instanceof IDocumentNode)
+ removeNode((IDocumentNode) object, ops);
+ break;
+ case IModelChangedEvent.INSERT :
+ if (object instanceof IDocumentNode)
+ insertNode((IDocumentNode) object, ops);
+ break;
+ case IModelChangedEvent.CHANGE :
+ if (object instanceof IDocumentNode) {
+ IDocumentNode node = (IDocumentNode) object;
+ IDocumentAttribute attr = node.getDocumentAttribute(event.getChangedProperty());
+ if (attr != null) {
+ addAttributeOperation(attr, ops, event);
+ } else {
+ if (event.getOldValue() instanceof IDocumentTextNode) {
+ addElementContentOperation((IDocumentTextNode)event.getOldValue(), ops);
+ } else if (event.getOldValue() instanceof IDocumentNode && event.getNewValue() instanceof IDocumentNode){
+ // swapping of nodes
+ modifyNode(node, ops, event);
+ }
+ }
+ }
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ private void removeNode(IDocumentNode node, ArrayList ops) {
+ // delete previous op on this node, if any
+ TextEdit old = (TextEdit)fOperationTable.get(node);
+ if (old != null) {
+ ops.remove(old);
+ fOperationTable.remove(node);
+ }
+ TextEdit oldMove= (TextEdit)fMoveOperations.get(node);
+ if (oldMove != null) {
+ ops.remove(oldMove);
+ fMoveOperations.remove(node);
+ }
+ // if node has an offset, delete it
+ if (node.getOffset() > -1) {
+ // Create a delete op for this node
+ TextEdit op = getDeleteNodeOperation(node);
+ ops.add(op);
+ fOperationTable.put(node, op);
+ } else if (old == null && oldMove == null){
+ // No previous op on this non-offset node, just rewrite highest ancestor with an offset
+ insertNode(node, ops);
+ }
+ }
+
+ private void insertNode(IDocumentNode node, ArrayList ops) {
+ TextEdit op = null;
+ node = getHighestNodeToBeWritten(node);
+ if (node.getParentNode() == null) {
+ op = new InsertEdit(0, node.write(true));
+ } else {
+ if (node.getOffset() > -1) {
+ // this is an element that was of the form <element/>
+ // it now needs to be broken up into <element><new/></element>
+ op = new ReplaceEdit(node.getOffset(), node.getLength(), node.write(false));
+ } else {
+ // try to insert after last sibling that has an offset
+ op = insertAfterSibling(node);
+ // insert as first child of its parent
+ if (op == null) {
+ op = insertAsFirstChild(node);
+ }
+ }
+ }
+ TextEdit old = (TextEdit) fOperationTable.get(node);
+ if (old != null)
+ ops.remove(old);
+ ops.add(op);
+ fOperationTable.put(node, op);
+ }
+
+ private InsertEdit insertAfterSibling(IDocumentNode node) {
+ IDocumentNode sibling = node.getPreviousSibling();
+ for (;;) {
+ if (sibling == null)
+ break;
+ if (sibling.getOffset() > -1) {
+ node.setLineIndent(sibling.getLineIndent());
+ String sep = TextUtilities.getDefaultLineDelimiter(getDocumentProvider().getDocument(getInput()));
+ return new InsertEdit(sibling.getOffset() + sibling.getLength(), sep + node.write(true));
+ }
+ sibling = sibling.getPreviousSibling();
+ }
+ return null;
+ }
+
+ private InsertEdit insertAsFirstChild(IDocumentNode node) {
+ int offset = node.getParentNode().getOffset();
+ int length = getNextPosition(getDocumentProvider().getDocument(getInput()), offset, '>');
+ node.setLineIndent(node.getParentNode().getLineIndent() + 3);
+ String sep = TextUtilities.getDefaultLineDelimiter(getDocumentProvider().getDocument(getInput()));
+ return new InsertEdit(offset+ length + 1, sep + node.write(true));
+ }
+
+
+ private void modifyNode(IDocumentNode node, ArrayList ops, IModelChangedEvent event) {
+ IDocumentNode oldNode = (IDocumentNode)event.getOldValue();
+ IDocumentNode newNode = (IDocumentNode)event.getNewValue();
+
+ IDocumentNode node1 = (oldNode.getPreviousSibling() == null || oldNode.equals(newNode.getPreviousSibling())) ? oldNode : newNode;
+ IDocumentNode node2 = node1.equals(oldNode) ? newNode : oldNode;
+
+ if (node1.getOffset() < 0 && node2.getOffset() < 2) {
+ TextEdit op = (TextEdit)fOperationTable.get(node1);
+ if (op == null) {
+ // node 1 has no rule, so node 2 has no rule, therefore rewrite parent/ancestor
+ insertNode(node, ops);
+ } else {
+ // swap order of insert operations
+ TextEdit op2 = (TextEdit)fOperationTable.get(node2);
+ ops.set(ops.indexOf(op), op2);
+ ops.set(ops.indexOf(op2), op);
+ }
+ } else if (node1.getOffset() > -1 && node2.getOffset() > -1) {
+ // both nodes have offsets, so create a move target/source combo operation
+ IRegion region = getMoveRegion(node1);
+ MoveSourceEdit source = new MoveSourceEdit(region.getOffset(), region.getLength());
+ region = getMoveRegion(node2);
+ source.setTargetEdit(new MoveTargetEdit(region.getOffset()));
+ MoveSourceEdit op = (MoveSourceEdit)fMoveOperations.get(node1);
+ if (op != null) {
+ ops.set(ops.indexOf(op), source);
+ } else {
+ op = (MoveSourceEdit)fMoveOperations.get(node2);
+ if (op != null && op.getTargetEdit().getOffset() == source.getOffset()) {
+ fMoveOperations.remove(node2);
+ ops.remove(op);
+ return;
+ }
+ ops.add(source);
+ }
+ fMoveOperations.put(node1, source);
+ } else {
+ // one node with offset, the other without offset. Delete/reinsert the one without offset
+ insertNode((node1.getOffset() < 0) ? node1 : node2, ops);
+ }
+ }
+
+ private IRegion getMoveRegion(IDocumentNode node) {
+ int offset = node.getOffset();
+ int length = node.getLength();
+ int i = 1;
+ try {
+ IDocument doc = getDocumentProvider().getDocument(getInput());
+ for (;;i++) {
+ char ch = doc.get(offset - i, 1).toCharArray()[0];
+ if (!Character.isWhitespace(ch)) {
+ i -= 1;
+ break;
+ }
+ }
+ } catch (BadLocationException e) {
+ }
+ return new Region(offset - i, length + i);
+ }
+
+ private void addAttributeOperation(IDocumentAttribute attr, ArrayList ops, IModelChangedEvent event) {
+ int offset = attr.getValueOffset();
+ Object newValue = event.getNewValue();
+ Object changedObject = attr;
+ TextEdit op = null;
+ if (offset > -1) {
+ if (newValue == null || newValue.toString().length() == 0) {
+ int length = attr.getValueOffset() + attr.getValueLength() + 1 - attr.getNameOffset();
+ op = getAttributeDeleteEditOperation(attr.getNameOffset(), length);
+ } else {
+ op = new ReplaceEdit(offset, attr.getValueLength(), getWritableString(event.getNewValue().toString()));
+ }
+ }
+
+ if (op == null) {
+ IDocumentNode node = attr.getEnclosingElement();
+ IDocument doc = getDocumentProvider().getDocument(getInput());
+ if (node.getOffset() > -1) {
+ changedObject = node;
+ int len = getNextPosition(doc, node.getOffset(), '>');
+ op = new ReplaceEdit(node.getOffset(), len + 1, node.writeShallow(shouldTerminateElement(doc, node.getOffset() + len)));
+ } else {
+ insertNode(node, ops);
+ return;
+ }
+ }
+ TextEdit oldOp = (TextEdit)fOperationTable.get(changedObject);
+ if (oldOp != null)
+ ops.remove(oldOp);
+ ops.add(op);
+ fOperationTable.put(changedObject, op);
+ }
+
+ private void addElementContentOperation(IDocumentTextNode textNode, ArrayList ops) {
+ TextEdit op = null;
+ Object changedObject = textNode;
+ if (textNode.getOffset() > -1) {
+ String newText = getWritableString(textNode.getText());
+ op = new ReplaceEdit(textNode.getOffset(), textNode.getLength(), newText);
+ } else {
+ IDocumentNode parent = textNode.getEnclosingElement();
+ if (parent.getOffset() > -1) {
+ IDocument doc = getDocumentProvider().getDocument(getInput());
+ try {
+ String endChars = doc.get(parent.getOffset() + parent.getLength() - 2, 2);
+ if ("/>".equals(endChars)) { //$NON-NLS-1$
+ // parent element is of the form <element/>, rewrite it
+ insertNode(parent, ops);
+ return;
+ }
+ } catch (BadLocationException e) {
+ }
+ // add text as first child
+ changedObject = parent;
+ String sep = TextUtilities.getDefaultLineDelimiter(getDocumentProvider().getDocument(getInput()));
+ StringBuffer buffer = new StringBuffer(sep);
+ for (int i = 0; i < parent.getLineIndent(); i++)
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(" " + getWritableString(textNode.getText())); //$NON-NLS-1$
+ int offset = parent.getOffset();
+ int length = getNextPosition(doc, offset, '>');
+ op = new InsertEdit(offset+ length + 1, buffer.toString());
+ } else {
+ insertNode(parent, ops);
+ return;
+ }
+ }
+ TextEdit oldOp = (TextEdit)fOperationTable.get(changedObject);
+ if (oldOp != null)
+ ops.remove(oldOp);
+ ops.add(op);
+ fOperationTable.put(changedObject, op);
+ }
+
+ private boolean shouldTerminateElement(IDocument doc, int offset) {
+ try {
+ return doc.get(offset-1, 1).toCharArray()[0] == '/';
+ } catch (BadLocationException e) {
+ }
+ return false;
+ }
+
+ private int getNextPosition(IDocument doc, int offset, char ch) {
+ int i = 0;
+ try {
+ for (i = 0; i + offset < doc.getLength() ;i++) {
+ if (ch == doc.get(offset + i, 1).toCharArray()[0])
+ break;
+ }
+ } catch (BadLocationException e) {
+ }
+ return i;
+ }
+
+ private DeleteEdit getAttributeDeleteEditOperation(int offset, int length) {
+ try {
+ IDocument doc = getDocumentProvider().getDocument(getInput());
+ for (;;) {
+ char ch = doc.get(offset + length, 1).toCharArray()[0];
+ if (!Character.isWhitespace(ch)) {
+ break;
+ }
+
+ length += 1;
+ }
+ } catch (BadLocationException e) {
+ }
+ return new DeleteEdit(offset, length);
+ }
+
+
+ private DeleteEdit getDeleteNodeOperation(IDocumentNode node) {
+ int offset = node.getOffset();
+ int length = node.getLength();
+ int indent = 0;
+ try {
+ IDocument doc = getDocumentProvider().getDocument(getInput());
+ int line = doc.getLineOfOffset(offset + length);
+ for (;;) {
+ char ch = doc.get(offset + length, 1).toCharArray()[0];
+ if (doc.getLineOfOffset(offset + length) > line || !Character.isWhitespace(ch)) {
+ length -= 1;
+ break;
+ }
+ length += 1;
+ }
+
+ for (indent = 1; indent <= node.getLineIndent(); indent++) {
+ char ch = doc.get(offset - indent, 1).toCharArray()[0];
+ if (!Character.isWhitespace(ch)) {
+ indent -= 1;
+ break;
+ }
+
+ }
+ //System.out.println("\"" + getDocumentProvider().getDocument(getInput()).get(offset-indent, length + indent) + "\"");
+ } catch (BadLocationException e) {
+ }
+ return new DeleteEdit(offset - indent, length + indent);
+
+ }
+
+ private IDocumentNode getHighestNodeToBeWritten(IDocumentNode node) {
+ IDocumentNode parent = node.getParentNode();
+ if (parent == null)
+ return node;
+ if (parent.getOffset() > -1) {
+ IDocument doc = getDocumentProvider().getDocument(getInput());
+ try {
+ String endChars = doc.get(parent.getOffset() + parent.getLength() - 2, 2);
+ return ("/>".equals(endChars)) ? parent : node; //$NON-NLS-1$
+ } catch (BadLocationException e) {
+ return node;
+ }
+
+ }
+ return getHighestNodeToBeWritten(parent);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#flushModel(org.eclipse.jface.text.IDocument)
+ */
+ protected void flushModel(IDocument doc) {
+ removeUnnecessaryOperations();
+ if (fOperationTable.size() == 1) {
+ Object object = fOperationTable.keySet().iterator().next();
+ if (object instanceof IDocumentNode && fEditOperations.get(0) instanceof InsertEdit) {
+ if (((IDocumentNode)object).getParentNode() == null) {
+ doc.set(((IDocumentNode)object).write(true));
+ fOperationTable.clear();
+ fEditOperations.clear();
+ return;
+ }
+ }
+ }
+ reorderInsertEdits(fEditOperations);
+ fOperationTable.clear();
+ fMoveOperations.clear();
+ super.flushModel(doc);
+ }
+
+ protected abstract void reorderInsertEdits(ArrayList ops);
+
+ protected void removeUnnecessaryOperations() {
+ Iterator iter = fOperationTable.values().iterator();
+ while (iter.hasNext()) {
+ Object object = iter.next();
+ if (object instanceof IDocumentNode) {
+ IDocumentNode node = (IDocumentNode)object;
+ if (node.getOffset() > -1) {
+ IDocumentAttribute[] attrs = node.getNodeAttributes();
+ for (int i = 0; i < attrs.length; i++) {
+ Object op = fOperationTable.remove(attrs[i]);
+ if (op != null)
+ fEditOperations.remove(op);
+ }
+ IDocumentTextNode textNode = node.getTextNode();
+ if (textNode != null) {
+ Object op = fOperationTable.remove(textNode);
+ if (op != null)
+ fEditOperations.remove(op);
+ }
+ }
+ }
+ }
+ }
+
+
+ public String getWritableString(String source) {
+ return CoreUtility.getWritableString(source);
+ }
+
+ protected HashMap getOperationTable() {
+ return fOperationTable;
+ }
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/ui/buildconfig/BuildConfigPlugin.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/ui/buildconfig/BuildConfigPlugin.java
new file mode 100644
index 0000000..247eb26
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/ui/buildconfig/BuildConfigPlugin.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Matt Chapman - initial version
+ *******************************************************************************/
+package org.eclipse.ajdt.ui.buildconfig;
+
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.internal.buildconfig.BCResourceChangeListener;
+import org.eclipse.ajdt.internal.buildconfig.BCWorkbenchWindowInitializer;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.ui.IStartup;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+public class BuildConfigPlugin extends AbstractUIPlugin implements IStartup {
+ public void start(BundleContext context) throws Exception {
+ // register the our build config implementations with ajdt.ui
+ DefaultBuildConfigurator.setBuildConfigurator(new BuildConfigurator());
+
+ super.start(context);
+
+ // Update project menu and listen for project selections
+ new BCWorkbenchWindowInitializer();
+
+ // listener for build configurator
+ AspectJPlugin.getWorkspace().addResourceChangeListener(
+ new BCResourceChangeListener(),
+ IResourceChangeEvent.PRE_CLOSE
+ | IResourceChangeEvent.PRE_DELETE
+ | IResourceChangeEvent.POST_CHANGE
+ | IResourceChangeEvent.PRE_BUILD);
+ }
+
+ public void earlyStartup() {
+ }
+}