How to use certain NetBeans APIs

This page contains extracted usecases for some of the NetBeans modules that offer an API.

How to use Common Annotations?

Provides common annotations serving as a documentation element and for static code analysis.

CheckReturnValue annotated method

When the method return value is important value to check (or the only effect the method has) the method can be annotated with CheckReturnValue. Annotation servers as documentation as well as a hint for static code analysis.

CheckForNull annotated method

Method annotated with CheckForNull may return null value. Annotation servers as documentation as well as a hint for static code analysis.

NonNull annotated element

When the field, parameter, local variable or return value of the method must not be null the NonNull annotation can be used to clearly express this. It servers as documentation as well as a hint for static code analysis.

NullAllowed annotated element

Field, parameter or local variable annotated with NullAllowed can contain null value so null check should occur before any dereference. Annotation servers as documentation as well as a hint for static code analysis.

NullUnknown annotated element

Annotation NullUnknown complementing other nullness annotations servers for cases where the element may or may not be null under certain defined circumstances (usage).

SuppressWarnings annotated element

When the analysis tool report false warning it is possible to use SuppressWarning annotation to suppress the warning.


How to use Intent API?

This module provides a contract between API clients that can express some intention to invoke an operation and SPI providers that can handle that intention. This is useful in client-server environments, where the intention can be constructed on server-side, but handled on client-side. The objects that describe the intention should be easy to construct, transfer and interpret.

Create an Intent, execute it and wait for result

                Future<Object> result = new Intent(Intent.ACTION_VIEW, new URI("scheme://path/")).execute();
    Object value = result.get();
            
        

Create an Intent and execute it with callback

                new Intent(Intent.ACTION_VIEW, new URI("scheme://path/")).execute(new Callback() {
      void success(Object result) {
        // use the result somehow
      }
      void failure(Exception exception) {
        // report the failure somehow
      }
    });
            
        

Handle some Intent

                @IntentHandlerRegistration(
                displayName = "Show my item in MyEditor",
                position = 800,
                uriPattern = "myscheme://.*",
                actions = {Intent.ACTION_VIEW, Intent.ACTION_EDIT}
    )
    public static Object handleIntent(Intent intent) {
        SomeType result = parseAndPerformIntentSomehow(intent);
        return result;
    }
            
        

Handle some Intent using Result object

                @IntentHandlerRegistration(
                displayName = "Show my item in MyEditor",
                position = 800,
                uriPattern = "myscheme://.*",
                actions = "*"
    )
    public static void handleIntent(final Intent intent, final Result result) {
        // Move the execution to another thread. Do not wait for the result
        // here, just pass the result object.
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Object result = doSomethingInEDT(intent);
                    result.setResult(e);
                } catch (Exception e) {
                    result.setException(e);
                }
            }
        });
    }
            
        

How to use I/O API and SPI?

The Input/Output API and SPI is a small module which contains InputOutput and related interfaces used in driving the Output Window. The normal implementation is org.netbeans.core.output2.

Print a simple output to a new output tab

The basic use-case is printing a simple text, e.g. text output of an application, into a dedicated pane in the UI, e.g. a tab in Output Window in the IDE.

    InputOutput io = InputOutput.get("UseCase1", true);
    io.getOut().println("This is a simple output");
    io.getOut().close();
            

Print a line with hyperlink for invocation of arbitrary code

Hyperlinks can be also used to invoke some code when clicked.

    InputOutput io = InputOutput.get("UseCase3", true);
    io.getOut().print("A line containing a ");
    io.getOut().print("hyperlink", Hyperlink.from(new Runnable() {
        public void run() {
            System.gc();
        }
    }));
    io.getOut().println(" for invocation of custom code.");
    io.getOut().close();
            

Print color text

Print a color text. Users can select a predefined color for common cases (debug, warning, failure, success), or custom color specified as RGB value.

    InputOutput io = InputOutput.get("UseCase4", true);
    io.getOut().println("Let's print some info", OutputColor.debug());
    io.getOut().println("or warning with appropriate color", OutputColor.warning());
    io.getOut().println("Maybe also text with custom reddish color", OutputColor.rgb(255, 16, 16));
    io.getOut().close();
            

Reset an InputOutput to clear all previosly printed text

It is possible to reuse already created output pane and clear all the previously printed text if it is not needed any more.

    InputOutput io = InputOutput.get("UseCase5", true);
    io.getOut().println("Let's print some text");
    io.getErr().println("and reset the pane immediately.");
    io.reset();
    io.getOut().println("The pane is now empty and we can reuse it simply");
    io.getOut().close();
            

How to use Progress API?

The progress API is good for tracking progress of long lasting tasks in the IDE.

Basic usage

There are 3 types of progress indication:

The default location of the progress indication is the status bar which aggregates all tasks running in the IDE that show progress. However it's possible to exclude the task from the default location and show the progress in one's custom dialog component. In such a case the same task should not appear in the status line component as well.

It's possible to request cancelling the task from status line progress aggregator if the task allows cancelling.

Progress tasks that get started as a result of explicit user action takes precedence in the status line docked component over tasks that are triggered by the system. (say filesystem refresh for example)

The most common usecase of the API looks like this:

ProgressHandle handle = ProgressHandleFactory.creatHandle("My custom task");
...
// we have 100 workunits
// at this point the task appears in status bar.
handle.start(100);
...
handle.progress(10);
...
handle.progress("half way through", 50);
...
handle.progress(99);
// at this point the task is finished and removed from status bar
// it's not realy necessary to count all the way to the limit, finish can be called earlier.
// however it has to be called at the end of the processing.
handle.finish();

Advanced Usage

In case your usage of the API

then you should consider using the aggregating version of APIs which is similar to the simple APIs but has distinctive differences and additions that allow for more complex scenarios.

It allows to compose the progress bar from 1+ independent sources, all sharing proportional piece of the progress bar. Additionally you can monitor the task's overall progress from one central place and possibly add more contributing sources of the progress during processing.

        // let's have a factory for client code that performs some part of the job to be done..
        Lookup.Result res = Lookup.getDefault().lookup(new LookupTemplate(MyWorkerFactory.class));
        Iterator it = res.allInstances().iterator();
        ProgressContributor[] contribs = new ProgressContributor[res.allInstances().size()];
        int i = 0;
        while (it.hasNext()) {
            MyWorkerFactory prov = (MyWorkerFactory)it.next();
            contribs[i] = AggregateProgressFactory.createProgressContributor("Module X contribution");
            MyWorker worker = prov.createWorker(contribs[i]);
            //... snip ... do something with the worker..
            i = i + 1;
        }
        AggregateProgressHandle handle = AggregateProgressFactory.createHandle("My Task", contribs, null, null);
        // non-cancellable and with out output link.
        
        // calling start() at the time when the actual long running task starts processing
        handle.start("here we go");
        // ...snip...
        // now the individual MyWorker instances log their progress.
        // possibly in other threads too..
        // ... snip...
        // 
        if (myConditionThatSpawnsAnotherContributor()) {
            ProgressContributor cont = AggregateProgressFactory.createProgressContributor("Additional exceptional contribution");
            handle.addContributor(cont);
            // ... snip ...
        }
        
        // the task is finished when all the ProgressContributors finish..

How to use Progress API - Swing?

XXX no answer for arch-what

XXX no answer for arch-usecases


How to use Search API?

This project is good for implementators of nodes to define how files under this node should be searched. For example, if you implement a custom project type, you can define which folders should be searched when the project is in the current search scope. It is also good for people who want to add a custom tab into the "Search in projects" dialog. For example, implementators of platform applications can add form with criteria for searching in a database.

Search History

SearchHistory is synchronising history content through netbeans modules and it saves history to preferences.

There are two separate histories. One for search and another for replace. When you add your propertyListener to SearchHistory - you can listen for changes in histories.

SearchHistory has methods for adding new entries and getting whole history list.

SearchInfo API & SPI

This use-case was formerly covered by module org.openidex.search.

The SearchInfo API+SPI allows other modules to specify whether and how should nodes they define be searched.

The definition is represented by objects extending class SearchInfoDefinition . To customize searching on a custom node, a SearchInfoDefinition object must be added to the node's lookup. In most cases, there is no need to define own class extending the class - one can use factory methods of class SearchInfoDefinitionFactory .

In some cases implementators may need to apply the same set of SearchFilterDefinitions in the whole subtree of a node. If so, it is not needed to put SearchInfoDefinition to all nodes' lookups, but only one instance of SubTreeSearchOptions have to be put into the lookup of the root node.

Defines abstract classes SearchInfoDefinition, SearchFilterDefinition, SubTreeSearchOptions and a factory class SearchInfoDefinitionFactory

Enhance IDE searching features

People that want to enhance IDE searching features (with custom search criteria or specialized algorithms) can add a new tab to the "Search in Projects" dialog.

They need to implement several classes:

Defines abstract classes that need to be implemented when creating custom providers: SearchProvider, SearchProvider.Presenter, SearchResultsDisplayer, SearchComposition and relative classes. Classes usually used by search providers. Contains class SearchInfo, that defines which files should be searched (it can be retrieved from methods in SearchInfoUtils, or UI component controller ScopeController), SearchListener that you should inform about events that happen during searching, and helper classes SearchInfoUtils (getting SearchInfo objects for nodes) and FileNameMatcher (filtering files by file name). Several UI components that can be used in presenters of search providers, and factory method for creating them.

Search in Projects API

This API enables other modules to open Find in Projects dialog with some pre-defined criteria and to start searching programatically.

Contains classes for controlling search, passing search criteria, and some helper classes.

How to use File Templates?

This utility standardizes the process to use files as blueprints to create new files.

Use boilerplates

An existing file can be used as a boilerplate for creation of a new file. The boiler plate can contain necessary skeleton, comments, content. As the boilerplate resides on config filesystem, it is also customizable by the user and the user can eventually develop custom templates.

In previous NetBeans versions, templating system was built into .

Custom template handlers

Often many people require ability to create a "clever" template - e.g. write piece of simple text and at the time of its processing do some advanced changes to it using either scripting or templating languages.

This traditionally used to be a bit complicated task (hacking into DataObject implementation), however since version 6.1 there are interface in DataSystem API and finally that can be registered as a services in a lookup and it is reponsible for handling the whole copy of the template file(s) to the destination folder.

Custom attributes for processing

Runtime or project-related values may be supplied by that can be registered as a services in a lookup and it is reponsible for providing "hints" - e.g. map mapping strings to various objects. and these interfaces allow anyone to extend the behaviour during creation of new files.

The CreateFromTemplateAttribute implementation knows which template is being used, where the outcome should be placed, so it can derive appropriate values for both the template and the target location.

Using Scripting and Templating Languages

There is a built in support for scripting languages in the standard NetBeans IDE. If a template is annotated with a property that can be associated to templates that either should return real instance of ScriptEngine interface or a String name of the engine that is then used to search for it in the javax.script.ScriptEngineManager. Usually the freemarker engine is the one that is supported by the NetBeans IDE - if your module wants to use it then include a token dependency OpenIDE-Module-Needs: javax.script.ScriptEngine.freemarker in your manifest file (also accessible through project customizer GUI) to indicate to the system that you need it. then the scripting engine is then used to process the template and generate the output file. While running the engine one can rely on few predefined properties:

Other properties can indeed be provided by CreateFromTemplateAttributess. After processing, the output is also sent to appropriate org.openide.text.IndentEngine associated with the mime type of the template, for formating.

Smart Templating Quick How-To
First of all create a file in your module layer located somewhere under the Templates/ folder. Make it a template by adding <attr name="template" boolvalue="true"/>. Associate this template with a scripting language, for example by <attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>. Now make sure that the scripting language integration is also available by requesting a token in standard format, for freemarker just put OpenIDE-Module-Needs: javax.script.ScriptEngine.freemarker in your manifest. This tells the NetBeans module system that a module providing integration with such scripting engine has to be enabled. Now you can use regular script language tags inside of your template file. When you write your instantiate method in your wizard, you can create a Map<String,Object> and fill it with parameters collected from your wizard and then pass it to createFromTemplate(targetFolder, targetName, mapWithParameters) . This will invoke the scripting language and make the mapWithParameters values available to it. Beyond this there is few standard parameters predefined including name, user, date, time, etc. and also additional parameters are collected from all registered CreateFromTemplateAttributesProviders.

Create sets of files

A CreateFromTemplateHandler should be able to create multiple files, one of them important so it will open after user initiates the creation action. The template of set of related files may be represented by a folder with a handler attached, and the operation deploys multiple files in the target directory.

Use HTML and JavaScript

There is a way to create a portable wizard (e.g. one that can be executed inside of NetBeans as well as in a browser). The most portable UI these days is written in HTML. To register such HTML based wizard with your file template, use @TemplateRegistration annotation and include page() attribute referencing your own HTML page:

            
            public class X {
    {@code @TemplateRegistration}(
        page = "x.html",
        scriptEngine = "freemarker",
        displayName = "JS Wizard",
        folder = "Other",
        content = "x.fmk"
    )
    public static String jsWizard() {
        return "yourInitializationCode();";
    }
}            
        
        

the return value of the annotated method (named jsWizard) should be of type String and its content should be snippet of JavaScript code to execute inside of your specified HTML page (e.g. x.html) to create an instance of KnockoutJS model to drive the wizard. Here is a sample code for the model:

            
            function yourInitializationCode() {
    var ok = ko.observable(false);
    var msg = ko.observable('');
    var current = ko.observable('Init');
    var data = {
        'errorCode': ko.computed(function() {
            if ('Init' == current()) return 0;
            if (!ok()) return 1;
            if (msg()) return 0;
            return 2;
        }),
        'current': current,
        'ok': ok,
        'msg' : msg
    }
    ko.applyBindings(data);
    return data;
}

        

The model defines wizard composed of few panels (defined in following HTML file) and a verification function (registered as errorCode) to check if everything is OK. In addition to that it defines proprietary text value msg which is going to be filled by the wizard and cannot be empty. Each page of the wizard is registered using a custom Knockout.js binding called step. Here is an HTML page defining three steps:

            <section data-bind="step: { 'id' : 'init', text : 'Initial Page'}" >
    <p>
        Write your UI in portable HTML and display it in NetBeans 
        or on web! Read more at <a href="http://wiki.netbeans.org/HtmlUIForTemplates">our wiki</a>...
    </p>
</section>

<section data-bind="step: 'info'" >
    <p>
        Use <a href="http://knockoutjs.com">knockout.js</a> bindings 
        to isolate your view model from the actual look of your HTML
        page. Bind your view to model written in Java or JavaScript.
    </p>
    <h3>Is everything OK?</h3>
    <input type="checkbox" data-bind="checked: ok"/>
    <h3>How do you feel?</h3>
    <input type='text' data-bind="textInput: msg"/>
</section>

<section data-bind="step: { 'id' : 'summary' }" >
    <p>
        You are feeling <span data-bind="text: msg"></span>!
        Let's proceed to create a file which will express your 
        feeling by using <a href="http://freemarker.org/">Freemarker</a>
        templating engine and values filled in this wizard.
    </p>
</section>

        

The Next/Finish buttons are controlled by the errorCode property. If it is non-zero, there is an error and these buttons are disabled. Also once can use that inside of the HTML page to display user related errors:

            <div data-bind="visible: errorCode() == 1">
    <span style="color: red">Please check you are OK!</span>
</div>
 
<div data-bind="visible: errorCode() == 2">
    <span style="color: red">Tell us how do you feel!</span>
</div>    

        

The L10N of the wizard is done on the level of HTML pages. The whole page gets translated into different language with appropriate suffix like x_cs.html and it is then selected instead of the default one, when user runs in such locale.

When the wizard is successfully finished, all the values specified in the model (except system ones like current, errorCode, etc.) are transfered to the templating engine, so they can influence the content of created files. Here is a sample x.fmt content which reuses the msg value provided by the wizard:

Hi,
I am Freemarker.
I feel ${wizard.msg}.    

When such file is instantiated, the ${wizard.msg} is replaced by the actual value taken from the wizard.

Use HTML and Java

Some people would rather use Java instead of Java script while getting the portability of the HTML. There is a simple way to rewrite the HTML and JavaScript sample to Java (and possibly run it in a plugin-less browser via bck2brwsr VM). Keep the same HTML, Freemarker, etc. files - just instead of encoding the logic in JavaScript use Java:

            {@link net.java.html.json.Model @Model}(className = "JavaWizard", properties = {
    {@link net.java.html.json.Property @Property}(name = "current", type = String.class),
    {@link net.java.html.json.Property @Property}(name = "ok", type = boolean.class),
    {@link net.java.html.json.Property @Property}(name = "msg", type = String.class)
})
public class JavaWizardCntrl {
    {@link net.java.html.json.ComputedProperty @ComputedProperty} static int errorCode(
        String current, boolean ok, String msg
    ) {
        if ("Init".equals(current)) return 0;
        if (!ok) return 1;
        if (msg == null || msg.isEmpty()) return 2;
        return 0;
    }
 
 
    {@code @TemplateRegistration}(
        page = "x.html",
        scriptEngine = "freemarker",
        displayName = "HTML/Java Wizard",
        folder = "Java",
        content = "x.fmk"
    )
    public static JavaWizard javaWizardFactory() {
        return new JavaWizard("Init", false, "");
    }
}            

        

The return value of the annotated method is now an HTML/Java model class which can naturally represent the essential Knockout.js objects in Java.

Selecting target location with HTML UI

It is very common that the HTML file creation wizards (either controled by JavaScript or by Java) need to allow user to specify target location of their file. To simplify such common task and to ensure its UI is consistent with the rest of the environment, one can just include following code snippet in the HTML file and leave its actual rendering on the system:

            <section data-bind="step: 'targetChooser'" >
</section>

        

Such section will then be replaced by a panel which provides appropriate UI for choosing target directory as well as name for the newly created file.

In case one prefers more Java-like chooser, it is possible to use 'targetChooser:java' as name of the step. Then all Java source groups in target project will be listed and presented in a typical Java package view selection mode. Once can use different suffix than java to list other types of source groups. This feature requires presence of org.netbeans.modules.java.project.ui module, otherwise the target chooser falls back to classical one.


How to use Visual Library API?

The Visual Library 2.0 is the next generation of the original Graph Library 1.0. It is designed for a general visualization with a support for graph-oriented modeling. Its focus is to become a part of the NetBeans platform and unify the visualization (UI and API) used in NetBeans-Platform-based applications. See http://graph.netbeans.org/ web-site for details. See documentation for complete set of use-cases and code-snippets.

See documentation for complete set of use-cases.


How to use MultiView Windows?

Multi views are general mechanism for displaying several perspectives, or views of data, which will be used consistently across whole IDE window system. Using multi views will enable modules to visually represent data document or object in unified manner at one specific place in the system, yet still allowing for different perspectives of data viewing.

There is an introduction to MultiView and its usage in its javadoc. It covers the major part of available usecases. Here is just a list of frequently asked or interesting questions slowly expanding as people ask them:

MultiView faq:

How does serialization work?

Q: How does serialization of multiviews work and what needs to be serializable?

First of all, you don't need to worry about serialization if all your MultiViewDescription instances contained in the multiview state to be non serializable. Meaning they all return TopComponent.PERSISTENCE_NEVER in MultiViewDescription.getPersistenceType().

If at least one of the views requires serialization, you have no choice but to make all MultiViewDescription implementors serializable. You also can persist the MultiViewElement instances that the multiview contains. The algorithm here is a bit complicated for performance reasons. Only those Elements are stored that were created during the session and which are Serializable. So if the user never switches to the 4rd tab, and it's corresponding element and visual component never get created, then it won't be stored. (We would have to create it just for the sake of persistance). So if your visual component needs some inital context for creation, you should store it in the description instance, and if the visual component wants to store it's state (location of cursor, selected field, something else that makes sense for the opened component) you should store it in the MultiViewElement. So basically if you are always able create the Element from Description without any persisted data, you don't need to persist anything.

If you define your own CloseOperationHandler implementation for the multiview component, then you also ought to define it Serializable. Otherwise it will be silently replaced by the default handler on restoration of the multiview component.

How to set the display name?

Q: How do I set the display name for the multiview component?

Each MultiViewDescription defines display name and icon. While the icon is meant for the whole document/view tab, the display name is just for the inner switching button. So how does one set the name for the whole MultiView component? It can be done when creating the component.

    TopComponent mvtc = MultiViewFactory.createMultiView(myDescriptions);
    mvtc.setDisplayName("My static mvtc displayName");

Later in the lifecycle of the component, it can be also influenced from within the individual multiview visual elements using the MultiViewElementCallback.updateTitle() method.


How to use UI Handler Library?

XXX no answer for arch-what

XXX no answer for arch-usecases


How to use Auto Update Services?

org.netbeans.api.autoupdate org.netbeans.spi.autoupdate

Browse all available units

Give overview of IDE installation to users, it involve overview of installed modules (grouped together as feature), overview of available updates, overview of available new features. The API can return list of UpdateUnit which describes all instances of unit, e.g. installation in IDE, all its available updates, optionlly its backup instance. UpdateUnit can represent either a feature (e.g. group of modules), a single module or a localization.

Proposed usage of API: Call List<UpdateUnit> UpdateManager.getDefault().getUpdateUnits()

Browse all units by chosen style (e.g. modules, features, localization)

Sometimes there can be a need to get overview of units by chosen style, e.g. feature, module or localization.

Proposed usage of API: Call List<UpdateUnit> UpdateManager.getDefault().getUpdateUnits(UpdateStyle style)

Browse installed modules

When an API client needs to get overview of installed modules.

Proposed usage of API: Call List<UpdateUnit> UpdateManager.getDefault().getUpdateUnits(UpdateStyle style) and filter units which haven't been installed yet.

Search for new functionality

Someone is searching for some functionality which can be installed into IDE. It needs a set of available UpdateUnits which are applicable to active IDE. UpdateManager will search all available UpdateUnit given attribute.

Install new functionality

An client needs to install new functionality into the IDE installation. She knows what unit and what version wants to install. Needs to identify if the functionality is ready to install, resolve its dependencies, identify possible problems and locate other unit what have to be installed together with asked functionality.

Proposed usage of API:

Update of installed unit

A client needs to update some unit of functionality which is already installed. She knows what unit and what update element (by version) wants to install. Needs to identify possible problems with update install, resolve its dependencies, identify possible problems and locate other unit what have to be installed together with asked functionality.

Proposed usage of API: See above Install new functionality

Uninstall functionality

An client needs to uninstall some functionality from IDE installation. She knows what unit wants to uninstall. Needs to identify if the functionality is ready to uninstall, resolve its dependencies, identify possible problems and locate other unit what will be disabled together.

Proposed usage of API:

Switch off functionality

An client needs to switch off (disable) some functionality in IDE installation. Needs to resolve its dependencies, identify possible problems and locate other unit what will be disabled together.

Proposed usage of API:

Switch on functionality

Like Switch off functionality An client needs to switch on (enable) some functionality in IDE installation.

Rollback of previous update

Sometimes an client needs to rollback of installed update of unit to previous version. Needs to resolve its dependencies, identify possible problems and locate other unit what are affected by rollback.

Proposed usage of API: Like above Switch off functionality

Resolve problems what accrued while processing operation

OperationContainer and OperationInfo identifies some problems, i.e. broken dependencies, needs to install more units, the operation causes disable some other modules and so on. The client can use this information to consult these with end-user.

Make IDE up-to-date

Sometimes need to make whole IDE installation up-to-date. Find all available updates of installed units and install the latest available version. It is covered by previous use-cases.

Get all subscriptions to Update Center

Show me all registered subscriptions to Update Center, e.g. get me list of UpdateUnitProvider. Proposed usage of API: Call UpdateUnitProviderFactory.getUpdateUnitProviders()

Subscribe new Update Center

If there is a new Update Center which is not already subscribed into IDE user wants to subscribe new one Update Center which will be connected from that time in periodically checks. There should be a factory where subscribe new one Update Center, known types of Update Center have own factory method. Proposed usage of API: Simply call UpdateUnitProviderFactory.create() which creates and registered new one subscription in the system and will be used from that time in the future.

Customization of Update Center subscription

An user wants to enable or disable of Update Center subscription. Proposed usage of API: Simply call UpdateUnitProviderFactory.setEnable(UpdateUnitProvider, boolean).

Unsubscribe of some Update Center

Simple unsubscribe a chosen Update Center from the system. Need to know of chosen Update Provider Id. This Update Center won't be checked anymore. Proposed usage of API: Simply call UpdateUnitProviderFactory.remove(Id).

Refresh content of subscribed Update Center

The content of Update Provider is cached and the system works across there caches. There is a cache per each Update Center subscription. The caches are refreshed periodically by the system. But, sometime an user wants to call refresh manually. Proposed usage of API: Simply call UpdateUnitProvider.refresh().

Specify the cluster where to install

TBD

Get all installed files of given unit

TBD


How to use Auto Update UI?

AutoUpdateUI

Download and Install

Primary purpose of the API is to share classical UI for downloading and installing additional modules. Read about PluginManager.openInstallWizard.

How to use MIME Lookup API?

Each editor provides an EditorKit which controls the policy of specific MIME content type. The policy of content type should be easily registered and found via some lookup mechanism, that will provide convenient way of using it either for kit provider or base editor infrastructure. In addition to this, the policy can be inherited, (e.g. in case of embeded kits like JSP) and the content types need to be merged in this case. MIME Lookup API should provide all mentioned requierements via easy lookup query, so content type policy user need not to solve this searching and merging on its own side.

Per mime-type operation

Operation of the editor module must be parametrized by the type of the file being edited. In the past the operation was parametrized by the class of the editor kit but that did not show up as being useful enough.
It is more practical to use a string-based parametrization concretely the mime-type. Anyone can then easily register an additional functionality for the editor because it's just enough to know the right mime-type and the type of the functionality class to be implemented and the xml layer folder where the class should be registered.

Provide list of instances as lookup result

On the modules' implementation side the registered functionality must be retrieved somehow. It's necessary to instantiate the registered objects and react to module enabling/disabling which can affect validity of the registered objects.
As the most convenient solution appears to use org.openide.util.Lookup allowing to provide the registered instances as a Lookup.Result allowing to listen for changes (e.g. caused by the module enabling/disabling).
This resulted into creation of class MimeLookup extends Lookup containing static MimeLookup getMimeLookup(String mimeType).

Nested mime-types

On the lexical level the document can contain nested languages.
For example JSP document can contain pieces of java code which can further contain javadoc comment tokens with nested javadoc language.
The nested languages should allow for special settings such as fonts and colors of nested syntax coloring but even things like actions that would be active in the nested document section.
This resulted into creation of static Lookup getLookup(MimePath mimePath) method in MimeLookup.

Known clients summary

Fold Manager Factories
The editor/fold module expects to find the registered fold manager factories (org.netbeans.spi.editor.fold.FoldManagerFactory classes).

Completion Providers
The editor/completion module expects to find the registered completion providers (org.netbeans.spi.editor.completion.CompletionProvider classes).

Editor Context Menu Actions
The editor module expects to find the registered popup menu actions (javax.swing.Action classes or names of actions (i.e. value of Action.NAME attribute) present in editor kit e.g. "goto-source").

Side Bars
The editor/lib module expects to find factories for components to be placed on the sides of the editor component (org.netbeans.editor.SideBarFactory classes).

Hyperlink Providers
The editor/lib module expects to find hyperlink providers that allow connecting an open document with some other documents (org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider classes).

Code Template Processors
The editor/codetemplates module expects to find factories for code template processors (org.netbeans.lib.editor.codetemplates.spi.CodeTemplateProcessorFactory classes).

Hints Providers
The editor/hints module expects to find editor hints providers (org.netbeans.modules.editor.hints.spi.HintsProvider classes).


API Use Cases

Find class instances for the given mime-type

An API method

MimeLookup lookup = MimeLookup.getMimeLookup("text/x-java");

can be used for getting the mime specific lookup. Having this we can lookup class or template:

Object obj = lookup.lookup(LookedUpClass.class);

or

Lookup.Result result = lookup.lookup(new Lookup.Template(LookedUpClass.class));

Getting embeded mime-type specific Lookup

As an example a jsp scriptlet is used. Scriptlet in fact consists of parent "text/x-jsp" mime-type and embeded "text/x-java" mime-type. To obtain a scriptlet lookup firstly we need to get a MimePath and then get appropriate lookup:

    MimePath scriptletPath = MimePath.parse("text/x-jsp/text/x-java");
    Lookup lookup = MimeLookup.getLookup(scriptletPath);

SPI Use Cases

Providing implemented MimeLookupInitializer

It is the general way of adding mime specific object into the MimeLookup. Implementation of MimeLookupInitializer should be created and registered to default lookup via META-INF/services registration. For details, please look at the simplified TestMimeLookupInitializer in mimelookup/test/unit or LayerMimeLookupInitializer. Usage of MimeLookupInitializer is deprecated, please use MimeDataProvider instead in similar way

How to use Keyring API?

XXX no answer for arch-what

XXX no answer for arch-usecases


How to use Options Dialog and SPI?

This module contains implementation of Options Panel and simple SPI.

Register top level Options Panel

Client can install new panel to Options Dialog - see JavaDoc for OptionsCategory class.

Register panel to Advanced Options Panel

Client can install new panel to Advanced Options Panel - see JavaDoc for AdvancedOption class.


How to use Print?

Provides print functionality in NetBeans.

The typical client of Print module can be any tool to print custom data.

The simple way to enable printing for a custom data is:

If the data is a Swing component which extends javax.swing.JComponent and shown in a org.openide.windows.TopComponent, the key "print.printable" (PrintManager.PRINT_PRINTABLE) with value "Boolean.TRUE" in the component must be set as a client property. See example:

      public class MyComponent extends javax.swing.JComponent {
        public MyComponent() {
          ...
          putClientProperty("print.printable", Boolean.TRUE); // NOI18N
        }
        ...
      }

How to use General Queries API?

General kinds of queries between modules. Queries are one way of solving the intermodule communication problem when it is necessary for some modules to obtain basic information about the system (e.g. whether a particular file is intended for version control) without needing direct dependencies on the module providing the answer (e.g. the project type which controls the file). Details are covered in the Javadoc.

Particular use cases are enumerated in the Javadoc for each query API. Usage consists of simple static method calls. Potentially a wide variety of modules could use these queries; implementations are typically registered by project type providers, though also by Java library and platform implementations.


How to use Command Line Parsing API?

GetOpts like infrastructure to parse command line arguments with the cooperative participation of various modules.

Just Parse the Command Line

There needs to be a simple API for someone who has an array of strings and wants to parse them. One does not need to search for providers, just ask the infrastructure to do the parse and get the result.

The correct way to achieve this is to call CommandLine.getDefault().process(args).

Parse the Command Line with Own Options

Since version 2.20 one can define own classes with fields and annotate them with @Arg annotation. Those classes can then be passed into a factory method that creates new command line. One can then process the arguments as many times as needed via the process method. Example:
                public final class MyOption implements Runnable {
  @Arg(longName="hello")
  public String name;

  public void run() {
    System.out.println("Hello " + name + "!");
  }
  
  public static void main(String... args) {
    CommandLine line = CommandLine.create(MyOption.class);
    line.process(args);
  }
}

            

If the above main class is called with parameters --hello World it will print out Hello World!.

Short and Long options with or without an argument

The standard getopts supports short form of options - e.g. a dash followed with one letter - or long form using two dashes followed with a word. Moreover the long form is optimized for abbrevations. If there are no conflicts between multiple options, then one can only use double dash followed with a prefix of a long option.

When using the declarative annotation style one can always specify @Arg(longName="text", shortName='t'). The longName attribute is required, but if there is supposed to be no long version of the argument, it can be set to empty string.

One can create an Option by calling any of its factory methods (like withoutArgument) and provider char for the one letter option and/or string for the long getopts option.

Options with or without an argument

There are three types of options. Those without an argument, those with a required one and those with optional one. Each one can be created by appropriate factory method in the Option class.

When using the declarative annotation style one needs to annotate a field of type boolean to create an option without an argument.

Support for --

The getopts compliant command line parsers support --. If these characters do appear on the command line, the rest of it is treated as extra arguments and not processed. The sendopts infrastructure supports this as well.

Multiple Independent CLI Handlers

The handlers for the options need not know about each other and still have to be able to process the command line successfully. Any module which wishes to provide its own options can register its OptionProcessor with @ServiceProvider annotation. Alternatively the module can use the @Arg annotation of its fields and it will be registered as well.

Extensible Options Set

Q: How shall one write an OptionProcessor that recognizes set of basic options, however contains one open slot? The processor wants other modules to provide recognizers for that slot and wants to communicate with them. For example, by default the processor recognizes option --channel <name_of_the_channel> which describes a source of data, and stores such data into a sink. There can be multiple sinks - discard the output, save it to file, show it on stdout, stream it to network. The processor itself can handle the copying of data, but does not itself know all the possible sink types.

To implement OptionProcessor like this one shall define an additional interface to communicate with the sink providers:

   package my.module;
   public interface SinkProvider {
     /** gets the option (even composite) that this sink needs on command line */
     public Option getOption();

     /** processes the options and creates a "sink" */
     public OutputStream createSink(Env env, Map<Option,String[]> values) throws CommandException;
   }
       

Other modules would then registered implementations of this interface in the META-INF/services/my.module.SinkProvider files. The OptionProcessor itself would just look all the implementations up, queried for the sinks, and then did the copying:

                   class CopyingProvider extends OptionProvider {
     public Option getOption() {
        List<Option> l = ...;
        for (SinkProvider sp : Lookup.getDefault().lookupAll(SinkProvider.class)) {
          l.add(sp.getOption());
        }

        // we need only one provider to be present
        Option oneOfSinks = OptionGroups.oneOf(l.toArray(new Option[0]));

        // our channel option
        Option channel = ...;

        // the channel option needs to be present as well as a sink
        return OptionGroups.allOf(channel, oneOfSinks);
     }

     public void process(Env env, Map<Option,String[]> values) throws CommandException {
        OutputStream os = null;
        for (SinkProvider sp : Lookup.getDefault().lookupAll(SinkProvider.class)) {
          if (values.containsKey(sp.getOption())) {
            os = sp.createSink(env, values);
            break;
          }
        }
        if (os == null) {
          throw CommandException.exitCode(2);
        }

        // process the channel option and
        // handle the copying to the sink os
     }
   }
       
            

Another possible approach how to allow sharing of one option between multiple modules is to expose the option definition and its handling code as an interface to other modules, and then let the modules to write their own OptionProcessors. Necessary condition is that each of the processor is uniquely identified by some additional option, so when the shared option appears the infrastructure knows which processor to delegate to. This is demonstrated in the SharedOptionTest which basically does the following:

   /** the shared option, part of an interface of some module */
   public static final Option SHARED = ...;
   /** finds value(s) associated with the SHARED option and 
   * creates a JPanel based on them */
   public static JPanel getSharedPanel(Map<Option,String[]> args) { ... }
       

Then each module who wishes to reuse the SHARED option and the factory method that knows how to process their values for their own processing can just:

  public static final class ShowDialog extends OptionProcessor {
    private static final Option DIALOG = Option.withoutArgument('d', "dialog");

    protected Set<Option> getOptions() {
        // the following says that this processor should be invoked
        // everytime --dialog appears on command line, if the SHARED
        // option is there, then this processor wants to consume it 
        // as well...
        return Collections.singleton(Option.allOf(DIALOG, Option.anyOf(SHARED)));
    }

    protected void process(Env env, Map<Option, String[]> optionValues) throws CommandException {
        JPanel p = getSharedPanel(optionvalues);
        if (p == null) {
           // show empty dialog
        } else {
           // show some dialog containing the panel p
        }
    }
  }
       

The other modules are then free to write other processors refering to SHARED, for example one can write ShowFrame that does the same, just shows the panel in a frame, etc. The infrastructure guarantees that the exactly one provider which matches the command line options is called.

Printing Full Help Text

Althrough the handlers are provided by independent parties, it must be possible to generate resonable and consistent help description from all of them, so for the end user it appears as well formated and easily understandable. That is why every option can be associated with a short description providing info about what it is useful for using Option.shortDescription method. When using the @Arg style, there is an additional @Description annotation which can be used to declaratively associate a localized display name and short description with the option. To get such descriptions for all available options one can use CommandLine.getDefault().usage(java.io.PrintWriter).

Finding and Reporting when Options Are Not Correct

In case the command line cannot be processed a clean error for programmatic consumation and also one that can be shown to the end user of the command line must be given. This is handled by throwing CommandException with appropriate message description and exit code.

Processing Extra Command Line Arguments

There can be non-option arguments in the command line and they can freely mix with the option ones. For example the getopts would treat the following command line arguments as the same:
       --open X.java Y.java Z.txt
       X.java Y.java --open Z.txt
       
if the option open handles extra arguments. The sendopts infrastructure must distinquish between them and pass the non-option ones to the only one handler (active because it processed an option) that knowns how to parse them. It is an error if more than one or no handler expresses an interest in extra arguments and those are given. One can register such option by using the Option.additionalArgument factory method.

When using the declarative annotation style one may annotate a field of type String[] which then means this field should be filled with all additional arguments.

Handling Input and Output

Handler's shall not use the input and output streams directly for their execution, they should rely on the framework provided ones. This allows NetBeans based application to transfer the I/O from second started instance to the master one which is already running. From the client side there is the CommandLine.getDefault().parse methods taking additional arguments like input and output streams. This gets transfered to providers as an Env argument of their methods.

Returning Exit Code

When Handler's get execute (in the order defined by the order of options on the command line), each of them can either execute successfully, or fail. If a handler succeeds, next one is executed, if it fails, the execution is terminated and its return code is returned to the caller. The error can be notified by creating and throwing CommandException.exitCode(int errorCode).

Processing Only Extra Command Line Arguments

Sometimes it is desirable to process non-option arguments like file names without providing any option. Handlers can declare interest in such arguments. It is an error if such non-options are provided and no or more than one handler is around to handle them. One can create such option by using Option.defaultArguments factory method. With the declarative annotation style one can annotate a field of type String[] and specify that it is supposed to be implicit.

Only those processor need to process the options are created

For purposes of usage in NetBeans, it is needed to not-initialize those handlers that are not really needed to process certain command line. The infrastructure decides which of them are going to be needed and instantiates only those. This is supported only when using the declarative annotation style - information about these options is recorded in declarative way and the system can decide without loading the provider classes whether they are present on the command line or not.

Complex Option Relations

Certain CLI processors may need more than one option before they can process the input. For example it is necesary to tune the radio and then also tell what to do with the output. It is unconvenient to process that as one option with argument(s), that is why one can use the OptionGroups.allOf, OptionGroups.someOf, for example like:
                class PP extends OptionProcessor {
    private static Option tune = Option.requiredArgument(Option.NO_SHORT_NAME, "tune");
    private static Option stream = Option.requiredArgument(Option.NO_SHORT_NAME, "stream");
    
    public Set<Option> getOptions() {
      return Collections.singleton(
        OptionGroups.allOf(tune, stream)
      );
    }
    
    public void process(Env env, Map>Option,String[]> values) throws CommandException {
        String freq = values.get(tune)[0];
        String output = values.get(stream)[0];

        // XXX handle what is needed here
    }
}

            
When the two options are registered and command line like --tune 91.9 --stream radio1.mp3 is being processed, the PP's process method is going to get called with values 91.9 and radio1.mp3.

This kind of grouping is not currently supported with the declarative annotation style registration.

Alternative Options

Sometimes there may different ways to specify the same option and just one of them or none of them can be provided at given time. For example is there is a way to tune the radio with direct frequency or with name of the station. Just one can be provided and one is needed. This can be specified by using OptionGroups.oneOf factory methods:
Option freq = Option.requiredArgument(Option.NO_SHORT_NAME, "tune");
Option station = Option.requiredArgument(Option.NO_SHORT_NAME, "station");
Option tune = OptionGroups.oneOf(freq, station);    
The option tune then signals that just one of the station or freq options can appear and that they both are replaceable.


How to use UI Gestures Collector Infrastructure?

XXX no answer for arch-what

Gather information about UI gestures

Primary purpose of this module is collect information about the user actions that take place in the running NetBeans based application.

The info about various UI events in the system is collected thru listening on log records send to Logger.getLogger(UI_LOGGER_NAME_VALUE) , where UI_LOGGER_NAME_VALUE is a value of UI_LOGGER_NAME resource bundle key, defining the name of the UI usage logger. Any code in the system can get instance of this logger or any child logger and send useful informations to it. At the end of the session the last few hundereds events is taken and displayed to the user for further processing. The info about various UI events in the system is collected thru listening on log records send to Logger.getLogger(METRICS_LOGGER_NAME_VALUE) , where METRICS_LOGGER_NAME_VALUE is a value of METRICS_LOGGER_NAME resource bundle key, defining the name of the metrics logger. Any code in the system can get instance of this logger or any child logger and send useful informations to it. At the end of the session the last few hundereds events is taken and displayed to the user for further processing.

Presenting usage statistics

Important part of the behaviour of this module is the ability to cooperate with information analyzing tools and present their results. This is done thru special HTTP contracts, where the module reads and understands various server responses and is able to open browser after submitting data to analysis.

There is a key in the org.netbeans.modules.uihandler.Bundle that specifies the location of the page on a server one shall query and display to the user when the module is about the submit usage data for analysis. There is a key in the org.netbeans.modules.uihandler.Bundle that specifies the location of the page on a server one shall query and display to the user when the module is about the submit metrics data for analysis. There is a key in the org.netbeans.modules.uihandler.Bundle that specifies the location of the page on a server one shall query and display to the user when the module is about the submit an error report. The page pointed by WELCOME_URL can contain any XHTML text, but it also should contain a <form/> tag that defines <input type="hidden" name="submit" value="localizedName"/>. The localizedName is then going to be used for a button for the dialog displaying the summary. When this button is invoked, the "action" URL is then feed with data from the UI logs. The server is then supposed to process the data, create some analytics pages and return them back to the client. If the returned page contains tag like <meta http-equiv='Refresh' content='3; URL=somepage'> an (external) browser is opened with the specified URL and the user can then interact directly with the server, thru pages it serves. For testing purposes one can specify different URL for upload of files, by setting org.netbeans.modules.uihandler.Submit property when invoking NetBeans.

Adding own UI gestures

The base module is in fact just an infrastructure which collects data about UI gestures, but the actual gestures need to be delivered to it somehow. Here is the description of the ways how one can extend own modules to cooperate with this UI gestures infrastructure.

To feed own data about special UI gestures one can just create own Logger.getLogger(UI_LOGGER_NAME_VALUE+".ownname") and send own log records to it. UI_LOGGER_NAME_VALUE is a value of UI_LOGGER_NAME resource bundle key, defining the name of the logger. The format of the log messages shall follow the one described by the structured logging document, e.g. the LogRecord shall have associated ResourceBundle and the record's getMessage shall point to a key in that bundle. there is an extension to the regular formatting done by the logging formatter that, in order to achieve nicer appearance to the user, allows each record to be associated with an icon. Just define MSG_KEY_ICON_BASE in the bundle associated with the LogRecord (where the MSG_KEY is the string returned by record.getMessage()) and the value is then going to be used for the Node representing the UI gesture.

Sometimes direct logging may not be possible. For example for performance data it might be meaningful to collect the information over a longer time period and only at the end output some statistics. This is supported as well. Just implement and register one of the interfaces from the API of this module and properly register them and the implementation will be called when the logger module is activated or when the user finishes the work with the application. In order to keep dependencies clean, it is strongly adviced to make modules that implement this API eager, so they get enabled as soon as the UI logger module is enabled.

These usecases are realized as described in here in provided UI specification.


How to use Quick Search API?

QuickSearch API and its implementations provides way for end user to learn system earlier and easier and also to find various things in the system more quickly, conveniently and in standard way. Main project page is on nb wiki, http://wiki.netbeans.org/QuickSearch

How To Add New Quick Search Provider

In order to plug in a new Quick Search provider and new category of results, module writers need to complete following steps:
1. Implement SearchProvider
2. Register SearchProvider implementation in xml layer
Register your SearchProvider implementation in your module's xml layer file under main "/QuickSearch" folder. Registration xml syntax is following:
              <folder name="QuickSearch">
                  <folder name="Category1_ID">
                      <attr name="position" intvalue="300"/>
                      <file name="org-netbeans-module1-package1-Provider1Impl.instance"/>
                  </folder>
                  <folder name="Category2_ID">
                      <!--Attribute for localization - provide localized display name of category!-->
                      <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.yourmodule.YourBundle"/>
                      <!--Attribute for command prefix - used to narrow search to this category only!-->
                      <attr name="command" stringvalue="p"/>
                      <!--Attribute for category ordering!-->
                      <attr name="position" intvalue="200"/>
                      <!--Note that multiple providers can contribute to one category!-->
                      <file name="org-netbeans-module2-package2-Provider2Impl.instance"/>
                      <file name="org-netbeans-module2-package3-Provider3Impl.instance"/>
                  </folder>
              </folder>
            
Syntax explanation:

How To Share Category Of Results

Quick Search UI shows search results divided into visually separeted sections, called categories. Several SearchProvider implementations may decide to display their results in one shared category of results in Quick Search UI.

In order to share category, module writers have to agree on shared category and its properties, especially its name. It means that all providers (possibly in different NetBeans modules) need to be registered under the same folder, as shown below:

Provider 1
Provider 1 is category "owner", which defines properties of SharedCategory such as display name, position and command prefix.
              <folder name="QuickSearch">
                  <folder name="SharedCategory">
                      <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.yourmodule.YourBundle"/>
                      <attr name="command" stringvalue="p"/>
                      <attr name="position" intvalue="200"/>
                      <file name="org-netbeans-module1-package1-Provider1Impl.instance">
                          <attr name="position" intvalue="300"/>
                      </file>                          
                  </folder>
              </folder>
            
Provider 2
Other providers from other modules are sharing category with Provider 1. Provider 2 does not define properties of SharedCategory, as they were already defined by Provider 1. Note that module dependency on the module of Provider 1 is needed to ensure that SharedCategory is fully defined.
              <folder name="QuickSearch">
                  <folder name="SharedCategory">
                      <file name="org-netbeans-module2-package2-Provider2Impl.instance"/>
                          <attr name="position" intvalue="200"/>
                      </file>                          
                  </folder>
              </folder>
            
Provider 3
The same rules apply like for Provider 2. Note that position attribute can be used to control position of provider's results in shared category. Results from provider with lowest position will go first and so on.
              <folder name="QuickSearch">
                  <folder name="SharedCategory">
                      <file name="org-netbeans-module2-package3-Provider3Impl.instance"/>
                          <attr name="position" intvalue="100"/>
                      </file>                          
                  </folder>
              </folder>
            

How To Define and Modify Order of Categories

Order of categories of results can be set by using "position" attribute of category xml folder definition. Following example will result in FirstCategory to be first, and SecongCategory to be second :), which means that FirstCategory and its results will be displayed above Secondcategory in QuickSearch results window.
              <folder name="QuickSearch">
                  <folder name="SecondCategory">
                      <attr name="position" intvalue="300"/>
                      ...
                  </folder>
                  <folder name="FirstCategory">
                      <attr name="position" intvalue="200"/>
                      ...
                  </folder>
             </folder>
            

How To Hide Recent Searches Results and Others

"Recent Searches" provider is contained directly in spi.quicksearch module, so its functionality is automatically always available by default. However, if your module wants to disable "Recent Searches" or any other category, follow the steps below:
Define module dependency
Your module have to depend on module where provider you want to disable is contained. In case of "Recent Searches" provider, it's spi,quicksearch, on which you probably already depend.
Disable provider using "_hidden"
For example, to disable "Recent Searches" provider, write into your layer:
              <folder name="QuickSearch">
                  <folder name="Recent_hidden">
                  </folder>
              </folder>
           
"Recent" is a name of category for "Recent Searches" provider and by appending "_hidden" suffix you are telling system to "hide" it. This technique can be used also to disable invidual search providers.

How To Use Quick Search in Platform Application

Quick Search UI is disabled by default in application built on top of NetBeans platform. To enable Quick Search feature in your application, complete following steps:
1. Write XML layer registration
Add the following lines to XML layer of some of your modules in your application suite:
        <folder name="Toolbars">
            <folder name="QuickSearch">
            <attr name="SystemFileSystem.localizingBundle" stringvalue="com.myapp.mymodule.MyBundle"/>
                <file name="org-netbeans-modules-quicksearch-QuickSearchAction.shadow">
                    <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-quicksearch-QuickSearchAction.instance"/>
                </file>
            </folder>
        </folder>
        
2. Localize Toolbar Name
Replace com.myapp.mymodule.MyBundle in the xml registration above with path to your properties file, in which you'll define localized name of Quick Search toolbar:
                Toolbars/QuickSearch=Quick Search
             

By default, providers for searching in actions and recent searches will be enabled. Web search provider is disabled by default, see use case below for info how to turn it on.

How To Add a Default Web Search Provider

There is a default implementation of web search provider which uses Google to search for the given text on the web. Simply add the following lines to your XML layer to enable this search provider in your application:
          <folder name="QuickSearch">
              <folder name="WebSearch">
                  <!--Attribute for localization - provide localized display name of category!-->
                  <attr name="SystemFileSystem.localizingBundle" stringvalue="com.myapp.mymodule.MyBundle"/>
                  <!--Attribute for command prefix - used to narrow search to this category only!-->
                  <attr name="command" stringvalue="g"/>
                  <!--Attribute for category ordering!-->
                  <attr name="position" intvalue="200"/>
                  <!--Note that multiple providers can contribute to one category!-->
                  <file name="org-netbeans-modules-quicksearch-web-WebQuickSearchProviderImpl.instance"/>
              </folder>
          </folder>
        
You can also add branding for org.netbeans.modules.quicksearch.web Bundle to restrict the search to a particular site only:
            quicksearch.web.site=mywebsite.com
        
And you can also restrict the search to some parts your website only:
            quicksearch.web.url_patterns=mywebsite.com/docs,mywebsite.com/files/tutorials
        

How to customize Look&Feel properties

If you need to adjust border of the Quick Search component for your Look&Feel, you can put a Border instance into UIManager under key nb.quicksearch.border.


How to use Actions APIs?

Actions provides system of support and utility classes for 'actions' usage in NetBeans.

First see the API description. Here is just a list of frequently asked or interesting questions slowly expanding as people ask them:

Actions faq:

How to define configurable Shortcut for Component based shortcut?

Q: The usual Swing way of defining Actions for your component is to create an Action instance and put it into the Input and Action maps of your component. However how to make this Action's shortcut configurable from the Tools/Keyboard Shortcuts dialog?

In order for the action to show up in Keyboards Shortcut dialog you need the action defined in the layer file under "Actions" folder and have the shortcut defined there under "Keymaps/<Profile Name>" linking to your action.

    <folder name="Actions" >
        <folder name="Window">
            <file name="org-netbeans-core-actions-PreviousViewCallbackAction.instance"/>
        </folder>
    </folder>

    <folder name="Keymaps">
        <folder name="NetBeans">
            <file name="S-A-Left.shadow">
                <attr name="originalFile" stringvalue="Actions/Window/org-netbeans-core-actions-PreviousViewCallbackAction.instance"/>
            </file>
        </folder>
    </folder>

The mentioned Action has to be a subclass of org.openide.util.actions.CallbackSystemAction. It does not necessarily has to perform the action, it's just a placeholder for linking the shortcut. You might want to override it's getActionMapKey() and give it a reasonable key.

The actual action that does the work in your component (preferably a simple Swing javax.swing.Action) is to be put into your TopComponent's ActionMap. The key for the ActionMap has to match the key defined in the global action's getActionMapKey() method.

        getActionMap().put("PreviousViewAction", new MyPreviousTabAction());

This way even actions from multiple TopComponents with the same gesture (eg. "switch to next tab") can share the same configurable shortcut.

Note: Don't define your action's shortcut and don't put it into any of the TopComponent's javax.swing.InputMap. Otherwise the component would not pick up the changed shortcut from the global context.


How to use UI Utilities API?

The org.openide.awt provides API/SPI for UI related aspects of application.

Cover of NetBeans Platform for Beginners book For general overview of the concepts of NetBeans action system and related UI elements, together with code samples, see chapter 5, of NetBeans Platform for Beginners by Jason Wexbridge and Walter Nyland.


How to use Dialogs API?

The DialogsAPI allows creating a user notification, a dialog's description and also permits it to be displayed. The wizard framework allows create a sequence of panels which leads a user through the steps to complete any task. This API is part of package org.openide.

There is a Wizard Guide Book providing the introductionary information, moreover here is a list of frequently asked questions and their answers:

How to change the title of a wizard?

Q: Although none of my panels have names set (using setName() method) and the method name() in the WizardDescriptor.Iterator returns an empty string, I'm getting "wizard ( )" as the title of each panel in my wizard. When I set the name of the panel and return a string from the method name() I get: "panelName wizard (myName)". The wizard steps are labeled correctly, it just the panel title/name that looks like it adds "wizard ()" to any of my panels. I don't mind the "( )", but I would like to rid of the word "wizard".

A: You can change the format of your wizard's title by WizardDescriptor.setTitleFormat(MessageFormat format) and rid of 'wizard' word in the default wizard's title.


How to use Explorer & Property Sheet API?

The ExplorerAPI is build around Explorer - solely a user-interface device: it has no particular knowledge of the structure of the IDE. Rather, it provides the physical user interface for the Node hierarchy, as described in the NodesAPI. A given Explorer instance will be some visual component (such as a Swing panel) displaying some representation of a subtree of the complete Node hierarchy; the topmost node being displayed is said to be the root of the Explorer. Be careful not to confuse the root of a particular Explorer instance, which is selected according to what the user wishes to see, with the root(s) of the entire Node hierarchy, which generally are fixed.

Cover of NetBeans Platform for Beginners book For general overview of the concepts related to nodes and explorers, together with code samples, see chapter 7, of NetBeans Platform for Beginners by Jason Wexbridge and Walter Nyland.


How to use File System API?

The Filesystems API provides a common API to access files in a uniform manner. It is available as standalone library and also is bundled together with other parts of the openide. Specification

Cover of NetBeans Platform for Beginners book For general overview of the filesystem concepts, related topics, together with code samples, see chapter 3, of NetBeans Platform for Beginners by Jason Wexbridge and Walter Nyland. Many of the usecases are described at the overall documentation, in a way how to register a mime type. Some of the additional usecases are covered here.

How to change menus, etc. after login?

See documentation about dynamically changing the system filesystem.


How to use I/O APIs - Swing?

The Input/Output API is a small API module which contains InputOutput and related interfaces used in driving the Output Window. The normal implementation is org.netbeans.core.output2.

There is an SPI but additional implementations are not expected. The API is most important.

Simple usage example:

            
            InputOutput io = IOProvider.getDefault().getIO("My Window", true);
io.select();
OutputWriter w = io.getOut();
w.println("Line of plain text.");
OutputListener listener = new OutputListener() {
    public void outputLineAction(OutputEvent ev) {
        StatusDisplayer.getDefault().setStatusText("Hyperlink clicked!");
    }
    public void outputLineSelected(OutputEvent ev) {
        // Let's not do anything special.
    }
    public void outputLineCleared(OutputEvent ev) {
        // Leave it blank, no state to remove.
    }
};
w.println("Line of hyperlinked text.", listener, true);

        

How to use Datasystems API?

In summary, the LoadersAPI is responsible for scanning files in a directory on disk, weeding out irrelevant files of no interest to the IDE, and grouping the rest into logical chunks, or just determining what type of data each represents. It does this scanning by asking each registered data loader whether or not the given file(s) should be handled. The first loader to recognize a file takes ownership of it, and creates a matching data object to represent it to the rest of the IDE.

A lot of usecases is described in the javadoc. Here is the list of some faqs:

Using Scripting and Templating Languages

Often many people require ability to create a "clever" template - e.g. write piece of simple text and at the time of its processing do some advanced changes to it using either scripting or templating languages.

This traditionally used to be a bit complicated task, however since version 6.1 there are new interfaces can be registered as a services in a lookup and it is reponsible for handling the whole copy of the template file(s) to the destination folder. and can be registered as a services in a lookup and it is reponsible for providing "hints" - e.g. map mapping strings to various objects. and these interfaces allow anyone to extend the behaviour during creation of new files without writing new DataLoader and co.

The support was moved to a new module; please see api.templates module for more information.

How to add action to folder's popup menu?

The actions that the default folder loader shows in its popup menu are read from a layer folder Loaders/folder/any/Actions so if any module wishes to extend, hide or reorder some of them it can just register its actions there. As code like this does:
    <folder name="Loaders" >
        <folder name="folder" >
            <folder name="any" >
                <folder name="Actions" >
                    <file name="org-mymodule-MyAction.instance" >
                        <attr name="instanceCreate" stringvalue="org.mymodule.MyAction" />
                    </file>
                </folder>
            </folder>
        </folder>
    </folder>
    
As described in general actions registration tutorial.

This functionality is available since version 5.0 of the loaders module. Please use OpenIDE-Module-Module-Dependencies: org.openide.loaders > 5.0 in your module dependencies.

In version 5.8 all the standard loaders were changed to read actions from layer:

How to allow others to enhance actions of your loader?

If you want other modules to enhance or modify actions that are visible on DataObjects produced by your DataLoader and you are either using DataNode or its subclass, you can just override protected String actionsContext() method to return non-null location of context in layers from where to read the actions.

The usual value should match Loaders/mime/type/Actions scheme, for example java is using Loaders/text/x-java/Actions, but the name can be arbitrary.

This functionality is available since version 5.0 of the loaders module. Please use OpenIDE-Module-Module-Dependencies: org.openide.loaders > 5.0 in your module dependencies.

How to use Module System API?

The Modules API lies at the core of NetBeans and describes how plug-in modules are added and managed. ModulesAPI

Cover of NetBeans Platform for Beginners book For general overview of the concepts, together with code samples, see chapter 2, of NetBeans Platform for Beginners by Jason Wexbridge and Walter Nyland. Gory technical details are explained on API overview page . Other interesting topic(s) follow:

How a classpath of my module is constructed?

The NetBeans is defacto a container that manages individual module's lifecycle and other runtime aspects. One of the important things is that it creates a runtime classpath for provided modules based on dependencies they specify in their manifests. The overview of the runtime infrastructure is a good starting place for everyone who wishes to learn more about the NetBeans runtime container behaviour.

Runtime compatibility patches

To maintain binary compatibility, method implementations may be injected at runtime, in a form of a superclass in the class' inheritance hierarchy. Modules compiled against older version of APIs which contains MethodReferences to methods removed from the oficial APIs will be then linked according to JVM Resolution algorithm to a matching method present in the superclass of the referenced type.

Annotations are used to instruct the ClassLoader to make transformations to the API classes. PatchFor causes the annotated class to be injected as a superclass of the API class identified by the annotation's value. ConstructorDelegate marks a method, which is called as constructor implementation in the case that it is necessary to preserve a constructor for binary compatibility.


How to use Nodes API?

Nodes API serves as the main aparatus for visualisation of objects in NetBeans. Nodes augment objects with standard aspects used for visualisation (e.g. name, displayName, icons, set of proerties, subnodes hierarchy, etc.) Once a Node is defined for given object it can be visualised using diferent views e.g. trees, lists, tables etc. Descripion of nodes can be found here.

Cover of NetBeans Platform for Beginners book For general overview of the concepts related to nodes and explorers, together with code samples, see chapter 7, of NetBeans Platform for Beginners by Jason Wexbridge and Walter Nyland.


How to use Text API?

The EditorAPI is used for accessing editor-related functionality from within the IDE for use by other modules and the core IDE itself.

XXX no answer for arch-usecases


How to use Base Utilities API?

Described in the overall answer.

Use-cases can be found in org.openide.util.ui module arch summary.


How to use Lookup API?

Described in the overall answer.

Cover of NetBeans Platform for Beginners book There is a great introduction to Lookup and its usage in its javadoc. For details on this topic, together with code samples, see chapter 4, of NetBeans Platform for Beginners by Jason Wexbridge and Walter Nyland. In addition to that here is a list of frequently asked or interesting questions slowly expanding as people ask them:

Lookup faq:

How to specify that a service in Lookup should be available only on Windows?

Q: Most of the time I specify interfaces that I want to add to the Lookup class in the layer.xml file. But, let's say I have a platform-specific interface (something on Windows only, for instance).

How can I specify (in the xml, or programmatically) that this service should only be added to the Lookup if the platform is Windows? >

In general there are three ways to achieve this.

How shall I write an extension point for my module?

Q: I have more modules one of them providing the core functionality and few more that wish to extend it. What is the right way to do it? How does the Netbeans platform declare such extension point?

Start with declaring an extension interface in your core module and put it into the module's public packages. Imagine for example that the core module is in JAR file org-my-netbeans-coremodule.jar and already contains in manifests line like OpenIDE-Module: org.my.netbeans.coremodule/1 and wants to display various tips of the day provided by other modules and thus defines:

             
package org.my.netbeans.coremodule;

public interface TipsOfTheDayProvider {
    public String provideTipOfTheDay ();
}

        

And in its manifest adds line OpenIDE-Module-Public-Packages: org.my.netbeans.coremodule.* to specify that this package contains exported API and shall be accessible to other modules.

When the core module is about to display the tip of the day it can ask the system for all registered instances of the TipsOfTheDayProvider, randomly select one of them:

            
            import java.util.Collection;
import java.util.Collections;
import org.openide.util.Lookup;

Lookup.Result result = Lookup.getDefault ().lookup (new Lookup.Template (TipsOfTheDayProvider.class));
Collection c = result.allInstances ();
Collections.shuffle (c);
TipsOfTheDayProvider selected = (TipsOfTheDayProvider)c.iterator ().next ();

        

and then display the tip. Simple, trivial, just by the usage of Lookup interface once creates a registry that other modules can enhance. But such enhancing of course requires work on the other side. Each module that would like to register its TipsOfTheDayProvider needs to depend on the core module - add OpenIDE-Module-Module-Dependencies: org.my.netbeans.coremodule/1 into its manifest and write a class with its own implementation of the provider:

            
            package org.my.netbeans.extramodule;

class ExtraTip implements TipsOfTheDayProvider {
    public String provideTipOfTheDay () {
        return "Do you know that in order to write extension point you should use Lookup?";
    }
}

        

Then, the only necessary thing is to register such class by using the J2SE standard into plain text file META-INF/services/org.my.netbeans.coremodule.TipsOfTheDayProvider in the module JAR containing just one line:

org.my.netbeans.extramodule.ExtraTip

and your modules are now ready to communicate using your own extension point.


How to use Utilities API?

Described in the overall answer.

How shall I do or influence logging in NetBeans?

If you are interested in logging from inside your module, or in writing your own log handler or in configuring the whole system, then best place to start is the NetBeans logging guide.


How to use Window System API?

Window System API is used to display and control application GUI: Main window, frames, components.

Cover of NetBeans Platform for Beginners book For general overview of the concepts, together with code samples, see chapter 6, of NetBeans Platform for Beginners by Jason Wexbridge and Walter Nyland.

General Usecases

General usecases can be read in the design document created before work on new window system design started.

How to create a '.settings' file for a TopComponent?

Either write it by hand (not that hard if you copy other file and tweak it to match your TC), or start the IDE, instantiate the TC somehow (You have a "Window->Show My TC", right? ), copy the file that gets created in $userdir/config/Windows2Local/Component and cleanup the serialdata section - replace it with proper "<instance class='..." /> tag.

How to make a TopComponentGroup?

Q: I'm trying to make a TopComponentGroup. I've just read http://ui.netbeans.org/docs/ui/ws/ws_spec.html#3.9 I want to make a group that uses the first invocation strategy. That is, I want the group to open/close when I activate a certain subclass of TopComponent. Say, for example, I have a FooTopComponent, and when it's active, I want to open a FooPropertySheetComponent, docked in a mode on the right-hand side. I know I have to:
  1. declare the group in the layer file (Windows2/Groups)
  2. have code for opening the group
  3. have code for closing the group
I think I do #2 in FooTopComponent.componentActivated() and #3 in FooTopComponent.componentDeactivated(). Is that right?

A:Yes it is correct way. You can check simple test module. First you must get TopComponentGroup instance using find method then call TopComponentGroup.open()/close(). Here is the code in your componentDeactivated method:
   protected void componentDeactivated ()
   {
       // close window group containing propsheet, but only if we're
       // selecting a different kind of TC in the same mode
       boolean closeGroup = true;
       Mode curMode = WindowManager.getDefault().findMode(this);
       TopComponent selected = curMode.getSelectedTopComponent();
       if (selected != null && selected instanceof FooTopComponent)
           closeGroup = false;
             if (closeGroup)
       {
           TopComponentGroup group = WindowManager.getDefault().findTopComponentGroup(TC_GROUP);
           if (group != null)
           {
               group.close();
           }
       }
   }