The remaining plug-ins in the Eclipse Platform are truly oriented toward writing development tools. This chapter covers elements of the Eclipse IDE workbench, found in the org.eclipse.ui.ide
plug-in. This plug-in includes most of the standard platform views, such as Navigator, Tasks, Problems, Properties, and Bookmark. We also take a quick look at advanced topics, such as writing repository clients and debuggers.
In Eclipse 2.1, use the openEditor
methods on IWorkbenchPage
to open files in the workspace. In 3.0, this API was moved to the IDE class in order to remove the dependency between the generic workbench and the workspace. If you use openEditor(IFile)
, the platform will guess the appropriate editor to use, based on the file extension.
To open an editor to a particular position, you can create a marker in the file and then use openEditor(IMarker)
. Be sure to get rid of the marker when you’re done. You can specify what editor to open by setting the EDITOR_ID_ATTR
on the marker. If you don’t do this, the workbench will guess what kind of editor to open from the file extension. The following code snippet opens the default text editor to line 5, using a marker:
IFile file = <choose the file to open>; IWorkbenchPage page = ; HashMap map = new HashMap(); map.put(IMarker.LINE_NUMBER, new Integer(5)); map.put(IWorkbenchPage.EDITOR_ID_ATTR, "org.eclipse.ui.DefaultTextEditor"); IMarker marker = file.createMarker(IMarker.TEXT); marker.setAttributes(map); //page.openEditor(marker); //2.1 API IDE.openEditor(marker); //3.0 API marker.delete();
You can open a read-only editor on a file outside the workspace by creating your own implementation of IStorage
and IStorageEditorInput
for the file. Alternatively, you can create a linked resource in an existing project, which points to a file elsewhere in the file system. This example snippet creates a project called “External Files,” and then prompts the user to select any file in the file system. The code then creates a linked resource in the project to that external file, allowing the platform to open the file in read/write mode in one of the standard editors:
IWorkspace ws = ResourcesPlugin.getWorkspace(); IProject project = ws.getRoot().getProject("External Files"); if (!project.exists()) project.create(null); if (!project.isOpen()) project.open(null); Shell shell = window.getShell(); String name = new FileDialog(shell, SWT.OPEN).open(); if (name == null) return; IPath location = new Path(name); IFile file = project.getFile(location.lastSegment()); file.createLink(location, IResource.NONE, null); IWorkbenchPage page = window.getActivePage(); if (page != null) page.openEditor(file);
Most editors will accept as input either an IFileEditorInput
or an IStorageEditorInput
. The former can be used only for opening files in the workspace, but the latter can be used to open a stream of bytes from anywhere. If you want to open a file on a database object, remote file, or other data source, IStorage
is the way to go. The only downside is that this is a read-only input type, so you can use it only for viewing a file, not editing it. To use this approach, implement IStorage
so that it returns the bytes for the file you want to display. Here is an IStorage
that returns the contents of a string:
class StringStorage extends PlatformObject implements IStorage { private String string; StringStorage(String input) {this.string = input;} public InputStream getContents() throws CoreException { return new ByteArrayInputStream(string.getBytes()); } public IPath getFullPath() {return null;} public String getName() { int len = Math.min(5, string.length()); return string.substring(0, len).concat("..."); } public boolean isReadOnly() {return true;} }
The class extends PlatformObject
to inherit the standard implementation of IAdaptable
, which IStorage
extends. The getName
and getFullPath
methods can return null
if they are not needed. In this case, we’ve implemented getName
to return the first five characters of the string.
The next step is to create an IStorageEditorInput
implementation that returns your IStorage
object:
class StringInput extends PlatformObject implements IStorageEditorInput { private IStorage storage; StringInput(IStorage storage) {this.storage = storage;} public boolean exists() {return true;} public ImageDescriptor getImageDescriptor() {return null;} public String getName() { return storage.getName(); } public IPersistableElement getPersistable() {return null;} public IStorage getStorage() { return storage; } public String getToolTipText() { return "String-based file: " + storage.getName(); } }
Again, many of the methods here are optional. The getPersistable
method is used for implementing persistence of your editor input, so the platform can automatically restore your editor on start-up. Here, we’ve implemented the bare essentials: the editor name, and a tool tip.
The final step is to open an editor with this input. This snippet opens the platform’s default text editor on a given string:
IWorkbenchWindow window = ...; String string = "This is the text file contents"; IStorage storage = new StringStorage(string); IStorageEditorInput input = new StringInput(storage); IWorkbenchPage page = window.getActivePage(); if (page != null) page.openEditor(input, "org.eclipse.ui.DefaultTextEditor");
The Tasks view, also called the task list, shows all markers of type org.eclipse.core.resources.taskmarker
, as well as any marker type that declares taskmarker
as a supertype. Prior to Eclipse 3.0, the task list also showed markers of type problemmarker
. In 3.0, problem markers appear in the Problems view instead. If you define a custom marker with one of these types, it will appear in either the Tasks or Problems view automatically. Note that if you don’t see your marker there, it might have been filtered out. Check the filter dialog to ensure that your marker type is selected.
Text editors in Eclipse can display markers in a number of ways. Most commonly, they appear as icons in the vertical rule on the left-hand side of the editor pane. Markers can also optionally be displayed as squiggly underlays in the text and in the overview ruler on the right-hand side of the editor. How each type of marker is displayed is chosen by the user on the editor preference pages (Workbench > Editors > Text Editor > Annotations and Java > Editor > Annotations). The IMarker
interface declares a number of frequently used marker types. Any created marker that has either the LINE_NUMBER
or CHAR_START
and CHAR_END
attributes set will be displayed by editors. These attributes must exist when the marker is created for the marker to appear in an editor. The most common mistake is to create the marker and then add the attributes in a separate operation. The text framework provides a utility class called MarkerUtilities
to make this easier for you. Here is a sample snippet that adds a marker correctly:
int lineNumber = ...; HashMap map = new HashMap(); MarkerUtilities.setLineNumber(map, lineNumber); MarkerUtilities.createMarker(resource, map, IMarker.TEXT);
FAQ 288 How do I create my own tasks, problems, bookmarks, and so on?
This question is often asked by newcomers to Eclipse, probably as a result of switching from another IDE with a different interpretation of the term project. Similarly, people often ask how to access the “active” file. In Eclipse there is no such thing as an active project or file. Projects can be opened or closed, but many projects may be open at any given time.
Often people are really asking for the currently selected project, folder, or file. The selection can be queried using the UI’s ISelectionService
.
Once you have the selection, you can extract the selected resource as follows:
IResource extractSelection(ISelection sel) { if (!(sel instanceof IStructuredSelection)) return null; IStructuredSelection ss = (IStructuredSelection)sel; Object element = ss.getFirstElement(); if (element instanceof IResource) return (IResource) element; if (!(element instanceof IAdaptable)) return null; IAdaptable adaptable = (IAdaptable)element; Object adapter = adaptable.getAdapter(IResource.class); return (IResource) adapter; }
If you are looking for the active editor, you can determine that from the IPartService
. If an editor is active, you can extract the resource, if available, like this:
IResource extractResource(IEditorPart editor) { IEditorInput input = editor.getInput(); if (!(input instanceof IFileEditorInput)) return null; return ((IFileEditorInput)input).getFile(); }
FAQ 168 How do I find out what object is selected?
IWorkspaceRunnable
is a mechanism for batching a set of changes to the workspace so that change notification and autobuild are deferred until the entire batch completes. IRunnableWithProgress
is a mechanism for batching a set of changes to be run outside the UI thread. You often need to do both of these at once: Make multiple changes to the workspace outside the UI thread. Wrapping one of these mechanisms inside the other would do the trick, but the resulting code is cumbersome, and it is awkward to communicate arguments, results, and exceptions between the caller and the operation to be run.
The solution is to use WorkspaceModifyOperation
. This class rolls the two mechanisms together by implementing IRunnableWithProgress
and performing the work within a nested IWorkspaceRunnable
. To use it, simply create a subclass that implements the abstract method execute
, and pass an instance of this subclass to IRunnableContext.run
to perform the work. If you already have an instance of IRunnableWithProgress
on hand, it can be passed to the constructor of the special subclass WorkspaceModifyDelegatingOperation
to create a new IRunnableWithProgress
that performs workspace batching for you.
Many of the people asking this question are confused by the fact that two Eclipse instances are in use when you are developing plug-ins. One is the development platform you are using as your IDE, and the other is the target platform—also known as the runtime workbench—consisting of the plug-ins in the development workbench you are testing against. When a plug-in in the target platform writes a message to System.out
or System.err
, the message appears in the Console view of the development platform. This view emulates the Java console that appears when Eclipse runs under Windows with java.exe
. You should be writing to the console only in this manner when in debug mode (see FAQ 122).
In some situations however, a plug-in in the development platform has a legitimate reason to write to the development platform Console view. Some tools originally designed for the command line, such as Ant and CVS, traditionally use console output as a way of communicating results to the tool user. When these tools are ported for use with an IDE, this console output is typically replaced with richer forms of feedback, such as views, markers, and decorations. However, users accustomed to the old command-line output may still want to see this raw output as an alternative to other visual forms of feedback. Tools in this category can use the Console view to write this output.
Prior to Eclipse 3.0, each plug-in that wanted console-like output created its own Console view. Eclipse 3.0 provides a single generic Console view that all plug-ins can write to. The view can host several console documents at once and allows the user to switch between different console pages. Each page in the console is represented by an org.eclipse.ui.console.IConsole
object. To write to the console, you need to create your own IConsole
instance and connect it to the Console view. For a console containing a simple text document, you can instantiate a MessageConsole
instance. Here is a method that locates a console with a given name and creates a new one if it cannot be found:
private MessageConsole findConsole(String name) { ConsolePlugin plugin = ConsolePlugin.getDefault(); IConsoleManager conMan = plugin.getConsoleManager(); IConsole[] existing = conMan.getConsoles(); for (int i = 0; i < existing.length; i++) if (name.equals(existing[i].getName())) return (MessageConsole) existing[i]; //no console found, so create a new one MessageConsole myConsole = new MessageConsole(name, null); conMan.addConsoles(new IConsole[]{myConsole}); return myConsole; }
Once a console is created, you can write to it either by directly modifying its IDocument
or by opening an output stream on the console. This snippet opens a stream and writes some text to a console:
MessageConsole myConsole = findConsole(CONSOLE_NAME); MessageConsoleStream out = myConsole.newMessageStream(); out.println("Hello from Generic console sample action");
Creating a console and writing to it do not create or reveal the Console view. If you want to make that sure the Console view is visible, you need to reveal it using the usual workbench API. Even once the Console view is revealed, keep in mind that it may contain several pages, each representing a different IConsole
provided by a plug-in. Additional API asks the Console view to display your console. This snippet reveals the Console view and asks it to display a particular console instance:
IConsole myConsole = ...;//your console instance IWorkbenchPage page = ...;//obtain the active page String id = IConsoleConstants.ID_CONSOLE_VIEW; IConsoleView view = (IConsoleView) page.showView(id); view.display(myConsole);
Several dialogs are available for prompting the user to select one or more resources in the workspace. Each dialog has its own particular attributes and uses, and supports varying degrees of customization based on your needs. Note that you can change the title of many of these dialogs by using the method SelectionDialog.setTitle
to suit your particular application. Here is a summary of the available dialogs:
ContainerSelectionDialog
prompts the user to select a single project or folder in the workspace. This dialog be configured to allow the user to specify a folder that does not yet exist.
ElementListSelectionDialog
is a powerful generic selection dialog that is widely used throughout the workbench. This dialog has a text box at the top that allows the user to enter a pattern. As the user types, the list below narrows down to show only the matching elements. The input elements can be any kind of objects.
TwoPaneElementSelector
is much like ElementListSelectionDialog
, except an extra qualifier list is added at the bottom. When a match is selected in the middle pane, the corresponding qualifiers are shown in the bottom pane. This is used most prominently by the Open Type and Open Resource actions. In these dialogs, the qualifier is either the package or folder name for the resource that is selected in the middle pane.
NewFolderDialog
prompts the user to enter the name of a new folder directly below a supplied parent container. This dialog allows the user to create a linked folder that maps to a directory in the file system outside the project content area.
ResourceListSelectionDialog
prompts the user to select a single resource from a flat list of resource names. This dialog can be configured with a resource type mask to narrow the list to only folders, only files, or both. The user can enter a filter pattern to narrow down the list of resources. Filtering and populating the dialog are done in a background thread to ensure responsiveness in large workspaces. This dialog is designed to be subclassed to allow for further customization.
ResourceSelectionDialog
prompts the user to select one or more resources below a given root. This dialog displays a table tree of containers on the left-hand side and a list of resources on the right-hand side, just like the panes at the top of the file system export wizard.
FileSelectionDialog
is deprecated in Eclipse 3.0. Its intent was to provide a generic dialog to allow the user to make selections from file-system-like structures such as the workspace, zip files, or the actual file system. Most of the functionality of this dialog can be found in other dialogs.
SaveAsDialog
has hard-coded title and messages; otherwise, it could be used in any context requiring a file selection. The user can supply the name of a new or existing file. This dialog is the file equivalent of ContainerSelectionDialog
. The dialog returns an IPath
result and does not check whether the file or parent folders already exist.
The FAQ Examples plug-in for this book includes an action called ResourceSelectionAction
that demonstrates the use of all these dialogs.
FAQ 142 How do I prompt the user to select a file or a directory?
Yes. All the resource actions in the Navigator view, including Copy, Move, Delete, Build, and Refresh, are available as API. These actions are found in the org.eclipse.ui.actions
package of the org.eclipse.ui.ide
plug-in. These actions expect a selection of either IResource
objects or IAdaptable
objects that are able to adapt to IResource
. You must either install the actions as selection change listeners, such as on a TreeViewer
, or supply them with the selection before running them:
IResource r = ...;//resource to delete IStructuredSelection ss = new StructuredSelection(r); DeleteResourceAction delete = new DeleteResourceAction(shell); delete.selectionChanged(ss); delete.run();
FAQ 126 How do I use IAdaptable
and IAdapterFactory
?
Repositories, or version and configuration management (VCM) tools, are an essential part of software development. A wide variety of code repositories and a larger number of client-side tools for interacting with those repositories are available. These clients range from rudimentary command-line tools to rich graphical clients that are deeply integrated with other development tools. As a tool-integration platform, repository client integration is an important aspect of Eclipse. From the very start, the core architecture of the Eclipse Platform has striven to allow deep integration of these repository client tools.
Early on, Eclipse used the term VCM as a label for its repository integration components. Because acronyms in general aren’t particularly descriptive and because this particular acronym didn’t seem to be widely understood, the Eclipse Platform adopted the term team tools as a replacement. This is why the repository APIs are found in the plug-ins org.eclipse.team.core
and org.eclipse.team.ui
and why the developers writing this stuff call themselves the team team.
As with many Eclipse components, team tooling is divided into a generic, repository-agnostic layer and then separate layers for specific repository clients. The platform includes a reference implementation of the generic team APIs, which implements a powerful graphical client for integrating with concurrent versions system, or CVS. The team API centers on the notion of a repository provider. Each project in an Eclipse workspace can be associated with a single RepositoryProvider
subclass that acts as the entry point for repository interaction. The RepositoryProvider
API and the remainder of the team-integration APIs are extremely well documented, so we don’t need to go into more detail here.
The Platform Plug-in Developer Guide includes detailed documentation on how to implement your own repository provider. See the section Programmer’s guide > Team support.
FAQ 299 What support does the workspace have for team tools?
Some development tools include support for pushing projects to a remote server, using such protocols as FTP and WebDAV. Then an ongoing challenge is to keep the old workspace contents synchronized with the remote content as files in the workspace and on the remote server are added, removed, or changed. The Eclipse team API includes generic infrastructure for deploying workspace contents to a remote location and for keeping the two copies synchronized.
The main entry point for this kind of team integration is the notion of a team subscriber. A subclass of TeamSubscriber
specifies the logic for comparing workspace contents to a remote resource and for performing synchronization. The team API has support for building and maintaining a model of remote resources and the synchronization state between remote and local resources. A subscriber can use the generic Synchronize view to allow users to browse the differences between local and remote copies and for refreshing and synchronizing the two. The org.eclipse.team.ui.synchronize
package includes API for adding pages to the Synchronize view and for displaying the synchronization model created by a team subscriber.
See the Platform Plug-in Developer Guide under Programmer’s Guide > Team support for complete details on how to implement your own team subscriber and for integrating with the generic Synchronize view.
The Eclipse Platform team component supports two categories of tool integration. Of primary interest are repository providers, which represent full-fledged versioning and configuration management tools, such as CVS, ClearCase
, and Subversion
. These tools typically include support for maintaining an arbitrary number of versions of files and file trees, for branching and merging development streams, and for linking versions to bug tracking and other configuration management tools. Clients for interacting with these tools are represented in Eclipse through the RepositoryProvider
API.
Another class of team tooling is used for deployment of development artifacts to a remote execution target. For example, you may use FTP or WebDAV to deploy code and other resources to a Web server, or a proprietary protocol for deploying code to embedded and hand-held devices. This class of tooling is represented by the team subscriber API.
Note the extensive overlap between these two categories of team tooling. In general, team subscribers represent a subset of the functionality provided by a repository client. In other words, if you’re writing a client for a repository, you will most likely need both the repository provider and the team subscriber API.
A launch configuration is a description of how to launch a program. The program itself may be a Java program, another Eclipse instance in the form of a runtime workbench, a C program, or something else. Launch configurations are manifested in the Eclipse UI through Run > Run....
Launching in Eclipse is closely tied to the infrastructure for debugging, enabling you to make the logical progression from support for launching to support for interactive debugging. This is why you will find launch configurations in the org.eclipse.debug.core
plug-in.
For extensive documentation on how to add your own launch configuration, refer to Platform Plug-in Developer Guide under Programmer’s Guide > Program debug and launch support.
A launch configuration captures all the information required to launch a particular application, but the launching is performed by a launch delegate. This separation allows a single launch configuration to be used by several launch delegates to launch an application in different ways using the same launch information. For example, there is a single launch-configuration type for launching Java programs but different launch delegates for launching in run mode versus debug mode. One could define more delegates for launching Java programs by associating with the existing Java launch-configuration type. This example shows a declaration of a launch delegate for launching Java applications in a special profiling mode:
<extension point="org.eclipse.debug.core.launchDelegates"> <launchDelegate id="org.eclipse.faq.example.traceDelegate" delegate="org.eclipse.faq.example.TraceLauncher" type="org.eclipse.jdt.launching.localJavaApplication" modes="trace"/> </extension>
For more information on launch delegates, see the documentation for the org.eclipse.debug.core.launchDelegates
extension point and the javadoc for ILaunchConfigurationDelegate
in the debug core plug-in.
Ant is a Java-based build tool created as part of the Apache open-source project. You can think of it as a Java version of make. Ant scripts have a structure and are written in XML. Similar to make, Ant targets can depend on other targets. For example, Ant is used in the context of plug-in development in the build.xml
, created from a plugin.xml
file for assembling a deployable version of your plug-in.
The Ant UI as provided in Eclipse comes with a first-class Ant build-file editor, including syntax highlighting, Content Assist, templates, and content formatting. This editor is automatically associated with files named build.xml
and can be associated with other file names from the Workbench > File Associations preference page.
The Ant UI also has a wizard for running Ant scripts and a toolbar button for repeating previous builds.
For more details, such as how to run Ant scripts programmatically, refer to Platform Plug-in Developer Guide under Programmer’s Guide > Platform Ant support.
Ant tasks that include the javac
task for compiling Java source will fail if a Java compiler cannot be found. This results in an error message like the following:
Unable to find a javac compiler; com.sun.tools.javac.Main is not on the classpath. Perhaps JAVA_HOME does not point to the JDK
This simply means that Ant could not find a Java compiler. The easiest solution is to make sure that tools.jar
, which is included with any JDK—as opposed to a JRE—is on Ant’s classpath. You can add items to Ant’s classpath from the Ant > Runtime preference page. If you launch Eclipse by using a full JDK instead of a JRE, tools.jar
should appear on the Ant classpath automatically.
Alternatively, Ant supports the notion of a compiler adapter, allowing you to plug in your own Java compiler, such as the Java compiler that is built into Eclipse. The Eclipse compiler adapter is found in the org.eclipse.jdt.core
in jdtCompilerAdapter.jar
. Again, you need to make sure that this JAR is on Ant’s classpath from the Ant preference page. Then, simply add the following line to your build file to specify the compiler:
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
FAQ 315 What is Ant?
External tools are applications or scripts that typically act as extensions to your development environment. For example, they may be used to execute scripts to package and deploy your application or to run an external compiler on your source files. External tools allow an end user to achieve a basic level of integration for a non-Eclipse-aware tool without writing a plug-in. External tools are created and configured via Run > External Tools > External Tools or from the drop-down menu on the Run button with the toolbox overlay.
If you want to write your own category of external tool, such as support for a different scripting language, you need to write a plug-in. The process for defining external tools is almost identical to writing your own launch configuration. Essentially, an external tool is a launch-configuration type that belongs to the special external-tools category:
<launchConfigurationType
name="My Tool"
delegate="com.xyz.MyLaunchDelegate"
category="org.eclipse.ui.externaltools"
modes="run"
id="com.xyz.MyLaunchType">
</launchConfigurationType>
FAQ 313 What is a launch configuration?
An external tool builder is an external tool that runs every time the projects in your workspace are built. End users can add external tool builders by selecting a project in the Navigator, choosing Properties, and then going to the Builders page. On the Build Options tab, you can specify whether the builder should run on autobuild, manual build, or on Clean. In most cases, running external tool builders during auto-builds is too disruptive because they are too long running.
As with ordinary external tools, you can define your own type of external tool builder by creating a new launch configuration type. In your launch configuration declaration, you must specify the category for external tool builder launch configurations:
<launchConfigurationType
name="%AntBuild"
delegate="com.xyz.MyLaunchDelegate"
category="org.eclipse.ui.externaltools.builder"
modes="run"
id="com.xyz.MyLaunchType">
</launchConfigurationType>
18.191.29.22