forum  

[Forum] A: Javahelp with Swixml

List for Users of Carlsbad Cubes' Technologies and Products
Wed, 08 Feb 2006 01:23:07 -0800

Hello all,

to bring this list a little back to life, I would like to show something which 
reminded me (again) of the power of XML for UI generation in general and Swixml 
in particular.

Recently I had the problem to add a help system to our application. Short scan 
revaled JavaHelp as the system to use and some tools (HelpSetMaker) to author 
the necessary files. The only problem remaining was to get my GUI components to 
be "registered" on this help system, such as:

HelpSet helpSet = ...;
HelpBroker broker = ...;
broker.enableHelp(myComponent, "my.help.id", helpSet);

Here, myComponent is an arbitrary java.awt.Component, perhaps a JTextField to 
enable help at. The helpSet and the helpBroker are JavaHelp specific classes.

One solution would have been to get all GUI components you want to enable help 
at and assign the appropriate help-ID manually. Each time you change the help 
system, you need to change this code as well.

So, my solution was different. First, I created specialized, help-enabled 
classes for each GUI component I wanted to use. This was done through copying 
the first manually created class to several others, changing name and ancestor:

public class HelpsupportTextField extends JTextField implements HelpComponent {

    /* (non-Javadoc)
     * @see 
de.imatics.ipd.tools.HelpIdComponent#setHelpBroker(javax.help.HelpBroker)
     */
    public void setHelp(HelpContainer helpContainer) {
        helpContainer.getHelpBroker().enableHelp(this, 
helpContainer.getHelpId(), null);
    }

}

For containers (JFrame, JPanel, JDialog) this is not that easy because these 
components have to capture the F1 key and take care of displaying help as well 
(taken from HelpsupportDialog):

String helpId = helpContainer.getHelpId();
HelpBroker mainHB = helpContainer.getHelpBroker();
mainHB.enableHelp(this, helpId, null);
mainHB.enableHelpKey(getRootPane(), helpId, helpContainer.getHelpSet(), 
"javax.help.MainWindow", null);


HelpComponent looks not that spectacular either:

public interface HelpComponent {
    /**
     * Enables the help on the implementing component.
     * 
     * The function is named wrong because Swixml supports only setter with a 
single argument.
     * 
     * @param helpBrokerContainer container for both a [EMAIL PROTECTED] 
javax.help.HelpBroker} and the
     * [EMAIL PROTECTED] HelpContainer#getHelpId() help id} to enable help at
     */
    public void setHelp(HelpContainer helpBrokerContainer);
}


The HelpContainer was only necessary to meet Swixml's limitation regarding 
one-argument setter methods. See below to get the code for it.  The only things 
to do where the converter to convert the XML attributes to HelpContainers and 
to register the help-enhanced components in the SwingEngine:

ConverterLibrary.getInstance().register(HelpContainer.class, new 
HelpIdConverter());
....
TagLibrary tagLib = engine.getTaglib();

tagLib.registerTag("helpmenuitem", HelpsupportMenuItem.class);
tagLib.registerTag("helpmenu", HelpsupportMenu.class);
tagLib.registerTag("helpbutton", HelpsupportButton.class);
tagLib.registerTag("helpdialog", HelpsupportDialog.class);
tagLib.registerTag("helpframe", HelpsupportFrame.class);
tagLib.registerTag("helptextfield", HelpsupportTextField.class);
tagLib.registerTag("helptextarea", HelpsupportTextArea.class);
tagLib.registerTag("helpcombobox", HelpsupportComboBox.class);
tagLib.registerTag("helpcheckbox", HelpsupportCheckBox.class);
tagLib.registerTag("helpradiobutton", HelpsupportRadioButton.class);

The HelpIdConverter does the work of initializing the HelpSet and the 
HelpBroker. My current implementation uses only one helpset, but this may be 
changed easily. The code of the HelpIdConverter is also below, but -- I think 
-- is straightforward anyway. Of course, in the above example I may have 
overwritten the standard "tag names", such as:

tagLib.registerTag("menuitem", HelpsupportMenuItem.class);

But then, I see at the first glance which GUI component is'nt yet help-enabled.

As you may have guessed, I can now write something like this in my Swixml-GUI 
files:

    <helpmenu text="Main.File" mnemonic="Main.File.Mnemonic" help="file-menu">

So, there ends my quick introduction to implementing context sensitive help 
with the help of Swixml. I guess, with a similar approach (shadow classes for 
each component) it is possible to implement GUIs able to switch language/locale 
at runtime: just remember the resource-key, add the affected component to some 
storage and -- upon locale change -- go through this storage and re-render the 
GUI item using the resource key. (just a thought, did'nt try this).

To additionally water your mouth, I additionally append actions to invoke help 
after tracking and for our main application frame.

Yours,

Frank Meissner

public class HelpPointAction extends AbstractAction {
    ActionListener displayHelpAfterTracking = new 
CSH.DisplayHelpAfterTracking(HelpIdConverter.getHelpBroker());

    /* (non-Javadoc)
     * @see 
java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        displayHelpAfterTracking.actionPerformed(e);
    }

}


public class HelpAction extends AbstractAction {
    private static HelpAction instance = new HelpAction();
    private CSH.DisplayHelpFromSource delegatee;

    /**
     * Gets the one and only help action.
     * 
     * @return never <code>null</code> but always the same [EMAIL PROTECTED] 
HelpAction} object
     */
    public static HelpAction getInstance() {
        return instance;
    }

    
    
    private HelpAction() {
        delegatee = new 
CSH.DisplayHelpFromSource(HelpIdConverter.getHelpBroker());
    }

    /* (non-Javadoc)
     * @see 
java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        delegatee.actionPerformed(e);
    }

}

public class HelpIdConverter implements Converter {
    private static final String HELPSET_NAME = "main.hs";

    private static HelpSet helpSet;

    private static HelpBroker helpBroker;
    static {
        ClassLoader cl = HelpSet.class.getClassLoader();
        try {
            helpSet = new HelpSet(cl, HelpSet.findHelpSet(cl, HELPSET_NAME));
        } catch (HelpSetException e) {
            throw new RuntimeException("failed to init help set from \""
                    + HELPSET_NAME + "\"", e);
        }
        helpBroker = helpSet.createHelpBroker();
    }

    public Object convert(Class type, Attribute attr, Localizer localizer)
            throws Exception {
        return new HelpContainer(helpBroker, helpSet, attr.getValue());
    }

    public Class convertsTo() {
        return HelpContainer.class;
    }

    /**
     * Gets the help broker to register components for online help on.
     * 
     * @return never <code>null</code>
     */
    public static HelpBroker getHelpBroker() {
        return helpBroker;
    }

    /**
     * Gets the (one and only) help set used in this application.
     * 
     * @return never <code>null</code>
     */
    public static HelpSet getHelpSet() {
        return helpSet;
    }

}


public class HelpContainer {
    private HelpBroker helpBroker;
    private String helpId;
    private HelpSet helpSet;
    /**
     * Construction takes place by specifying a broker, a help set and the id 
of the object help should be 
     * registered for.
     * 
     * @param broker
     * @param set 
     * @param helpId
     */
    public HelpContainer(HelpBroker broker, HelpSet set, String helpId) {
        helpBroker = broker;
        helpSet = set;
        this.helpId = helpId;
    }

    /**
     * Gives the help broker to enable help with.
     * @return the help broker object
     */
    public HelpBroker getHelpBroker() {
        return helpBroker;
    }

    
    /**
     * The help id to enable at a [EMAIL PROTECTED] HelpBroker}
     * 
     * The [EMAIL PROTECTED] de.imatics.view.help.HelpIdConverter help 
converter} sets this to the value of the
     * <code>help</code> attribute. This help id <em>must</em> equal the key 
used in the help set 
     * (the <code>label</code> when using the HelpSetMaker). 
     * 
     * @return the help id
     */
    public String getHelpId() {
        return helpId;
    }

    /**
     * Gives the helpset to use.
     * @return the help set
     */
    public HelpSet getHelpSet() {
        return helpSet;
    }
}



_______________________________________________
Forum mailing list
Forum@carlsbadcubes.com
http://carlsbadcubes.com/mailman/listinfo/forum_carlsbadcubes.com
  • [Forum] A: Javahelp with Swixml List for Users of Carlsbad Cubes' Technologies and Products