FAQ1 FAQ: Can I dynamically change the contents of the System Filesystem at runtime? @ServiceProvider(service=FileSystem.class) public class DynamicLayerContent extends MultiFileSystem { private static DynamicLayerContent INSTANCE; public DynamicLayerContent() { // will be created on startup, exactly once INSTANCE = this; setPropagateMasks(true); // permit *_hidden masks to be used } static boolean hasContent() { return INSTANCE.getDelegates().length > 0; } static void enable() { if (!hasContent()) { try { INSTANCE.setDelegates(new XMLFileSystem( DynamicLayerContent.class.getResource( "dynamicContent.xml"))); } catch (SAXException ex) { Exceptions.printStackTrace(ex); } } } static void disable() { INSTANCE.setDelegates(); } } FAQ2 FAQ: How do I create an Action that is automatically enabled and disabled depending on the selection? public class FooAction extends AbstractAction implements LookupListener, ContextAwareAction { private Lookup context; Lookup.Result lkpInfo; public FooAction() { this(Utilities.actionsGlobalContext()); } private FooAction(Lookup context) { putValue(Action.NAME, NbBundle.getMessage(FooAction.class, "LBL_Action")); this.context = context; } void init() { assert SwingUtilities.isEventDispatchThread() : "this shall be called just from AWT thread"; if (lkpInfo != null) { return; } //The thing we want to listen for the presence or absence of //on the global selection lkpInfo = context.lookupResult(Whatever.class); lkpInfo.addLookupListener(this); resultChanged(null); } public boolean isEnabled() { init(); return super.isEnabled(); } public void actionPerformed(ActionEvent e) { init(); for (Whatever instance : lkpInfo.allInstances()) { // use it somehow... } } public void resultChanged(LookupEvent ev) { setEnabled(!lkpInfo.allInstances().isEmpty()); } public Action createContextAwareInstance(Lookup context) { return new FooAction(context); } } FAQ3 FAQ: How do I add an action to a project node's popup menu of my own project type? public final class AddActionActions implements ActionProvider { private final AddActionProject project; //suppose this is your project public AddActionActions(AddActionProject project) { this.project = project; } public String[] getSupportedActions() { return new String[] { ActionProvider.COMMAND_COPY }; } public boolean isActionEnabled(String command, Lookup context) { if (command.equals(ActionProvider.COMMAND_COPY)) { return true; } else { throw new IllegalArgumentException(command); } } public void invokeAction(String command, Lookup context) { if (command.equalsIgnoreCase(ActionProvider.COMMAND_COPY)){ DefaultProjectOperations.performDefaultCopyOperation(project); } } } FAQ4 FAQ: How can I add actions to all folder nodes? @ActionID( category = "Build", id = "com.foo.bar.OnAnyFolderAction") @ActionRegistration( displayName = "#CTL_OnAnyFolderAction") @ActionReferences({ @ActionReference(path = "Loaders/folder/any/Actions", position = 0) }) @Messages("CTL_OnAnyFolderAction=ActionOnAnyFolder") public final class OnAnyFolderAction implements ActionListener { private final DataFolder context; public OnAnyFolderAction(DataFolder context) { this.context = context; } @Override public void actionPerformed(ActionEvent ev) { JOptionPane.showMessageDialog(null, context.toString()); } } FAQ5 FAQ: How can I to add actions to the Java package node? @ActionID( category = "Build", id = "com.foo.bar.OnJavaPackageAction") @ActionRegistration( displayName = "#CTL_OnJavaPackageAction") @ActionReferences({ @ActionReference(path = "Projects/package/Actions", position = 0) }) @Messages("CTL_OnJavaPackageAction=OnJavaPackageAction") public final class OnJavaPackageAction implements ActionListener { private final DataFolder context; public OnJavaPackageAction(DataFolder context) { this.context = context; } @Override public void actionPerformed(ActionEvent ev) { JOptionPane.showMessageDialog(null, context.toString()); } } FAQ6 FAQ: How can I add a JSeparator to the main toolbar? package com.example.util.widgets; public class VerticalSeparator extends JSeparator { public VerticalSeparator() { super(JSeparator.VERTICAL); } @Override public Dimension getMaximumSize() { return new Dimension(getPreferredSize().width, super.getMaximumSize().height); } @Override public Dimension getSize() { return new Dimension(getPreferredSize().width, super.getSize().height); } } FAQ7 FAQ: How do I Add Content to the Global Context? @ActionID(...) @ActionRegistration(...) @ActionReference(...) public final class CloseProjectAction implements ActionListener { private final Project project; public CloseProjectAction(Project context) { this.project = context; } @Override public void actionPerformed(ActionEvent e) { OpenProjects.getDefault().close(new Project[] { project }); } } FAQ8 FAQ: What if multiple objects of the same type should be available? class ObjectInterestedInFooObjects implements LookupListener { final Lookup.Result result; //result object is weakly referenced inside Lookup ObjectInterestedInFooObjects() { result = someLookup.lookupResult(Foo.class); result.addLookupListener(this); resultChanged(null); } public void resultChanged(LookupEvent evt) { Collection c = result.allInstances(); // do something with the result } } FAQ9 FAQ: How can I add support for Lookups on nodes representing my file type? public SomeObject implements Lookup.Provider { private InstanceContent content = new InstanceContent(); private final AbstractLookup lkp = new AbstractLookup(content); public someMethod() { ic.set (someCollection...); } public Lookup getLookup() { return lkp; } } FAQ10 FAQ: How can I be notified when a file is modified and saved?? DataObject.Registry registries = DataObject.getRegistry(); registries.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { System.out.println("ChangedListener: o = " + e.getSource().getClass()); System.out.println("ChangedListener: o.source = " + e.getSource()); } }); DataObject[] objects = registries.getModified(); for (int i = 0; i < objects.length; i++) { DataObject dataObj = objects[I]; System.out.println("data object name = " + dataObj.getName()); System.out.println("data object pimary file name = " + dataObj.getPrimaryFile().getName()); Set fss = dataObj.files(); Iterator iter = fss.iterator(); while (iter.hasNext()) { FileObject fo = (FileObject) iter.next(); System.out.println("\tset file object: " + fo.getName()); } } FAQ11 FAQ: How can I open a file in the editor in read-only mode? JFileChooser jfc = new JFileChooser(); if (jfc.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) { return; } File f = jfc.getSelectedFile(); FileObject fo = FileUtil.toFileObject(f); try { new ROEditor(fo).open(); } catch (DataObjectNotFoundException e) { e.printStackTrace(); } FAQ12 FAQ: How can I get a list of open editor windows? Node[] arr = TopComponent.getRegistry().getCurrentNodes(); for (int i = 0; i < arr.length; i++) { EditorCookie ec = (EditorCookie) arr[i].getCookie(EditorCookie.class); if (ec != null) { JEditorPane[] panes = ec.getOpenedPanes(); if (panes != null) { // USE panes } } } FAQ13 FAQ: How can I get the position of the caret in the currently selected editor window? Node[] n = TopComponent.getRegistry().getActivatedNodes(); if (n.length == 1) { EditorCookie ec = (EditorCookie) n[0].getCookie(EditorCookie.class); if (ec != null) { JEditorPane[] panes = ec.getOpenedPanes(); if (panes.length > 0) { int cursor = panes[0].getCaret().getDot(); String selection = panes[0].getSelectedText(); // USE selection } } } FAQ14 FAQ: How can I open a particular file at a particular line number and column? File f = ...; int lineNumber = ...; FileObject fobj = FileUtil.toFileObject(f); DataObject dobj = null; try { dobj = DataObject.find(fobj); } catch (DataObjectNotFoundException ex) { ex.printStackTrace(); } if (dobj != null) LineCookie lc = (LineCookie) dobj .getCookie(LineCookie.class); if (lc == null) {/* cannot do it */ return;} Line l = lc.getLineSet().getOriginal(lineNumber); l.show(Line.SHOW_GOTO); } FAQ15 FAQ: How can I track what file the user is currently editing? import org.netbeans.api.editor.EditorRegistry; PropertyChangeListener l = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { JTextComponent jtc = EditorRegistry.lastFocusedComponent(); if (jtc != null) { Document d = jtc.getDocument(); // use the document } } }; EditorRegistry.addPropertyChangeListener(l); FAQ16 FAQ: I want to make some programmatic changes to the edited file. How can I do it so one Undo undoes it all? ... import org.openide.text.NbDocument; import org.netbeans.api.editor.EditorRegistry; ... public final class MyAction implements ActionListener { private class RunnableAction implements Runnable { private JTextComponent ed; private Document doc; private RunnableAction( JTextComponent ed, Document doc ) { this.ed = ed; this.doc = doc; } @Override public void run() { ... } } public void actionPerformed( ActionEvent e ) { JTextComponent ed = EditorRegistry.lastFocusedComponent(); StyledDocument doc = ( StyledDocument ) ed.getDocument(); // Perform all of the changes atomically so that they can be undone with one undo. NbDocument.runAtomic( doc, new RunnableAction( ed, doc ) ); } } FAQ17 FAQ: How to add code completion to any JEditorPane JEditorPane editorPane = new JEditorPane(); // This will find the Java editor kit and associate it with // our editor pane. But that does not give us code completion // just yet because we have no Java context (i.e. no class path, etc.). // However, this does give us syntax coloring. EditorKit kit = CloneableEditorSupport.getEditorKit("text/x-java"); editorPane.setEditorKit(kit); // You can specify any ".java" file. // If the file does not exist, it will be created. // The contents of the file does not matter. // The extension must be ".java", however. String newSourcePath = "tmp.java"; File tmpFile = new File(newSourcePath); FileObject fob = FileUtil.createData(tmpFile); DataObject dob = DataObject.find(fob); editorPane.getDocument().putProperty( Document.StreamDescriptionProperty, dob); // This sets up a default class path for us so that // we can find all the JDK classes via code completion. DialogBinding.bindComponentToFile(fob, 0, 0, editorPane); // Last but not least, we need to fill the editor pane with // some initial dummy code - as it seems somehow required to // kick-start code completion. // A simple dummy package declaration will do. editorPane.setText("package dummy;"); FAQ18 FAQ: How can I open a file in the IDE programatically? FileObject fo = FileUtil.toFileObject(new File("test.js").getAbsoluteFile()); DataObject newDo = DataObject.find(fo); final Node node = newDo.getNodeDelegate(); Action a = node.getPreferredAction(); if (a instanceof ContextAwareAction) { a = ((ContextAwareAction) a).createContextAwareInstance(node.getLookup()); } if (a != null) { a.actionPerformed(new ActionEvent(node, ActionEvent.ACTION_PERFORMED, "")); // NOI18N FAQ19 FAQ: How can code in one module be notified when other modules are loaded or unloaded? import some.Interface; // ... private static final Lookup.Result services = Lookup.getDefault().lookupResult(Interface.class); static { services.addLookupListener(new LookupListener() { public void resultChanged(LookupEvent ev) { // some module was loaded or unloaded! } }); } // ... for (Interface service : services.allInstances()) { // use a currently available service } FAQ20 FAQ: How do I create a TopComponent to show an explorer view? public class MyView extends TopComponent implements ExplorerManager.Provider { private final ExplorerManager manager = new ExplorerManager(); private final JComponent view = new BeanTreeView(); public MyView() { setLayout (new BorderLayout()); add(view, BorderLayout.CENTER); manager.setRootContext(someNode); // Probably boilerplate (depends on what you are doing): ActionMap map = getActionMap(); map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager)); map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager)); map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager)); // This one is sometimes changed to say "false": map.put("delete", ExplorerUtils.actionDelete(manager, true)); // Boilerplate: associateLookup(ExplorerUtils.createLookup(manager, map)); } // This is optional: public boolean requestFocusInWindow() { super.requestFocusInWindow(); // You will need to pick a view to focus: return view.requestFocusInWindow(); } // The rest is boilerplate. public ExplorerManager getExplorerManager() { return manager; } protected void componentActivated() { ExplorerUtils.activateActions(manager, true); } protected void componentDeactivated() { ExplorerUtils.activateActions(manager, false); } } FAQ21 FAQ: FAQ How are resources created? IWorkspace workspace = ResourcesPlugin.getWorkspace(); IWorkspaceRoot root = workspace.getRoot(); IProject project = root.getProject("MyProject"); IFolder folder = project.getFolder("Folder1"); IFile file = folder.getFile("hello.txt"); //at this point, no resources have been created if (!project.exists()) project.create(null); if (!project.isOpen()) project.open(null); if (!folder.exists()) folder.create(IResource.NONE, true, null); if (!file.exists()) { byte[] bytes = "File contents".getBytes(); InputStream source = new ByteArrayInputStream(bytes); file.create(source, IResource.NONE, null); } FAQ22 FAQ: FAQ Why do the names of some interfaces end with the digit 2? public void runWithEvent(Event event) { ... if (delegate instanceof IActionDelegate2) { ((IActionDelegate2)delegate).runWithEvent(this, event); return; } // Keep for backward compatibility with R2.0 if (delegate instanceof IActionDelegateWithEvent) { ((IActionDelegateWithEvent) delegate). runWithEvent(this, event); return; } ... } FAQ23 FAQ: FAQ How do I create fixed views and perspectives? class RecipePerspective implements IPerspectiveFactory { public void createInitialLayout(IPageLayout page) { page.setEditorAreaVisible(true); page.setFixed(true); page.addStandaloneView( RecipePlugin.VIEW_CATEGORIES, false, IPageLayout.TOP, 0.2f, IPageLayout.ID_EDITOR_AREA); IViewLayout view = page.getViewLayout( RecipePlugin.VIEW_CATEGORIES); view.setCloseable(false); view.setMoveable(false); } } FAQ24 FAQ: FAQ How do I make menus with dynamic contents? IMenuListener listener = new IMenuListener() { public void menuAboutToShow(IMenuManager m) { if (daytime) { m.add(workAction); m.add(playAction); } else { m.add(sleepAction); } } }; menu.addMenuListener(listener); FAQ25 FAQ: FAQ How do I customize the menus in an RCP application? public void fillActionBars(IWorkbenchWindow window, IActionBarConfigurer configurer, int flags) { if ((flags & FILL_MENU_BAR) == 0) return; IMenuManager mainMenu = configurer.getMenuManager(); MenuManager windowMenu = new MenuManager("&Window", IWorkbenchActionConstants.M_WINDOW); mainMenu.add(windowMenu); windowMenu.add(ActionFactory.MAXIMIZE.create(window)); MenuManager helpMenu = new MenuManager("&Help", IWorkbenchActionConstants.M_HELP); mainMenu.add(helpMenu); helpMenu.add(new AboutAction()); } FAQ26 FAQ: FAQ How and when do I save the workspace? final MultiStatus status = new MultiStatus(...); IRunnableWithProgress runnable = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { try { IWorkspace ws = ResourcesPlugin.getWorkspace(); status.merge(ws.save(true, monitor)); } catch (CoreException e) { status.merge(e.getStatus()); } } }; new ProgressMonitorDialog(null).run(false, false, runnable); if (!status.isOK()) { ErrorDialog.openError(...); } FAQ27 FAQ: FAQ How do I implement Quick Fixes for my own language? public class QuickFixer implements IMarkerResolutionGenerator { public IMarkerResolution[] getResolutions(IMarker mk) { try { Object problem = mk.getAttribute("WhatsUp"); return new IMarkerResolution[] { new QuickFix("Fix #1 for "+problem), new QuickFix("Fix #2 for "+problem), }; } catch (CoreException e) { return new IMarkerResolution[0]; } } } FAQ28 FAQ: FAQ How do I create a Java project? String name = "MyProject"; IWorkspace workspace = ResourcesPlugin.getWorkspace(); IWorkspaceRoot root= workspace.getRoot(); IProject project= root.getProject(name); project.create(null); project.open(null); IProjectDescription desc = project.getDescription(); desc.setNatureIds(new String[] { JavaCore.NATURE_ID}); project.setDescription(desc); IJavaProject javaProj = JavaCore.create(project); IFolder binDir = project.getFolder("bin"); IPath binPath = binDir.getFullPath(); javaProj.setOutputLocation(binPath, null); String path = "c:\\jre\\lib\\rt.jar"; IClasspathEntry cpe= JavaCore.newLibraryEntry( path, null, null); javaProj.setRawClasspath(new IClasspathEntry[] {cpe}); FAQ29 FAQ: FAQ How do I find all the plug-ins that contribute to my extension point? IExtensionRegistry reg = Platform.getExtensionRegistry(); IExtensionPoint ep = reg.getExtensionPoint(extensionID); IExtension[] extensions = ep.getExtensions(); ArrayList contributors = new ArrayList(); for (int i = 0; i < extensions.length; i++) { IExtension ext = extensions[i]; IConfigurationElement[] ce = ext.getConfigurationElements(); for (int j = 0; j < ce.length; j++) { Object obj = ce[j].createExecutableExtension("class"); contributors.add(obj); } } FAQ30 FAQ: FAQ What is a label decorator? ImageDescriptor readOnlyOverlay = ...; public void decorate(Object element, IDecoration decoration) { if (!(element instanceof java.io.File)) return; boolean readOnly = !((java.io.File) element).canWrite(); if (!readOnly) return; decoration.addOverlay(readOnlyOverlay); decoration.addSuffix(" (read only)"); } FAQ31 FAQ: FAQ How do I run a lengthy process in a wizard? getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { int sum = n1 + n2; monitor.beginTask("Computing sum: ", sum); for (int i = 0; i < sum; i++) { monitor.subTask(Integer.toString(i)); //sleep to simulate long running operation Thread.sleep(100); monitor.worked(1); } monitor.done(); } }); FAQ32 FAQ: FAQ Can I create an application that doesn't have views or editors? public class JFaceApp implements IPlatformRunnable { public Object run(Object args) throws Exception { Display display = new Display(); JFaceAppWindow window = new JFaceAppWindow(); window.open(); Shell shell = window.getShell(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } return EXIT_OK; } } FAQ33 FAQ: FAQ How do I use the text document model? String searchAndReplace(String input, String search, String replace) throws BadLocationException { Document doc = new Document(input); int offset = 0; while (offset < doc.getLength()) { offset = doc.search(offset, search, true, true, true); if (offset < 0) break; doc.replace(offset, search.length(), replace); offset += replace.length(); } return doc.get(); } FAQ34 FAQ: FAQ How do I change the selection on a double-click in my editor? public void doubleClicked(ITextViewer part) { final int offset = part.getSelectedRange().x; int length = 0; IDocument doc = part.getDocument(); while (true) { char c = doc.getChar(offset + length); if (c=='a'||c=='e'||c=='i'||c=='o'||c=='u') break; if (offset + ++length >= doc.getLength()) return; } part.setSelectedRange(offset, length); } FAQ35 FAQ: FAQ How do I access the active project? 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; } FAQ36 FAQ: FAQ Why do I get an invalid thread access exception? new Thread(new Runnable() { public void run() { while (true) { try { Thread.sleep(1000); } catch (Exception e) { } Display.getDefault().asyncExec(new Runnable() { public void run() { ... do any work that updates the screen ... } }); } } }).start(); FAQ37 FAQ: FAQ How do I specify the order of pages in a wizard? public class AddingWizard extends Wizard { private AddingWizardPage page1, page2; ... public void addPages() { page1 = new AddingWizardPage("Page1", "Please enter the first number"); addPage(page1); page2 = new AddingWizardPage("Page2", "Enter another number"); addPage(page2); } } FAQ38 FAQ: FAQ How do I create an image registry for my plug-in? public class ExamplesPlugin extends AbstractUIPlugin { public static final String PLUGIN_ID = "org.eclipse.faq.examples"; public static final String IMAGE_ID = "sample.image"; ... protected void initializeImageRegistry(ImageRegistry registry) { Bundle bundle = Platform.getBundle(PLUGIN_ID); IPath path = new Path("icons/sample.gif"); URL url = FileLocator.find(bundle, path, null); ImageDescriptor desc = ImageDescriptor.createFromURL(url); registry.put(IMAGE_ID, desc); } } FAQ39 FAQ: FAQ How do I get started with creating a custom text editor? public class HTMLEditor extends AbstractTextEditor { public HTMLEditor() { //install the source configuration setSourceViewerConfiguration(new HTMLConfiguration()); //install the document provider setDocumentProvider(new HTMLDocumentProvider()); } protected void createActions() { super.createActions(); //... add other editor actions here } } FAQ40 FAQ: FAQ How do I provide syntax coloring in an editor? ITokenScanner scanner = new RuleBasedScanner(); IToken string = createToken(colorString); IRule[] rules = new IRule[3]; // Add rule for double quotes rules[0] = new SingleLineRule("\"", "\"", string, '\\'); // Add a rule for single quotes rules[1] = new SingleLineRule("'", "'", string, '\\'); // Add generic whitespace rule. rules[2] = new WhitespaceRule(whitespaceDetector); scanner.setRules(rules); scanner.setDefaultReturnToken(createToken(colorTag)); FAQ41 FAQ: FAQ How do I write to the console from a plug-in? 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; } FAQ42 FAQ: FAQ What is a JDOM? String oldContents = ...;//original file contents IMethod method = ...;//the method to change String returnType = ...;//the new return type ICompilationUnit cu = method.getCompilationUnit(); String unitName = cu.getElementName(); String typeName = method.getParent().getElementName(); String mName = method.getElementName(); DOMFactory fac = new DOMFactory(); IDOMCompilationUnit unit = fac.createCompilationUnit(oldContents, unitName); IDOMType type = (IDOMType) unit.getChild(typeName); IDOMMethod domMethod = (IDOMMethod) type.getChild(mName); domMethod.setReturnType(returnType); FAQ43 FAQ: FAQ How do I use image and font registries? static final String IMAGE_ID = "my.image"; ... //declaring the image ImageRegistry registry = new ImageRegistry(); ImageDescriptor desc = ImageDescriptor.createFromURL(...); registry.put(IMAGE_ID, desc); ... //using the image Button button = new Button(...); Image image = registry.get(IMAGE_ID); button.setImage(image); FAQ44 FAQ: FAQ How do I find out what view or editor is selected? IWorkbenchPage page = ...; //the active part IWorkbenchPart active = page.getActivePart(); //adding a listener IPartListener2 pl = new IPartListener2() { public void partActivated(IWorkbenchPartReference ref) System.out.println("Active: "+ref.getTitle()); } ... other listener methods ... }; page.addPartListener(pl); FAQ45 FAQ: FAQ How do I hook my editor to the Back and Forward buttons? public class MarkLocationAction extends Action { private IEditorPart editor; public MarkLocationAction(IEditorPart editor) { super("Mark Location in History", null); this.editor = editor; } public void run() { IWorkbenchPage page = editor.getSite().getPage(); page.getNavigationHistory().markLocation(editor); } } FAQ46 FAQ: FAQ How do I add Content Assist to my editor? public IContentAssistant getContentAssistant(ISourceViewer sv) { ContentAssistant ca = new ContentAssistant(); IContentAssistProcessor pr = new TagCompletionProcessor(); ca.setContentAssistProcessor(pr, HTML_TAG); ca.setContentAssistProcessor(pr, IDocument.DEFAULT_CONTENT_TYPE); ca.setInformationControlCreator(getInformationControlCreator(sv)); return ca; } FAQ47 FAQ: FAQ How do I open an editor on a file in the workspace? IFile file = ; 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(); FAQ48 FAQ: FAQ What is a working copy? ICompilationUnit unit = ...; //get compilation unit handle unit.becomeWorkingCopy(null, null); try { IBuffer buffer = unit.getBuffer(); String oldContents = buffer.getContents(); String newContents = ...; //make some change buffer.setContents(newContents); unit.reconcile(false, null); } finally { unit.discardWorkingCopy(); } FAQ49 FAQ: FAQ How do I make my plug-in dynamic aware? public void startup() { IExtensionRegistry reg = Platform.getExtensionRegistry(); IExtensionPoint pt = reg.getExtensionPoint(PT_ID); IExtension[] ext = pt.getExtensions(); for (int i = 0; i < ext.length; i++) extensions.add(ext[i]); reg.addRegistryChangeListener(this); } FAQ50 FAQ: FAQ How do I enable global actions such as Cut, Paste, and Print in my editor? IAction print = ...; public void setActiveEditor(IEditorPart part) { IActionBars bars= getActionBars(); if (bars == null) return; print.setEditor(part); bars.setGlobalActionHandler( IWorkbenchActionConstants.PRINT, print); bars.updateActionBars(); } FAQ51 FAQ: How do I get at the file that a particular node represents? Node n = ...; DataObject dob = n.getLookup().lookup(DataObject.class); if (dob == null) { // definitely not a file node } else { // could also get all files in the data object, if desired: FileObject fo = dob.getPrimaryFile(); // and if you really need java.io.File File f = FileUtil.toFile (fo); if (f != null) { //if it is null, it is a virtual file - //its filesystem does not represent disk-based storage //do something } } FAQ52 FAQ: I need to add-to/remove-from/customize the content of my Node/DataObject/TopComponent's Lookup. How do I do it? public class FooDataObject extends MultiDataObject { private final Lookup lookup; private final InstanceContent lookupContents = new InstanceContent(); public FooDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { super(pf, loader); lookup = new ProxyLookup(getCookieSet().getLookup(), new AbstractLookup(lookupContents)); lookupContents.add (...whatever...); } @Override public Lookup getLookup() { return lookup; } @Override protected Node createNodeDelegate() { return new DataNode (this, Children.LEAF, getLookup()); } //... FAQ53 FAQ: Decorating an entire tree of Nodes class NodeProxy extends FilterNode { public NodeProxy(Node original) { super(original, new ProxyChildren(original)); } // add your specialized behavior here... } class ProxyChildren extends FilterNode.Children { public ProxyChildren(Node owner) { super(owner); } protected Node copyNode(Node original) { return new NodeProxy(original); } } FAQ54 FAQ: Saving Column Attributes of a TreeTableView public void writeExternal(ObjectOutput out) throws IOException { super.writeExternal(out); out.writeInt(columns.length); for (int ii = 0; ii < columns.length; ii++) { Boolean b = (Boolean) columns[Ii].getValue("InvisibleInTreeTableView"); if (b == null) { b = Boolean.FALSE; } out.writeBoolean(b.booleanValue()); Integer i = (Integer) columns[Ii].getValue("OrderNumberTTV"); if (i == null) { i = new Integer(ii); } out.writeInt(i.intValue()); b = (Boolean) columns[Ii].getValue("SortingColumnTTV"); if (b == null) { b = Boolean.FALSE; } out.writeBoolean(b.booleanValue()); b = (Boolean) columns[Ii].getValue("DescendingOrderTTV"); if (b == null) { b = Boolean.FALSE; } out.writeBoolean(b.booleanValue()); } try { TableColumnModel tcm = treeTable.getColumnModel(); int count = tcm.getColumnCount(); for (int index = 0; index < count; index++) { TableColumn tc = tcm.getColumn(index); out.writeInt(tc.getWidth()); } } catch (IOException ioe) { ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe); } } FAQ55 FAQ: Why do my nodes in the Explorer always have an expand-box by them, even though they have no children? void myModelChanged() { if (this.isLeaf()) { if (getObject().hasChildren()) { initChildren(); } } else { if (getObject().hasChildren()) { // Cause children to regenerate it's key list. this.getChildren().addNotify(); } else { // We no longer have children. Change to leaf. setChildren(Children.LEAF); } } } FAQ56 FAQ: How can I change my node's appearance? public class MovieNode extends AbstractNode { private Movie movie; public MovieNode(Movie key) { super(Children.LEAF, Lookups.fixed(new Object[]{key})); this.movie = key; setName(key.getTitle()); setDisplayName(key.getTitle()); getHandle(); setIconBaseWithExtension("org/nb/marilyn/pics/marilyn.gif"); } @Override public String getHtmlDisplayName() { return "" + this.getDisplayName() + ""; } } FAQ57 FAQ: I want to allow other modules to inject objects into my Node's Lookup or elsewhere (Actions, Properties...) public class BaseNode extends AbstractNode { final InstanceContent content; final Class type; public BaseNode(Class type, T modelObject) { this(type, modelObject, new InstanceContent()); } public BaseNode(Class type, T modelObject, InstanceContent content){ super(Children.LEAF, new ProxyLookup(Lookups.fixed(modelObject), new AbstractLookup(content))); this.content = content; this.type = type; //Populate lookup based on declaratively registered factories String pathInSystemFS = getRegistrationPath("lookupContents"); Collection all = Lookups.forPath(pathInSystemFS). lookupAll(InstanceContent.Convertor.class); for (InstanceContent.Convertor factory : all) { content.add(modelObject, factory); } //if you want to handle modules being loaded/unloaded in a running app, //use lookupResult() instead of lookupAll(), retain a reference to the //Lookup.Result, listen on it for changes, and remove all acquired //InstanceContent objects if it changes, then rerun the above code } @Override public Action[] getActions(boolean context) { return Lookups.forPath(getRegistrationPath("actions")). lookupAll(Action.class).toArray(new Action[0]); } String getRegistrationPath(String subfolder) { //e.g. pass "lookupContents" and get //MyModule/com/foo/mymodule/MyType/lookupContents return "MyModule/" + type.getName().replace('.', '/') + "/" + subfolder; } } FAQ58 FAQ: How to execute a long running task from an action without blocking the GUI? @ActionRegistration(asynchronous = true) ... public void actionPerformed(ActionEvent ev) { if (isLongTaskRequired) { // maybe run a ProgressHandler doLongTask(); } EventQueue.invokeLater(new Runnable() { @Override public void run() { // do domething with the gui } }); } FAQ59 FAQ: How can I operation occasionally on a background thread, but reschedule it if something happens to delay it? public class FooDataNode extends DataNode implements PropertyChangeListener, Runnable { private boolean error; private static final RequestProcessor THREAD_POOL = new RequestProcessor("FooDataNode processor", 1); private final RequestProcessor.Task task = THREAD_POOL.create(this); FooDataNode(FooDataObject obj) { super(obj, Children.LEAF); obj.addPropertyChangeListener(WeakListeners.propertyChange(this, obj)); task.schedule(100); } public void propertyChange(PropertyChangeEvent evt) { DataObject obj = (DataObject) evt.getSource(); if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName()) && !obj.isModified()) { //file was saved task.schedule(100); } } @Override public String getHtmlDisplayName() { return error ? "" + getDisplayName() : null; } public void run() { boolean old = error; error = doesTheFileHaveErrors(); if (old != error) { fireDisplayNameChange(null, null); } } private boolean doesTheFileHaveErrors() { assert !EventQueue.isDispatchThread(); //parse the file here return true; //whatever the value should be } } FAQ60 FAQ: My TopComponent always opens in the editor area, but I want it to open in the same place as XYZ? public MyTopComponent extends TopComponent { public void open() { Mode m = WindowManager.getDefault().findMode ("output"); if (m != null) { m.dockInto(this); } super.open(); } } FAQ61 FAQ: I want to disable the popup menu on the toolbars in the main window. How do I do that? package org.netbeans.modules.toolbarthing; import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JToolBar; import org.openide.modules.ModuleInstall; import org.openide.windows.WindowManager; public class Installer extends ModuleInstall implements Runnable { public void restored() { WindowManager.getDefault().invokeWhenUIReady(this); } public void run() { JToolBar[] tb = findToolbars(); for (int i = 0; i < tb.length; i++) { processToolbar (tb[I]); } } private JToolBar[] findToolbars() { List l = new ArrayList(); JFrame jf = (JFrame) WindowManager.getDefault().getMainWindow(); findToolbars (jf.getContentPane(), l); JToolBar[[ | ]] tb = (JToolBar[[ | ]]) l.toArray(new JToolBar[L.size()]); return tb; } private void findToolbars(Component c, List l) { if (c instanceof JToolBar) { l.add(c); } else if (c instanceof Container) { Component[] cc = ((Container) c).getComponents(); for (int i=0; i < cc.length; i++) { findToolbars(cc[I], l); } } } private void processToolbar (JToolBar bar) { MouseListener[] ml = bar.getMouseListeners(); for (int i = 0; i < ml.length; i++) { if (ml[I].getClass().getName().indexOf("PopupListener") >= 0) { bar.removeMouseListener (ml[I]); } } } } FAQ62 FAQ: I want to create a TopComponent class to use as an editor, not a singleton void init(final FooDataObject file) throws IOException { associateLookup(file.getLookup()); setDisplayName(file.getName()); setLayout(new BorderLayout()); add(new JLabel(getDisplayName()), BorderLayout.NORTH); //If you expect large files, load the file in a background thread //and set the field's text under its Document's lock final JTextField field = new JTextField(file.getPrimaryFile().asText()); add(field, BorderLayout.CENTER); field.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { changedUpdate(e); } @Override public void removeUpdate(DocumentEvent e) { changedUpdate(e); } @Override public void changedUpdate(DocumentEvent e) { FooDataObject foo = getLookup().lookup(FooDataObject.class); foo.setContent(field.getText()); } }); file.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) { //fire a dummy event setDisplayName(Boolean.TRUE.equals(evt.getNewValue()) ? file.getName() + "*" : file.getName()); } } }); } FAQ63 FAQ: How can I control when the OK button is enabled? public void actionPerformed(ActionEvent e) { MyForm form = new MyForm(); DialogDescriptor desc = new DialogDescriptor(form, "Hello", true, DialogDescriptor.OK_CANCEL_OPTION, DialogDescriptor.OK_OPTION, null); desc.setValid(false); form.setDialogDescriptor(desc); DialogDisplayer.getDefault().notify(desc); // displays the dialog } static class MyForm extends JPanel implements DocumentListener { private JTextField field; private DialogDescriptor desc; MyForm() { super(new BorderLayout()); field = new JTextField(); add(new JLabel("Type Something Here"), BorderLayout.NORTH); add(field, BorderLayout.SOUTH); } void setDialogDescriptor(DialogDescriptor desc) { this.desc = desc; field.getDocument().addDocumentListener(this); } private void doEnablement() { if (field.getText().isEmpty()) { desc.setValid(false); } else { desc.setValid(true); } } @Override public void insertUpdate(DocumentEvent e) { doEnablement(); } @Override public void removeUpdate(DocumentEvent e) { doEnablement(); } @Override public void changedUpdate(DocumentEvent e) { doEnablement(); } } FAQ64 FAQ: How can I open a Project programatically? File projectToBeOpenedFile = new File(getPath()); FileObject projectToBeOpened = FileUtil.toFileObject(projectToBeOpenedFile); Project project = ProjectManager.getDefault().findProject(projectToBeOpened); Project[] array = new Project[1]; array[0] = project; OpenProjects.getDefault().open(array, false); FAQ65 FAQ: How to get the project for the actual file in the editor? Project p = TopComponent.getRegistry().getActivated().getLookup().lookup(Project.class); if (p == null) { DataObject dob = TopComponent.getRegistry().getActivated().getLookup().lookup(DataObject.class); if (dob != null) { FileObject fo = dob.getPrimaryFile(); p = FileOwnerQuery.getOwner(fo); ... FAQ66 FAQ: How to get the name of the active project group /** * * @return name of the current project group or null */ public String getActiveProjectGroup() { Preferences groupNode = getPreferences("org/netbeans/modules/projectui/groups"); if (null != groupNode) { final String groupId = groupNode.get("active", null); if (null != groupId) { final Preferences groupPref = getPreferences("org/netbeans/modules/projectui/groups/" + groupId); if (null != groupPref) { final String activeProjectGroup = groupPref.get("name", null); return activeProjectGroup; } } } return null; } /** * Get the preference for the given node path. * * @param path configuration path like "org/netbeans/modules/projectui" * @return {@link Preferences} or null */ private Preferences getPreferences(String path) { try { if (NbPreferences.root().nodeExists(path)) { return NbPreferences.root().node(path); } } catch (BackingStoreException ex) { Exceptions.printStackTrace(ex); } return null; } FAQ67 FAQ: How do I add a new panel to a Project Properties dialog? @ProjectCustomizer.CompositeCategoryProvider.Registration( projectType="org-netbeans-modules-java-j2seproject") public class BlaPanelProvider implements ProjectCustomizer.CompositeCategoryProvider { public @Override Category createCategory(Lookup context) { return ProjectCustomizer.Category.create( "Bla", "Bla", null, null); } public @Override JComponent createComponent(Category category, Lookup context) { return new BlaPanel(); } } FAQ68 FAQ: How do I add an action to a project popup menu of a specific project type? @ActionID(...) @ActionRegistration(...) @ActionReference(path="Projects/Actions") public class DemoAction extends AbstractAction implements ContextAwareAction { public @Override void actionPerformed(ActionEvent e) {assert false;} public @Override Action createContextAwareInstance(Lookup context) { return new ContextAction(context); } private static final class ContextAction extends AbstractAction { private final Project p; public ContextAction(Lookup context) { p = context.lookup(Project.class); String name = ProjectUtils.getInformation(p).getDisplayName(); // TODO state for which projects action should be enabled char c = name.charAt(0); setEnabled(c >= 'A' && c <= 'M'); putValue(DynamicMenuContent.HIDE_WHEN_DISABLED, true); // TODO menu item label with optional mnemonics putValue(NAME, "&Info on " + name); } public @Override void actionPerformed(ActionEvent e) { // TODO what to do when run String msg = "Project location: " + FileUtil.getFileDisplayName(p.getProjectDirectory()); DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(msg)); } } } FAQ69 FAQ: How do I identify the "main project"? public final class ShowMainProjectAction extends CookieAction { protected void performAction(Node[] activatedNodes) { String projectPath = OpenProjects.getDefault().getMainProject().getProjectDirectory().getPath(); JOptionPane.showMessageDialog(null, projectPath); } protected int mode() { return CookieAction.MODE_EXACTLY_ONE; } public String getName() { return NbBundle.getMessage(ShowMainProjectAction.class, "CTL_ShowMainProjectAction"); } protected Class[] cookieClasses() { return new Class[]{Project.class}; } @Override protected void initialize() { super.initialize(); // see org.openide.util.actions.SystemAction.iconResource() Javadoc for more details putValue("noIconInMenu", Boolean.TRUE); } public HelpCtx getHelpCtx() { return HelpCtx.DEFAULT_HELP; } @Override protected boolean asynchronous() { return false; } } FAQ70 FAQ: How do I change the default behavior of PropertySheet editors? class MyEditor implements ExPropertyEditor { PropertyEnv env; public void attachEnv(e) { env = e; } public void anyMethod() { Object[] arr = env.getBeans(); // now arr contains either the real bean objects if invoked on Object // or it contains Node that the properties belong to } } FAQ71 FAQ: How do I show my node's properties in the Properties view? public class MyComponent extends TopComponent implements PropertyChangeListener { private ExplorerManager explorerManager; public MyComponent() { explorerManager = new ExplorerManager(); explorerManager.addPropertyChangeListener(this); } public void propertyChange(PropertyChangeEvent evt) { if (evt.getSource() == explorerManager && ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) { setActivatedNodes(explorerManager.getSelectedNodes()); } } } FAQ72 FAQ: How do I route the output from an external process to the output window? private class ProcessLaunch implements Callable { private final String[] commandLine; public ProcessLaunch(String... commandLine) { this.commandLine = commandLine; } public Process call() throws Exception { ProcessBuilder pb = new ProcessBuilder(cmdline); pb.directory(new File(System.getProperty("user.home"))); //NOI18N pb.redirectErrorStream(true); return pb.start(); } } FAQ73 FAQ: How to use color text in Output Window InputOutput io = IOProvider.getDefault().getIO("test", true); // change default color for output in corresponding tab if (IOColors.isSupported(io)) { IOColors.setColor(io, IOColors.OutputType.OUTPUT, Color.GRAY); } // print line in specific color if (IOColorLines.isSupported(io)) { IOColorLines.println(io, "Green line", Color.GREEN); } class L implements OutputListener { //... } // print parts of line in specific color if (IOColorPrint.isSupported(io)) { IOColorPrint.print(io, "Green part", Color.GREEN); IOColorPrint.print(io, " pink part", Color.PINK); IOColorPrint.print(io, " hyperlink with custom color", new L(), false, Color.MAGENTA); } FAQ74 FAQ: How do I remove the status bar? private static JComponent getCustomStatusLine() { try { String fileName = Constants.CUSTOM_STATUS_LINE_PATH; if (fileName == null) { return null; } FileObject fo = FileUtil.getConfigFile(fileName); if (fo != null) { DataObject dobj = DataObject.find(fo); InstanceCookie ic = (InstanceCookie)dobj.getCookie(InstanceCookie.class); if (ic != null) { return (JComponent)ic.instanceCreate(); } } } catch (Exception e) { Exceptions.printStackTrace(e); } return null; } FAQ75 FAQ: Other strategies for authentication and authorization package com.tomwheeler; import java.lang.reflect.Method; public class CustomStartup { private static final String NB_MAIN_CLASS = "org.netbeans.core.startup.Main"; public static void main(String[] args) throws Exception { // do whatever you need here (e.g. show a custom login form) System.out.println("Hello world! I am a custom startup class"); // once you're done with that, hand control back to NetBeans ClassLoader classloader = Thread.currentThread().getContextClassLoader(); Class mainClass = Class.forName(NB_MAIN_CLASS, true, classloader); Object mainObject = mainClass.newInstance(); Method mainMethod = mainClass.getDeclaredMethod("main", new Class[]{String[].class}); mainMethod.invoke(mainObject, (Object) args); } } FAQ76 FAQ: How Can I Hook Up JavaHelp to Property Sets or Individual Properties? @Override protected Sheet createSheet() { Sheet s = super.createSheet(); Sheet.Set ss = s.get(Sheet.PROPERTIES); if (ss == null) { ss = Sheet.createPropertiesSet(); s.put(ss); } // Do this to specify help for a whole sheet set ss.setValue("helpID", "my.help.ctx"); ss.put(new FirstNameProperty("Abe")); ss.put(new LastNameProperty("Lincoln")); return s; } FAQ77 FAQ: How do I Get All Methods/Fields/Constructors of a Class? protected void performAction(Node[] activatedNodes) { DataObject dataObject = (DataObject) activatedNodes[0].getLookup().lookup(DataObject.class); JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile()); try { js.runUserActionTask(new Task() { public void run(CompilationController parameter) throws IOException { parameter.toPhase(Phase.ELEMENTS_RESOLVED); new MemberVisitor(parameter).scan(parameter.getCompilationUnit(), null); } }, true); } catch (IOException e) { Logger.getLogger("global").log(Level.SEVERE, e.getMessage(), e); } } private static class MemberVisitor extends TreePathScanner { private CompilationInfo info; public MemberVisitor(CompilationInfo info) { this.info = info; } @Override public Void visitClass(ClassTree t, Void v) { Element el = info.getTrees().getElement(getCurrentPath()); if (el == null) { System.err.println("Cannot resolve class!"); } else { TypeElement te = (TypeElement) el; System.err.println("Resolved class: " + te.getQualifiedName().toString()); //XXX: only as an example, uses toString on element, which should be used only for debugging System.err.println("enclosed methods: " + ElementFilter.methodsIn(te.getEnclosedElements())); System.err.println("enclosed types: " + ElementFilter.typesIn(te.getEnclosedElements())); } return null; } } FAQ78 FAQ: How do I obtain a source file for a Java class and open it in the editor? String classResource = "javax/swing/JComponent.java"; for (FileObject curRoot : GlobalPathRegistry.getDefault().getSourceRoots()) { FileObject fileObject = curRoot.getFileObject(classResource); if (fileObject != null) { // source file object found // do something, e.g. openEditor(fileObject, lineNumber); return; } } FAQ79 FAQ: How can I scan a classpath to find all classes of a particular type? private Set> findAllSubTypes(ClassPath on, ElementHandle of) { ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.EMPTY, ClassPath.EMPTY, on); List> todo = new LinkedList>(of); Set> result = new HashSet>(); while (!todo.isEmpty()) { //TODO: if cancellable, check for cancel here ElementHandle curr = todo.remove(0); result.add(curr); Set> typeElements = cpInfo.getClassIndex().getElements(eh, EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS), EnumSet.of(ClassIndex.SearchScope.SOURCE)); if (typeElements != null) { //can be null for cancellable tasks todo.addAll(typeElements); } } return result; } FAQ80 FAQ: FAQ What is a document partition? IPartitionTokenScanner createScanner() { IToken cmt = new Token(HTMLConfiguration.HTML_COMMENT); IToken tag = new Token(HTMLConfiguration.HTML_TAG); IPredicateRule[] rules = new IPredicateRule[2]; rules[0] = new MultiLineRule("", cmt); rules[1] = new TagRule(tag); RuleBasedPartitionScanner scanner = new RuleBasedPartitionScanner(); scanner.setPredicateRules(rules); return sc; } FAQ81 FAQ: FAQ How do I create a repeating background task? public class RepeatingJob extends Job { private boolean running = true; public RepeatingJob() { super("Repeating Job"); } protected IStatus run(IProgressMonitor monitor) { schedule(60000); return Status.OK_STATUS; } public boolean shouldSchedule() { return running; } public void stop() { running = false; } } /* Sample Code by Parvez Hakim www.abobjects.com */ RepeatingJob job = new RepeatingJob("BackupScheduler"+jobNumber++,nextDelay) { protected IStatus run(IProgressMonitor monitor){ schedule(repeatDelay-cpuTimeTakenbyJob); return org.eclipse.core.runtime.Status.OK_STATUS; } }; job.schedule(delay); // start after 20 seconds return job; } public abstract class RepeatingJob extends Job{ private boolean running = true; protected long repeatDelay = 0; public RepeatingJob(String jobName,long repeatPeriod){ super(jobName); repeatDelay = repeatPeriod; }/** protected IStatus run(IProgressMonitor monitor) { schedule(repeatDelay); return Status.OK_STATUS; } */ public boolean shouldSchedule() { return running; } public void stop() { running = false; } } FAQ82 FAQ: FAQ How do I implement an incremental project builder? public class Builder extends IncrementalProjectBuilder { protected IProject[] build(int kind, Map args, IProgressMonitor monitor) { if (kind == IncrementalProjectBuilder.FULL_BUILD) { fullBuild(monitor); } else { IResourceDelta delta = getDelta(getProject()); if (delta == null) { fullBuild(monitor); } else { incrementalBuild(delta, monitor); } } return null; } private void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) { System.out.println("incremental build on "+delta); try { delta.accept(new IResourceDeltaVisitor() { public boolean visit(IResourceDelta delta) { System.out.println("changed: "+ delta.getResource().getRawLocation()); return true; // visit children too } }); } catch (CoreException e) { e.printStackTrace(); } } private void fullBuild(IProgressMonitor monitor) { System.out.println("full build"); } } FAQ83 FAQ: FAQ How do I add Content Assist to my language editor? class CompletionProcessor implements IContentAssistProcessor { private final IContextInformation[] NO_CONTEXTS = { }; private final char[] PROPOSAL_ACTIVATION_CHARS = { 's','f','p','n','m', }; private ICompletionProposal[] NO_COMPLETIONS = { }; public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { try { IDocument document = viewer.getDocument(); ArrayList result = new ArrayList(); String prefix = lastWord(document, offset); String indent = lastIndent(document, offset); EscriptModel model = EscriptModel.getModel(document, null); model.getContentProposals(prefix, indent, offset, result); return (ICompletionProposal[]) result.toArray(new ICompletionProposal[result.size()]); } catch (Exception e) { // ... log the exception ... return NO_COMPLETIONS; } } private String lastWord(IDocument doc, int offset) { try { for (int n = offset-1; n >= 0; n--) { char c = doc.getChar(n); if (!Character.isJavaIdentifierPart(c)) return doc.get(n + 1, offset-n-1); } } catch (BadLocationException e) { // ... log the exception ... } return ""; } private String lastIndent(IDocument doc, int offset) { try { int start = offset-1; while (start >= 0 && doc.getChar(start)!= '\n') start--; int end = start; while (end < offset && Character.isSpaceChar(doc.getChar(end))) end++; return doc.get(start+1, end-start-1); } catch (BadLocationException e) { e.printStackTrace(); } return ""; } public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { return NO_CONTEXTS; } char[] getCompletionProposalAutoActivationCharacters() { return PROPOSAL_ACTIVATION_CHARS; } // ... remaining methods are optional ... } FAQ84 FAQ: FAQ How do I create and examine an AST? class ASTPrinter extends ASTVisitor { StringBuffer buffer = new StringBuffer(); public void preVisit(ASTNode node) { //write the name of the node being visited printDepth(node); String name = node.getClass().getName(); name = name.substring(name.lastIndexOf('.')+1); buffer.append(name); buffer.append(" {\r\n"); } public void postVisit(ASTNode node) { //write a closing brace to indicate end of the node printDepth(node); buffer.append("}\r\n"); } void printDepth(ASTNode node) { //indent the current line to an appropriate depth while (node != null) { node = node.getParent(); buffer.append(" "); } } } ... //java model handle for selected file ICompilationUnit unit = ...; ASTParser parser = ASTParser.newParser(AST.JLS2); parser.setKind(ASTParser.K_COMPILATION_UNIT); CompilationUnit ast = (CompilationUnit)parser.createAST(null); ASTPrinter printer = new ASTPrinter(); ast.accept(printer); MessageDialog.openInformation(shell, "AST for: " + unit.getElementName(), printer.buffer.toString()); FAQ85 FAQ: FAQ How does a view persist its state between sessions? private static final String STORE_SELECTION = "ShoppingList.SELECTION"; public void saveState(IMemento memento) { super.saveState(memento); ISelection sel = viewer.getSelection(); IStructuredSelection ss = (IStructuredSelection) sel; StringBuffer buf = new StringBuffer(); for (Iterator it = ss.iterator(); it.hasNext();) { buf.append(it.next()); buf.append(','); } memento.putString(STORE_SELECTION, buf.toString()); } FAQ86 FAQ: FAQ How do I create a Rich Client application? public class MinimalRCPApp extends WorkbenchAdvisor implements IPlatformRunnable { public String getInitialWindowPerspectiveId() { return "org.eclipse.faq.minimalperspective"; } public void preWindowOpen( IWorkbenchWindowConfigurer wwc) { configurer.setShowMenuBar(false); configurer.setShowFastViewBars(false); configurer.setShowStatusLine(false); configurer.setShowCoolBar(false); } public Object run(Object args) throws Exception { Display d = PlatformUI.createDisplay(); int ret = PlatformUI.createAndRunWorkbench(d, this); if (ret == PlatformUI.RETURN_RESTART) return EXIT_RESTART; return EXIT_OK; } } FAQ87 FAQ: FAQ How do I load and save plug-in preferences? private void savePluginSettings() { // saves plugin preferences at the workspace level Preferences prefs = //Platform.getPreferencesService().getRootNode().node(Plugin.PLUGIN_PREFEERENCES_SCOPE).node(MY_PLUGIN_ID); InstanceScope.INSTANCE.getNode(MY_PLUGIN_ID); // does all the above behind the scenes prefs.put(KEY1, this.someStr); prefs.put(KEY2, this.someBool); try { // prefs are automatically flushed during a plugin's "super.stop()". prefs.flush(); } catch(BackingStoreException e) { //TODO write a real exception handler. e.printStackTrace(); } } private void loadPluginSettings() { Preferences prefs = new InstanceScope().getNode(MY_PLUGIN_ID); // you might want to call prefs.sync() if you're worried about others changing your settings this.someStr = prefs.get(KEY1); this.someBool= prefs.getBoolean(KEY2); } FAQ88 FAQ: FAQ How to decorate a TableViewer or TreeViewer with Columns? /** * Class that supports Decoration of TableViewer and TreeViewer with TreeColumns */ package decorators; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.swt.graphics.Image; /** * @author Annamalai Chockalingam * */ public class TableDecoratingLabelProvider extends DecoratingLabelProvider implements ITableLabelProvider { ITableLabelProvider provider; ILabelDecorator decorator; /** * @param provider * @param decorator */ public TableDecoratingLabelProvider(ILabelProvider provider, ILabelDecorator decorator) { super(provider, decorator); this.provider = (ITableLabelProvider) provider; this.decorator = decorator; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) */ public Image getColumnImage(Object element, int columnIndex) { Image image = provider.getColumnImage(element, columnIndex); if (decorator != null) { Image decorated = decorator.decorateImage(image, element); if (decorated != null) { return decorated; } } return image; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) */ public String getColumnText(Object element, int columnIndex) { String text = provider.getColumnText(element, columnIndex); if (decorator != null) { String decorated = decorator.decorateText(text, element); if (decorated != null) { return decorated; } } return text; } FAQ89 FAQ: FAQ How do I open an editor on something that is not a file? class StringStorage 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 Object getAdapter(Class adapter) { return null; } public String getName() { int len = Math.min(5, string.length()); return string.substring(0, len).concat("..."); //$NON-NLS-1$ } public boolean isReadOnly() { return true; } } FAQ90 FAQ: FAQ How do I write an editor for my own language? class Scanner extends RuleBasedScanner { public Scanner() { WordRule rule = new WordRule(new IWordDetector() { public boolean isWordStart(char c) { return Character.isJavaIdentifierStart(c); } public boolean isWordPart(char c) { return Character.isJavaIdentifierPart(c); } }); Token keyword = new Token(new TextAttribute(Editor.KEYWORD, null, SWT.BOLD)); Token comment = new Token(new TextAttribute(Editor.COMMENT)); Token string = new Token(new TextAttribute(Editor.STRING)); //add tokens for each reserved word for (int n = 0; n < Parser.KEYWORDS.length; n++) { rule.addWord(Parser.KEYWORDS[n], keyword); } setRules(new IRule[] { rule, new SingleLineRule("#", null, comment), new SingleLineRule("\"", "\"", string, '\\'), new SingleLineRule("'", "'", string, '\\'), new WhitespaceRule(new IWhitespaceDetector() { public boolean isWhitespace(char c) { return Character.isWhitespace(c); } }), }); } } FAQ91 FAQ: FAQ How do I create an Outline view for my own language editor? public Object getAdapter(Class required) { if (IContentOutlinePage.class.equals(required)) { if (myOutlinePage == null) { myOutlinePage = new CoolLanguageContentOutlinePage( getDocumentProvider(), this); myOutlinePage.setInput(getEditorInput()); } return myOutlinePage; } return super.getAdapter(required); } FAQ92 FAQ: FAQ What is the Java model? IWorkspace workspace = ResourcesPlugin.getWorkspace(); IJavaModel javaModel = JavaCore.create(workspace.getRoot()); IJavaProject projects[] = javaModel.getJavaProjects(); for (int n = 0; n < projects.length; n++) { IJavaProject project = projects[n]; IPackageFragmentRoot[] roots = project.getAllPackageFragmentRoots(); int nClasses = 0; for (int k = 0; k < roots.length; k++) { IPackageFragmentRoot root = roots[k]; IJavaElement[] elements = root.getChildren(); for (int i = 0; i < elements.length; i++) { IJavaElement element = elements[i]; PackageFragment fragment = (PackageFragment) element.getAdapter(PackageFragment.class); if (fragment == null) continue; IJavaElement fes[] = fragment.getChildren(); for (int j = 0; j < fes.length; j++) { String className = fes[j].getElementName(); nClasses++; } } } String projectName = projects[n].getElementName(); System.out.println("Classpath for project "+ projectName +" contains "+nClasses+" classes."); } FAQ93 FAQ: FAQ How do I switch from using a Progress dialog to the Progress view? IRunnableWithProgress op = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { runDecathlon(monitor); } }; IWorkbench wb = PlatformUI.getWorkbench(); IWorkbenchWindow win = wb.getActiveWorkbenchWindow(); Shell shell = win != null ? win.getShell() : null; new ProgressMonitorDialog(shell).run(true, true, op); FAQ94 FAQ: FAQ How do I make a view respond to selection changes in another view? public class ChaptersView extends ViewPart { private TableViewer viewer; ISelectionListener listener = new ISelectionListener() { public void selectionChanged(IWorkbenchPart part, ISelection sel) { if (!(sel instanceof IStructuredSelection)) return; IStructuredSelection ss = (IStructuredSelection) sel; Object o = ss.getFirstElement(); if (o instanceof Book) viewer.setInput(ss.size()==1 ? o : null); } }; public void createPartControl(Composite parent) { getSite().getPage().addSelectionListener(listener); } public void dispose() { getSite().getPage().removeSelectionListener(listener); } } FAQ95 FAQ: FAQ How do I enable the Save and Revert actions? public class MinimalEditor extends EditorPart { protected boolean dirty = false; ... public boolean isDirty() { return dirty; } protected void setDirty(boolean value) { dirty = value; firePropertyChange(PROP_DIRTY); } } FAQ96 FAQ: FAQ How do I implement a search operation? class SearchSizePage extends DialogPage implements ISearchPage { private ISearchPageContainer container; public boolean performAction() { // ... validate input ... IRunnableWithProgress query = ...;//the query object container.getRunnableContext().run(true, true, query); return true; } public void setContainer(ISearchPageContainer spc) { this.container = spc; } } FAQ97 FAQ: FAQ How do I create a Compare dialog? class CompareItem implements IStreamContentAccessor, ITypedElement, IModificationDate { private String contents, name; private long time; CompareItem(String name, String contents, long time) { this.name = name; this.contents = contents; this.time = time; } public InputStream getContents() throws CoreException { return new ByteArrayInputStream(contents.getBytes()); } public Image getImage() {return null;} public long getModificationDate() {return time;} public String getName() {return name;} public String getString() {return contents;} public String getType() {return ITypedElement.TEXT_TYPE;} } FAQ98 FAQ: FAQ How do I create a dialog with a details area? Date date = new Date(); SimpleDateFormat format = new SimpleDateFormat(); String[] patterns = new String[] { "EEEE", "yyyy", "MMMM", "h 'o''clock'"}; String[] prefixes = new String[] { "Today is ", "The year is ", "It is ", "It is "}; String[] msg = new String[patterns.length]; for (int i = 0; i < msg.length; i++) { format.applyPattern(patterns[i]); msg[i] = prefixes[i] + format.format(date); } final String PID = ExamplesPlugin.ID; MultiStatus info = new MultiStatus(PID, 1, msg[0], null); info.add(new Status(IStatus.INFO, PID, 1, msg[1], null)); info.add(new Status(IStatus.INFO, PID, 1, msg[2], null)); info.add(new Status(IStatus.INFO, PID, 1, msg[3], null)); ErrorDialog.openError(window.getShell(), "Time", null, info); FAQ99 FAQ: FAQ How do I open an editor programmatically? import java.io.File; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.ui.PartInitException; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; File fileToOpen = new File("externalfile.xml"); if (fileToOpen.exists() && fileToOpen.isFile()) { IFileStore fileStore = EFS.getLocalFileSystem().getStore(fileToOpen.toURI()); IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); try { IDE.openEditorOnFileStore( page, fileStore ); } catch ( PartInitException e ) { //Put your exception handler here if you wish to } } else { //Do something if the file does not exist } FAQ100 FAQ: FAQ What is the difference between a path and a location? IPath location = ...; IFile[] files = root.findFilesForLocation(location); IFolder[] folders = root.findContainersForLocation(location); if (files.length > 0) { for (int i = 0; i < files.length; i++) path = files[i].getLocation(); } else { for (int i = 0; i < folders.length; i++) path = folders[i].getLocation(); } FAQ101 FAQ: FAQ How do I display a Web page in SWT? Display display = new Display(); final Shell shell = new Shell(display, SWT.SHELL_TRIM); shell.setLayout(new FillLayout()); Browser browser = new Browser(shell, SWT.NONE); browser.addTitleListener(new TitleListener() { public void changed(TitleEvent event) { shell.setText(event.title); } }); browser.setBounds(0,0,600,400); shell.pack(); shell.open(); browser.setUrl("http://eclipsefaq.org"); while (!shell.isDisposed()) if (!display.readAndDispatch()) display.sleep(); FAQ102 FAQ: FAQ How do I open an editor on a file outside the workspace? 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); FAQ103 FAQ: FAQ How do I add a builder to a given project? private void addBuilder(IProject project, String id) { IProjectDescription desc = project.getDescription(); ICommand[] commands = desc.getBuildSpec(); for (int i = 0; i < commands.length; ++i) if (commands[i].getBuilderName().equals(id)) return; //add builder to project ICommand command = desc.newCommand(); command.setBuilderName(id); ICommand[] nc = new ICommand[commands.length + 1]; // Add it before other builders. System.arraycopy(commands, 0, nc, 1, commands.length); nc[0] = command; desc.setBuildSpec(nc); project.setDescription(desc, null); } FAQ104 FAQ: FAQ How do I add hover support to my text editor? public class TextHover implements ITextHover { public IRegion getHoverRegion(ITextViewer tv, int off) { return new Region(off, 0); } public String getHoverInfo(ITextViewer tv, IRegion r) { try { IDocument doc = tv.getDocument(); EscriptModel em = EscriptModel.getModel(doc, null); return em.getElementAt(r.getOffset()). getHoverHelp(); } catch (Exception e) { return ""; } } } FAQ105 FAQ: FAQ How do I launch a Java program? void launch(IJavaProject proj, String main) { IVMInstall vm = JavaRuntime.getVMInstall(proj); if (vm == null) vm = JavaRuntime.getDefaultVMInstall(); IVMRunner vmr = vm.getVMRunner(ILaunchManager.RUN_MODE); String[] cp = JavaRuntime. computeDefaultRuntimeClassPath(proj); VMRunnerConfiguration config = new VMRunnerConfiguration(main, cp); ILaunch launch = new Launch(null, ILaunchManager.RUN_MODE, null); vmr.run(config, launch, null); } FAQ106 FAQ: FAQ How do I find out what object is selected? IWorkbenchPage page = ...; //the current selection in the entire page ISelection selection = page.getSelection(); //the current selection in the navigator view selection = page.getSelection(IPageLayout.ID_RES_NAV); //add a listener ISelectionListener sl = new ISelectionListener() { public void selectionChanged(IWorkbenchPart part, ISelection sel) { System.out.println("Selection is: " + sel); } }; page.addSelectionListener(sl); //add a listener to selection changes only //in the navigator view page.addSelectionListener(sl, IPageLayout.ID_RES_NAV); FAQ107 FAQ: FAQ How do I make my view appear in the Show In menu? public boolean show(ShowInContext context) { if (viewer == null || context == null) return false; ISelection sel = context.getSelection(); if (sel instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection)sel; Object first = ss.getFirstElement(); if (first instanceof Book) { viewer.setInput(first); return true; } } return false; } FAQ108 FAQ: FAQ How do I create my own editor? public class MinimalEditor extends EditorPart { private Label contents; public void createPartControl(Composite parent) { contents = new Label(parent, SWT.NONE); contents.setText("Minimal Editor"); } public void init(IEditorSite site, IEditorInput input) { setSite(site); setInput(input); } public void setFocus() { if (contents != null) contents.setFocus(); } } FAQ109 FAQ: FAQ How do I create a compare editor? class CompareInput extends CompareEditorInput { public CompareInput() { super(new CompareConfiguration()); } protected Object prepareInput(IProgressMonitor pm) { CompareItem ancestor = new CompareItem("Common", "contents"); CompareItem left = new CompareItem("Left", "new contents"); CompareItem right = new CompareItem("Right", "old contents"); return new DiffNode(null, Differencer.CONFLICTING, ancestor, left, right); } } FAQ110 FAQ: FAQ How can I change the name or tooltip of my action? class ToggleAction implements IWorkbenchWindowActionDelegate { private boolean state = false; public void run(IAction action) { state = !state; String name = state ? "True Action" : "False Action"; action.setText(name); action.setToolTipText(name); } } FAQ111 FAQ: FAQ How do I support multiple natural languages in my plug-in messages? String translate(String key, String[] parms) { try { ResourceBundle bundle = ResourceBundle.getBundle("messages"); String msg = bundle.getString(key); return MessageFormat.format(msg, parms); } catch (MissingResourceException e) { return key; } } FAQ112 FAQ: FAQ How do I prevent builds between multiple changes to the workspace? final IFolder folder1 = ..., folder2 = ...; Job job = new WorkspaceJob("Creating folders") { public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { folder1.create(IResource.NONE, true, null); folder2.create(IResource.NONE, true, null); return Status.OK_STATUS; } }; job.schedule(); FAQ113 FAQ: FAQ How do I open a Property dialog? ISelection sel = ... obtain the current selection PropertyPage page = new MyPropertyPage(); PreferenceManager mgr = new PreferenceManager(); IPreferenceNode node = new PreferenceNode("1", page); mgr.addToRoot(node); PropertyDialog dialog = new PropertyDialog(shell, mgr, sel); dialog.create(); dialog.setMessage(page.getTitle()); dialog.open(); FAQ114 FAQ: FAQ How do I support formatting in my editor? MultiPassContentFormatter formatter= new MultiPassContentFormatter( getConfiguredDocumentPartitioning(viewer), IDocument.DEFAULT_CONTENT_TYPE); formatter.setMasterStrategy( new JavaFormattingStrategy()); formatter.setSlaveStrategy( new CommentFormattingStrategy(...), IJavaPartitions.JAVA_DOC); FAQ115 FAQ: FAQ How do I insert text in the active text editor? IWorkbenchPage page = ...; IEditorPart part = page.getActiveEditor(); if (!(part instanceof AbstractTextEditor) return; ITextEditor editor = (ITextEditor)part; IDocumentProvider dp = editor.getDocumentProvider(); IDocument doc = dp.getDocument(editor.getEditorInput()); int offset = doc.getLineOffset(doc.getNumberOfLines()-4); doc.replace(offset, 0, pasteText+"\n"); FAQ116 FAQ: FAQ How do activities get enabled? String id = ... IWorkbench wb = PlatformUI.getWorkbench(); IWorkbenchActivitySupport as = wb.getActivitySupport(); IActivityManager am = as.getActivityManager(); IIdentifier identifier = am.getIdentifier(id); Set activities = new HashSet(am.getEnabledActivityIds()); if (activities.addAll(identifier.getActivityIds())) { as.setEnabledActivityIds(activities); } FAQ117 FAQ: FAQ How do I distinguish between internal and external JARs on the build path? IClasspathEntry entry = ... IPath path = entry.getPath(); IWorkspace workspace = ResourcesPlugin.getWorkspace(); IResource jarFile= workspace.getRoot().findMember(path); if (jarFile != null) { return jarFile.getLocation(); } else { // must be an external JAR (or invalid classpath entry) } FAQ118 FAQ: FAQ How do I use the context class loader in Eclipse? Thread current = Thread.currentThread(); ClassLoader oldLoader = current.getContextClassLoader(); try { current.setContextClassLoader(getClass().getClassLoader()); //call library code here } finally { current.setContextClassLoader(oldLoader); } FAQ119 FAQ: FAQ How do I launch the preference page that belongs to my plug-in? IPreferencePage page = new MyPreferencePage(); PreferenceManager mgr = new PreferenceManager(); IPreferenceNode node = new PreferenceNode("1", page); mgr.addToRoot(node); PreferenceDialog dialog = new PreferenceDialog(shell, mgr); dialog.create(); dialog.setMessage(page.getTitle()); dialog.open(); FAQ120 FAQ: FAQ How do I use progress monitors? try { monitor.beginTask("Performing decathlon: ", 10); monitor.subTask("hammer throw"); //perform the hammer throw monitor.worked(1); //... repeat for remaining nine events } finally { monitor.done(); } FAQ121 FAQ: FAQ How do I use a SubProgressMonitor? public void move(File a, File b, IProgressMonitor pm) { try { pm.beginTask("Moving", 10); copy(a, b, new SubProgressMonitor(pm, 8)); delete(a, new SubProgressMonitor(pm, 2)); } finally { pm.done(); } } FAQ122 FAQ: FAQ How do I use IAdaptable and IAdapterFactory? Object input = ...; IResource resource = null; if (input instanceof IResource) { resource = (IResource)input; } else if (input instanceof IAdaptable) { IAdaptable a = (IAdaptable)input; resource = (IResource)a.getAdapter(IResource.class); } FAQ123 FAQ: FAQ How do I react to changes in source files? IResourceChangeListener rcl = new IResourceChangeListener() { public void resourceChanged(IResourceChangeEvent event) { IResource resource = event.getResource(); if (resource.getFileExtension().equals("escript")) { // run the compiler } } }; ResourcesPlugin.getWorkspace().addResourceChangeListener(rcl); FAQ124 FAQ: FAQ How do I create Java elements? IType type = ...; String body = "public String toString() {"+ "return super.toString();}"; IMethod method = type.'''getMethod'''("toString", new String[0]); if (!method.exists()) method = type.createMethod(body, null, false, null); FAQ125 FAQ: FAQ How do I make key bindings work in an RCP application? public void fillActionBars(IWorkbenchWindow window, IActionBarConfigurer configurer, int flags) { ... if (maximizeAction == null) { maximizeAction = ActionFactory.MAXIMIZE.create(window); configurer.registerGlobalAction(maximizeAction); } menu.add(maximizeAction); } FAQ126 FAQ: FAQ How do I use the platform logging facility? import org.eclipse.core.runtime.Status; ... public void log(String msg) { log(msg, null); } public void log(String msg, Exception e) { getLog().log(new Status(Status.INFO, myPluginID, Status.OK, msg, e)); } FAQ127 FAQ: FAQ How do I prevent two jobs from running at the same time? public class MutexRule implements ISchedulingRule { public boolean isConflicting(ISchedulingRule rule) { return rule == this; } public boolean contains(ISchedulingRule rule) { return rule == this; } }