Tuesday, December 16, 2008

Sunday, December 07, 2008

Hooking into Eclipse command execution

When I was working on implementing the Clips plug-in I wanted to intercept the Cut and Copy actions and automatically create clips from the selection. To my delight I discovered the necessary mechanism to exactly do that. Basically I had to add the following listener:
// Add listener to monitor Cut and Copy commands
ICommandService commandService = (ICommandService) PlatformUI
.getWorkbench().getAdapter(ICommandService.class);
if (commandService != null) {
commandService.addExecutionListener(new IExecutionListener() {

public void notHandled(String commandId,
NotHandledException exception) {
}

public void postExecuteFailure(String commandId,
ExecutionException exception) {
}

public void postExecuteSuccess(String commandId,
Object returnValue) {
// Is it a Cut or Copy command
if ("org.eclipse.ui.edit.copy".equals(commandId)
|| "org.eclipse.ui.edit.cut".equals(commandId)) {
Clipboard clipboard = new Clipboard(PlatformUI
.getWorkbench().getActiveWorkbenchWindow()
.getShell().getDisplay());
Object contents = clipboard
.getContents(TextTransfer.getInstance());
if (contents instanceof String) {
// Now do something with text selection
}
}

}

public void preExecute(String commandId, ExecutionEvent event) {
}

});
}

Cool huh?

Thursday, November 27, 2008

Graphical cd

The following bash function allows you to change directory using a Directory chooser:
gcd() {
local CDTO=`zenity --title="cd" --file-selection --directory`
if [ -n "${CDTO}" ] ; then
cd "${CDTO}"
fi
}

Clips Eclipse Plug-in

Check out the new Clips Eclipse plug-in here.

Clips View


Clips Preferences

Thursday, November 13, 2008

Zero length Java array cache

Many times I find myself declaring private static final zero length array fields of some type or the other. Some times the zero length arrays for a same type are declared in more than one place. To avoid this, I came up with the simple zero length array cache backed by a WeakHashMap. The beauty of this is that it does not require a cast because it uses the generic method which uses the Class
as a type token.

import java.util.Map;
import java.util.WeakHashMap;

/**
* A simple cache using WeakHashMap of zero length arrays of a given class.
*
* @author schitale
*
*/
public class ZeroLength {
private static Map map = new WeakHashMap();

@SuppressWarnings("unchecked")
public static T[] array(Class c) {
T[] array = (T[]) map.get(c);
if (array == null) {
array = (T[]) java.lang.reflect.Array.newInstance(c, 0);
map.put(c, array);
}
return array;
}

public static void main(String[] args) {
System.out.println(array(String.class).getClass().getCanonicalName()
+ " of length " + array(String.class).length);
System.out.println(array(String[].class).getClass().getCanonicalName()
+ " of length " + array(String.class).length);
}
}
The output is:
java.lang.String[] of length 0
java.lang.String[][] of length 0

If you want to rely on the identity of the zero length array instance (e.g. == based comparison) then replace the WeakHashMap with HashMap. However, in that case you have to watch out for memory leaks through static fields of array component classes. You may want to add a method to remove the reference to the array from the HashMap.

Is there a better way to do this?

IMHO the java.lang.Class class should provide such factory method. This is along the lines of factory method:
public static final T  List T java.util.Collections.emptyList();


The implementation in java.lang.Class may look like:

private static T[] zeroLengthArray;

public static synchronized T[] emptyArray() {
if (zeroLengthArray == null) {
zeroLengthArray = (T[]) java.lang.reflect.Array.newInstance(this, 0);
}
return zeroLengthArray;
}

Thursday, October 23, 2008

Bundles, Extension Points, Extensions View for Eclipse 3.4

The BEPEB View is replacement for PDE's Plug-ins view. It allows you to explore:
  • Bundles
  • Extensions Points
  • Extensions

You can start with any one of these at the top level by using the toolbar settings. You can continue to expand the relationships between these objects to any level.

Several actions are supported in the context menu:

  • Open plugin.xml
  • Copy extension and extension element trees
  • Open Java Type specified by attributes which specify implementing Java classes.
For example, the Copy Extension action copied the following xml to the Clipboard:







Export a file containing the names and locations of the shared projects in the workspace.







I plan to make more enhancements to this view.

You can download it here.

DISCLAIMER:
This plug-in is experimental. So no guarantees. Use the plug-in at your own risk.

Tuesday, October 14, 2008

Reclaim Ctrl+C and Ctrl+V for familiar Copy and Paste in gnome-terminal

Most people work with graphical desktops. Most desktop (GUI) applications use the Ctrl+C and Ctrl+V for Copy and Paste actions respectively. One gets use to these really fast. However, when working with bash shell running inside a gnome-terminal those key bindings mean something different i.e. Ctrl+C sends the kill signal to the foreground process and Ctrl+V is used for quoted insert functionality (i.e. to enter control keys literally). This is the legacy of the command line oriented Unix terminals based on tty (stty - program that controls the settings of tty devices).

In this entry I describe how to make Ctrl+C and Ctrl+V do Copy and Paste in gnome-terminals. Here is how to do it:

Open a gnome-terminal window and type the following commands:

> stty intr ^K # free Ctrl+C for copy
> stty lnext ^- # free Ctrl+V for paste
> stty -g
> stty -g > ~/.stty # store the settings in home directory
Add the following to .bashrc
case $- in
*i*)
stty `cat ~/.stty` # reload the stored stty settings
bind -u quoted-insert # unbind the quoted-insert function of bash - free Ctrl+V for paste
esac
Now using the gconf-editor, edit the gnome-terminal's key bindings (@ /apps/gnome-terminal/keybindings key).

Close and reopen the terminal window. And now Ctrl+C will copy and Ctrl+V will paste.

Sunday, October 12, 2008

Launching the Open Type dialog

You can use the following code to launch the JDT's Open Type dialog to select a Java Type name and then open it in the Java editor programmatically:


OpenTypeSelectionDialog dialog = new OpenTypeSelectionDialog(
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
true,
PlatformUI.getWorkbench().getProgressService(),
null,
IJavaSearchConstants.TYPE);
dialog.setTitle(JavaUIMessages.OpenTypeAction_dialogTitle);
dialog.setMessage(JavaUIMessages.OpenTypeAction_dialogMessage);
dialog.setInitialPattern("java.lang.String");

int result= dialog.open();
if (result != IDialogConstants.OK_ID)
{
return;
}

Object[] types= dialog.getResult();
if (types != null && types.length > 0) {
IType type= null;
for (int i= 0; i < types.length; i++) {
type= (IType) types[i];
try {
JavaUI.openInEditor(type, true, true);
} catch (CoreException x) {
// Handle exception
}
}
}

Enhanced Plug-in Registry View

The Plug-in Registry View Enhancements Plug-in enhances the Plug-in Registry View.

The Plug-in Registry View has a mode (Show Extension Content only) to show:

  • extension-points
  • extensions
  • extension elements
  • extension attributes

This plug-in adds some additional actions on the Plug-in Registry View's tool bar. The following screen shot shows the example of the additional actions.

For attributes with values that look like Java Type name - the Open action opens the Open Type dialog:

This works well if you have added all the plug-in classes to your Java search using the tip - Extending the Java search scope.


The other supported action is:

  • Open plugin.xml

You can download the plug-in here.


BTW this plug-in makes use of the technique described in the entry - Add pulldown actions to Eclipse View's Toolbars.


DISCLAIMER: This plug-in is experimental. So no guarantees. Use the plug-in at your own risk.

Sunday, September 28, 2008

Template Tools Eclipse plug-in

UPDATE:
Template Tools Eclipse plug-in enhances the functionality of code templates:
  • ${clipboard} template variable - replaced by the contents of the clipboard.
  • ${prompt(input|file|directory|enumeration, value [, value]*|color|font)}
    • input - the user is prompted to enter a value
    • file - the user is prompted to select a file
    • directory - the user is prompted to select a directory
    • enumeration - the user is prompted to select a value from the list of values
    • color - the user is prompted to select a color using a color dialog. The color value can be formatted using java.util.Formatter strings. The parameters passed to the format are red, green or blue color component values. If no format is specified the value is formatted as the org.eclipse.swt.graphics.RGB.toString() value of the color.
    • font - the user is prompted to select a font using a FontDialog. The returned value is the org.eclipse.swt.graphics.FontData.toString() value returned by the font dialog.

This plug-in also supports extension-point promptProviders. Here is an example:

  <extension
point="TemplateTools.promptProviders">
<promptProvider
class="templatetools.InputPrompt"
type="input">
</promptProvider>
:
:
</extension>

Here is the implementation:


package templatetools;

import java.util.Formatter;
import java.util.List;

import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.ui.PlatformUI;

public class ColorPrompt implements IPrompt {

@SuppressWarnings("unchecked")
public String getValue(String name, List params) {
ColorDialog colorDilaog = new ColorDialog(PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getShell());
RGB color = colorDilaog.open();
if (color != null) {
if (params.size() > 0) {
Object format = params.get(0);
if (format instanceof String) {
StringBuffer formatBuffer = new StringBuffer();
new Formatter(formatBuffer).format((String) format,
color.red, color.green, color.blue);
return formatBuffer.toString();
}
} else {
return color.toString();
}
}
return null;
}

}

You can download the plug-in here.

DISCLAIMER: This plug-in is experimental. So no guarantees. Use the plug-in at your own risk.


Monday, September 15, 2008

Reorder Eclipse Plug-in : How does it work?

In the last entry I published the Reorder Eclipse plug-in. In this entry I will talk about how it works.

Basically, the Reorder plug-in uses the AST APIs to get parsed structure of the Java source code surrounding the caret in the Java editor.
  • It gets the ASTNode at caret position using NodeFinder API and starts traversing the parent ASTNodes until it find a Class Instance Creation, Method Invocation, Method Declaration or an Array initializer node.
  • Once found it gets the ASTNode's list of arguments, parameters or array initialization elements and stores the text of each node in a ordered list of items. While doing so, it also records the intervening white spaces as items.
  • It also records which item's extent surrounds the caret position. It records it as a current item.
  • Then, it swaps the current item with the following or preceding non-whitespace item in the list based on the action that was invoked - forward or backward swap.
  • Lastly it builds the string from the list of items and replaces the original text with the new string.
That's it.

Sunday, September 14, 2008

Reorder Eclipse Plug-in for Java Editor

The asymmetrical way in which the , (comma) is used to separate the items in parameter and arguments lists always causes problem when one wants to reorder that list in Java editor. Is that why Java allows trailing commas in array initializer? ;) may be. The Reorder plug-in supports single click swapping of a parameter, argument or array initializer expressions with previous or next item in the list. Each item of the sequence can be a simple literal, an identifier or a more complex function call expression. The comma delimiter is correctly handled.

This plug-in adds two toolbar buttons to the Java editor:

  • Swap backward
  • Swap forward


Usage

With the caret at | in:

void method(int iii, String |sss, boolean bbb){}
pressing the Swap forward button yields:
void method(int iii, boolean bbb, String |sss){}
or pressing Swap backward button with the original source yields:
void method(String |sss, int iii, boolean bbb){}


You can download the plug-in from here.


TODO

  • Key bindings for the actions
  • Generalization of the concept to other language editors

DISCLAIMER: This plug-in is experimental. So no guarantees. Use the plug-in at your own risk.

Saturday, September 13, 2008

Add pulldown actions to Eclipse View's Toolbars

The actions added to the org.eclipse.ui.actionSets extension point (which allows contribution to the Wokbench Window's toolbars) allow the pulldown style. However the actions added to the org.eclipse.ui.viewActions extension point do not allow the pulldown style. IMHO this is a annoying limitation. It may be that the original reason for this limitation was to avoid confusion with the drop down menu in the View toolbars. However the visual of a pulldown action down action is different enough that it is not confusing. Besides the pull down actions are used in View toolbars of many Eclipse provided Views e.g. Open Console action on the as Console view's toolbar. So how are such actions created? Well such actions are programatically created during the View's createPartControl() invocation. However that is not always the case. You may want to contribute a pulldown action to a View created elsewhere. In this entry I show you how to do exactly that programatically.

The basic idea behind this is to watch for opening of the view that you are interested in and programatically add the pulldown style action when the view is opened. Just put the following code in your plug-in's Activator. One thing to keep in mind is that your plug-in may get activated some time after the View that you are contributing a pull down action to - was already created. To handle that we process all the exiting windows that are already present when our code activates. We monitor the opening of the views in the Workbench windows by adding the IPartListener to the Window's PartService. What happens if the user creates more Workbench windows and then openes the View of interest in that Workbench window. Well, we monitor creation of new Workbench windows by adding the IWindowListener to the Workbench. We keep track of the fact that the action was added to the View's toolbar in a WeakHashMap (keyed by the IViewPart) so that we add the action only once. This is because the addActions() is called from multiple places in the following code. One more thing...the action you add must use SWT.AS_DROP_DOWN_MENU style and also implement the IMenuCreator intreface. That's it. Here is the code:
private static WeakHashMap actionsAddedToView = new WeakHashMap();
private static void addActions(IViewPart viewPart)
{
Boolean added = actionsAddedToView.get(viewPart);
if (added == null) {
// The actions were not added yet
final IToolBarManager toolBarManager = viewPart.getViewSite().getActionBars().getToolBarManager();

// SomePulldownAction extends Action implements IMenuCreator
// public SomePulldownAction() {
// super("Some Action...", IAction.AS_DROP_DOWN_MENU);
// }
// Also implement the getMenu() action.
// public Menu getMenu(Control parent) {
// create menu
// add menu items
// return the menu
// }
SomePulldownAction someDownloadAction = new SomePulldownAction();
someDownloadAction.init(viewPart);
toolBarManager.insertAfter("id-of-an-exiting-action-on-views-toolbar", someDownloadAction); //$NON-NLS-1$

// Add more actions
// ...
// ...
// ...

toolBarManager.update(true);
actionsAddedToView.put(viewPart, Boolean.TRUE);
}
}

// Listner for monitoring the view opening
private static final IPartListener partListener = new PartListenerAdapter()
{
@Override
public void partOpened(IWorkbenchPart part)
{
if (part instanceof IViewPart)
{
IViewPart viewPart = (IViewPart) part;
if ("-id-of-the-view-to-which-you-want-to-add-the-pulldown-action".equals(viewPart.getSite().getId()))
{
addActions(viewPart);
}
}
}

@Override
public void partClosed(IWorkbenchPart part)
{
if (part instanceof IViewPart)
{
IViewPart viewPart = (IViewPart) part;
if ("-id-of-the-view-to-which-you-want-to-add-the-pulldown-action".equals(viewPart.getSite().getId()))
{
// forget the view's actions added state
actionsAddedToView.remove(viewPart);
}
}
}
};

private static void processWindow(IWorkbenchWindow window)
{
IWorkbenchPage[] pages = window.getPages();
for (IWorkbenchPage workbenchPage : pages)
{
IViewPart viewPart = workbenchPage.findView("-id-of-the-view-to-which-you-want-to-add-the-pulldown-action");
if viewPart != null && viewPart.getSite() != null)
{
addActions(viewPart);
break;
}
}

// Monitor furture view creation in case the view
// is closed and reopened
window.getPartService().addPartListener(partListener);
}

static {
// Add pulldown action to the view that may be already present in
// exiting Workbench windows.
IWorkbenchWindow[] workbenchWindows = PlatformUI.getWorkbench().getWorkbenchWindows();
for (IWorkbenchWindow workbenchWindow : workbenchWindows)
{
processWindow(workbenchWindow);
}

// Monitor future Workbench windows
PlatformUI.getWorkbench().addWindowListener(new IWindowListener()
{
public void windowActivated(IWorkbenchWindow window) {}
public void windowClosed(IWorkbenchWindow window) {}
public void windowDeactivated(IWorkbenchWindow window) {}
public void windowOpened(IWorkbenchWindow window)
{
processWindow(window);
}
});
}

Tuesday, September 09, 2008

An enhanced ListEditor implementation

As discussed in this article on Eclipse.org, the Eclipse FieldEditors make it easy to implement the preferences pages. The ListEditor is one of the many imlementations provided by Eclipse which allows editing of list like values. However it has a serious limitation. It only allows addition, deletion and reordering of the values. It does not allow editing of the values already in the list. The following subclass of ListEditor overcomes that limitation by providing the functionality of editing any one value in the list of values. To use it you have to subclass and implement the following additional abstract method:

/**
* The subclasses must override this to return the modified entry.
*
* @param original the new entry
* @return the modified entry. Return null to prevent modification.
*/
protected abstract String getModifiedEntry(String original);

One possible implementation could look something like this:

@Override
protected String getModifiedEntry(String original) {
InputDialog entryDialog = new InputDialog(
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
"Edit entry", "Edit entry:", original, null);
if (entryDialog.open() == InputDialog.OK) {
return entryDialog.getValue();
}
return null;
}

In fact, I make use of this in my Path Tools Eclipse Plug-in to edit the custom commands for folders and files. Here is the screenshot:


Here is the full code:

package somepackage;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.ListEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.List;

/**
* This class extends {@link ListEditor} to enable editing of entries.
*
* @author Sandip V. Chitale
*
*/
public abstract class EntryModifiableListEditor extends ListEditor {

public EntryModifiableListEditor(String name, String labelText, Composite parent) {
super(name, labelText, parent);
}

/**
* The subclasses must override this to return the modified entry.
*
* @param original the new entry
* @return the modified entry. Return null to prevent modification.
*/
protected abstract String getModifiedEntry(String original);

private Button editButton;
private List commandListControl;

@Override
public Composite getButtonBoxControl(Composite parent) {
Composite buttonBoxControl = super.getButtonBoxControl(parent);
if (editButton == null) {
editButton = createPushButton(buttonBoxControl, "Edit..."); // TODO I18N
editButton.setEnabled(false);
editButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (commandListControl.getSelectionCount() == 1) {
String modified = getModifiedEntry(commandListControl.getSelection()[0]);
if (modified != null) {
int selectedIndex = commandListControl.getSelectionIndex();
commandListControl.remove(selectedIndex);
commandListControl.add(modified, selectedIndex);
}
}
}
});
buttonBoxControl.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
editButton = null;
}
});
}
return buttonBoxControl;
}

/**
* Helper method to create a push button.
*
* @param parent the parent control
* @param key the resource name used to supply the button's label text
* @return Button
*/
private Button createPushButton(Composite parent, String key) {
Button button = new Button(parent, SWT.PUSH);
button.setText(key);
button.setFont(parent.getFont());
GridData data = new GridData(GridData.FILL_HORIZONTAL);
int widthHint = convertHorizontalDLUsToPixels(button,
IDialogConstants.BUTTON_WIDTH);
data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
SWT.DEFAULT, true).x);
button.setLayoutData(data);
return button;
}

@Override
public List getListControl(Composite parent) {
List listControl = super.getListControl(parent);
if (commandListControl == null) {
commandListControl = listControl;
commandListControl.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
editButton.setEnabled(commandListControl.getSelectionCount() == 1);
}
});
}
return listControl;
}

}

Sunday, September 07, 2008

Perspectives and Views Toolbar Plugin for Eclipse

In Eclipse IDE, I find it very inconvenient to go to the the Window:Open Perspective or Window:Show View submenu, and then select the one I want in dialog that is shown. I was inconvenienced enough that I wrote a simple Eclipse Plug-in called - Perspectives and Views Toolbar. The basic idea is that it adds two drop down menus to the toolbar. Using the drop down you can directly select the Perspective or the View that you want to show.












Get the Eclipse 3.4 compatible Perspectives and Views Toolbar Plug-in here.

DISCLAIMER: This plug-in is experimental. So no guarantees. Use the plug-in at your own risk.

Sunday, August 31, 2008

Eclipse template variables ${selection} and ${clipboard}

I just filed two enhancement requests in bugzilla at Eclipse.org:

245788 Add a template variable ${selection} and allow Surround With action to deal consider it.
245790 Add a template variable ${clipboard}

The jist of the enhancement is that two new template variables should be added:

${selection} - this is replaced by what ever was the selection in the editor at the time of template insertion was invoked. Note that this requires a template invocation machanism that does not destroy the selection in text editor.
${clipboard} - this is replaced by the text content of the the clipboard.

Here is a use case:

template name: hyperlink
template pattern:

<a href="${clipboard}">${selection}</a>${cursor}

and with text http://www.google.com/ in the clipboard and the text

Google|

selected in the Eclipse editor.

Invoking the hyperlink template using the Surround with... action yields:

<a herf="http://www.google.com">Google</a>

Granted this would have been easy to type but imagine a complex URL copied into the clipboard from the browser address bar in place of "http://www.google.com/".

Please vote on the enhancement if you like this idea.

Friday, August 29, 2008

Self maintaining package level logger access class

Many times I have seen that programmers declare a static field which hold an instance of a Logger. I find this pattern repeated in many classes in the same package. Below is an example of a simple package level logger accessor class. It has an interesting property being a self maintaining code in that you can drop this code in any package and fix the package name by hand or even better let the IDE such as Eclipse provide the quick fix to correct the package for you.
package somepackage;

import java.util.logging.Logger;

/**
* Self maintaining package level logger access
*
*/
final class Log {
private static Logger logger;

// not thread safe
static Logger getLogger() {
if (logger == null) {
logger =
Logger.getLogger(Log.class.getPackage().getName());
}
return logger;
}

private Log(){}
}

Thoughts?

Monday, August 25, 2008

INFO: Eclipse View and Perspective IDs

Views
Ant org.eclipse.ant.ui.views.AntView
Bookmarks org.eclipse.ui.views.BookmarkView
Breakpoints org.eclipse.debug.ui.BreakpointView
CVS Annotate org.eclipse.team.ccvs.ui.AnnotateView
CVS Editors org.eclipse.team.ccvs.ui.EditorsView
CVS Repositories org.eclipse.team.ccvs.ui.RepositoriesView
Call Hierarchy org.eclipse.jdt.callhierarchy.view
Cheat Sheets org.eclipse.ui.cheatsheets.views.CheatSheetView
Classic Search org.eclipse.search.SearchResultView
Console org.eclipse.ui.console.ConsoleView
Debug org.eclipse.debug.ui.DebugView
Declaration org.eclipse.jdt.ui.SourceView
Display org.eclipse.jdt.debug.ui.DisplayView
Error Log org.eclipse.pde.runtime.LogView
Expressions org.eclipse.debug.ui.ExpressionView
Help org.eclipse.help.ui.HelpView
Hierarchy org.eclipse.jdt.ui.TypeHierarchy
History org.eclipse.team.ui.GenericHistoryView
Internal Web Browser org.eclipse.ui.browser.view
JUnit org.eclipse.jdt.junit.ResultView
Javadoc org.eclipse.jdt.ui.JavadocView
Members org.eclipse.jdt.ui.MembersView
Memory org.eclipse.debug.ui.MemoryView
Navigator org.eclipse.ui.views.ResourceNavigator
Outline org.eclipse.ui.views.ContentOutline
Package Explorer org.eclipse.jdt.ui.PackageExplorer
Packages org.eclipse.jdt.ui.PackagesView
Plug-in Dependencies org.eclipse.pde.ui.DependenciesView
Plug-in Registry org.eclipse.pde.runtime.RegistryBrowser
Plug-ins org.eclipse.pde.ui.PluginsView
Problems org.eclipse.ui.views.ProblemView
Progress org.eclipse.ui.views.ProgressView
Project Explorer org.eclipse.ui.navigator.ProjectExplorer
Projects org.eclipse.jdt.ui.ProjectsView
Properties org.eclipse.ui.views.PropertySheet
Registers org.eclipse.debug.ui.RegisterView
SVN Annotate org.tigris.subversion.subclipse.ui.annotations.AnnotateView
SVN Properties org.tigris.subversion.subclipse.ui.svnproperties.SvnPropertiesView
SVN Repositories org.tigris.subversion.subclipse.ui.repository.RepositoriesView
Search org.eclipse.search.ui.views.SearchView
Synchronize org.eclipse.team.sync.views.SynchronizeView
Tasks org.eclipse.ui.views.TaskList
Types org.eclipse.jdt.ui.TypesView
Variables org.eclipse.debug.ui.VariableView
Welcome org.eclipse.ui.internal.introview
Perspectives
CVS Repository Exploring org.eclipse.team.cvs.ui.cvsPerspective
Debug org.eclipse.debug.ui.DebugPerspective
Java org.eclipse.jdt.ui.JavaPerspective
Java Browsing org.eclipse.jdt.ui.JavaBrowsingPerspective
Java Type Hierarchy org.eclipse.jdt.ui.JavaHierarchyPerspective
Plug-in Development org.eclipse.pde.ui.PDEPerspective
Resource org.eclipse.ui.resourcePerspective
SVN Repository Exploring org.tigris.subversion.subclipse.ui.svnPerspective
Team Synchronizing org.eclipse.team.ui.TeamSynchronizingPerspective

Monday, August 18, 2008

Sunday, August 17, 2008

Friday, August 15, 2008