// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= DevFaqJavaHelpOverrideCustom
:jbake-type: wiki
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqJavaHelpOverrideCustom
:description: Apache NetBeans wiki DevFaqJavaHelpOverrideCustom
:toc: left
:toc-title:
:syntax: true

= How can I override JavaHelp to display my own help or documentation?

1. link:#How_can_I_override_JavaHelp_to_display_my_own_help_or_documentation.3F[How can I override JavaHelp to display my own help or documentation?]
1. link:#Step_1:_HelpCtx.Displayer[Step 1: HelpCtx.Displayer]
2. link:#Step_2:_Help.class[Step 2: Help.class]
3. link:#Step_3:_Connecting_UI_To_JavaHelp[Step 3: Connecting UI To JavaHelp]
4. link:#Step_4:_Add_the_JavaHelp_Integration_Module[Step 4: Add the JavaHelp Integration Module]
5. link:#Summary:_Putting_It_All_Together[Summary: Putting It All Together]
1. link:#Apache_Migration_Information[Apache Migration Information]

== Step 1: HelpCtx.Displayer

First, you must create a HelpCtx.Displayer that is capable of displaying your help and register it as a service provider

[source,java]
----

@ServiceProviders({
    @ServiceProvider(service = HelpCtx.Displayer.class, position = 1000)
})
public class CustomHelpDisplayer implements HelpCtx.Displayer {
    
    public boolean display(final HelpCtx helpCtx) {
        
        // Put your displaying code here.
        JOptionPane.showMessageDialog(
                WindowManager.getDefault().getMainWindow(),
                helpCtx.getHelpID());

        return true;
    }
}
----

== Step 2: Help.class

An instance of org.netbeans.api.javahelp.Help determines what to do with a particular HelpCtx. In order to use your custom help displayer, you need to create an instance of Help that can display using your custom help displayer. In this case, you want to override the Help class provided with the NetBeans platform, so you set the 'position' attribute low. The purpose of this class is two-fold:

* If the HelpCtx.getHelpID() is a value we recognize and can use, we display it with our displayer. For our example below, we handle any help ID that starts with "PREFIX."
* If not, we pass it on to the default help system.
[source,java]
----

@ServiceProviders({
    @ServiceProvider(service = Help.class, position = 1)
})
public class CustomHelp extends Help {

    @Override
    public Boolean isValidID(final String id, final boolean force) {
        // We return true because even if it's not a valid ID for our purposes, we just pass it
        // to the default help and let it deal with it.
        return true;
    }

    @Override
    public void showHelp(final HelpCtx ctx, final boolean showmaster) {

        // Here, we examine the ID and if it starts with "PREFIX", we find our implementation
        // of HelpCtx.Displayer using the Lookup API and use it to display our help.
        if (ctx.getHelpID().startsWith("PREFIX")) {

            final HelpCtx.Displayer displayer =
                    Lookup.getDefault().lookup(HelpCtx.Displayer.class);

            displayer.display(ctx);
        }

        // If we don't know what do with the ID, we find all the implementations of Help and
        // pass the HelpCtx along to the first one we find that isn't this class.
        else {
            final Collection<? extends Help> helps =
                    Lookup.getDefault().lookupAll(Help.class);
            
            for (Help help : helps) {
                if (help != this) {
                    help.showHelp(ctx, showmaster);
                    
                    break;
                }
            }
        }
    }

    @Override
    public void addChangeListener(final ChangeListener listener) {
        // *** Not sure what to do here.
    }

    @Override
    public void removeChangeListener(final ChangeListener listener) {
        // *** Not sure what to do here.
    }
}
----

== Step 3: Connecting UI To JavaHelp

See link:http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-javahelp/org/netbeans/api/javahelp/doc-files/help-guide.html[Connecting Help In NetBeans].

== Step 4: Add the JavaHelp Integration Module

This module is not "eager", so to force it to load, at least one module must depend on it. Simply make JavaHelp Integeration a dependency of one your modules to make Help available. The JavaHelp Integration module is in the 'platform' library.

== Summary: Putting It All Together

* Your UI provides the HelpCtx.
* The CustomHelp class (invoked when the user launches help, usually by pressing F1) examines help IDs.
* If it's one we recognize, we invoke our custom displayer.
* If it's not, we hand it off to another Help instance.

--
Applies to: NetBeans IDE 7.2
Platforms: All

=== Apache Migration Information

The content in this page was kindly donated by Oracle Corp. to the
Apache Software Foundation.

This page was exported from link:http://wiki.netbeans.org/DevFaqJavaHelpOverrideCustom[http://wiki.netbeans.org/DevFaqJavaHelpOverrideCustom] , 
that was last modified by NetBeans user Michael.Bishop 
on 2013-03-08T19:33:37Z.


*NOTE:* This document was automatically converted to the AsciiDoc format on 2018-02-07, and needs to be reviewed.
