« Previous month (Feb 2005) | Main | Next month (Apr 2005) »

20050331 Thursday March 31, 2005

Creating Tabbed Menus

Somebody asked on the forum how to create a Tab menu using standard JSF components.

Here's one way you can do it. It's not easy (yet!) but works. The solution involves the following steps:

First go ahead and create your TabFragment. In it, drop a gridpanel. Let's say you want 6 pages to be part of this tab. Set the columns property to 6 - this will ensure that the components are laid out in a single horizontal row.

Now drop 6 hyperlinks into the page. The tab text for the nested output text components should be the displayed tab names. The action properties for the action links should be logical navigation case names - these can be anything, as long as you use the same names in your navigation file. (Note that each link action you dropped results in two separate components - the link, which has an action property, and a nested output text, which has the text string. Use the application outline when in doubt.)

Next, go and create all six pages that will be part of the tabbed set. On each page, include the tab fragment. Next go to the navigation file, switch to the XML file view (because wildcards are not yet well supported in the design view), and add a rule like this - use cut & paste:

    <navigation-rule>
        <from-view-id>*</from-view-id>
        <navigation-case>
            <from-outcome>viewPreferences</from-outcome>
            <to-view-id>/ViewPreferences.jsp</to-view-id>
        </navigation-case>
    </navigation-rule>

This assumes that one of the links in the tabbed fragment has the action attribute set to "viewPreferences", and when clicked, this will navigate to the ViewPreferences.jsp page.

Repeat the above for all the hyperlinks in your tabbed fragment such that each has a page, a corresponding link, and a corresponding navigation rule.

Voila! You're ready to run - you now have a functional (but ugly) tabbed window set up. You should be able to run and navigate the tabs as expected.

The next thing you'll want to do is create some sort of visual feedback for the tabs, such that exactly one tab is shown as "current" (e.g. it has a tabbed border). Likewise, you'll probably want to change the link styling for this tab (so it looks like plain text) and for the other tabs (so they look less like hyperlinks).

We can achieve this with CSS. Let's say you add these two rules to your stylesheet:

.selected { }
.notselected { }
We'll tweak these later. Now the big question is: How do we get the tab fragment to automatically style the different portions of the tabbed fragments according to which tab is selected?

Go to your tabbed fragment's backing bean, and add some code like this:

    // XXX You MUST keep this in sync with the actual links included in the page fragment,
    // and navigation destinations in the navigation.xml file!
    static String[] tabs = { "/Page1.jsp",
                             "/Page2.jsp",
                             "/Page3.jsp",
                             "/Page4.jsp",
                             "/Page5.jsp",
                             "/ViewPreferences.jsp"};

    private int getSelectedIndex() {
         FacesContext fc = getContext();
         String viewId = fc.getViewRoot().getViewId();
         for (int i = 0; i < tabs.length; i++) {
             if (viewId.equals(tabs[i])) {
                 return i;
             }
         }
         return-1;
    }

    public String getColClasses() {
        StringBuffer sb = new StringBuffer();
        int sel = getSelectedIndex();
        for (int i = 0; i < sel; i++) {
            sb.append("notselected,");
        }
        sb.append("selected,");
        for (int i = sel+1; i < tabs.length; i++) {
            sb.append("notselected,");
        }
        return sb.toString();
    }
The whole point of this code is to create a property in the page fragment, called "colClasses", which will return something like "notselected selected notselected notselected notselected notselected" if for example the second tab is selected. And how do we know which tab is selected? It's obviously the page that is including the tabbed fragment being rendered! So the getSelectedIndex() method goes out and finds out what the root page name is, then looks that up in its tabbed page list (which you need to edit obviously), and based on this computes a comma-separated list of style class names.

The list of style class names can be bound directly to the grid panel in the page fragment which is including the links. Go and select it, then set its columnClasses property to the value binding expression #{TabFragment.colClasses}. (You can do this by right clicking on the grid panel and choosing Property Bindings... too, then drill into your page fragment and locate the colClasses name. Don't forget to hit Apply.)

We're almost done. We now apply different styles to the different cells rendered for the tabs in the tab fragment. Now we just need to play with CSS to create tab-like effects.

Here are some things you'll want to try:

I wish I could share my stylesheet with you but I used an existing proprietary one. If anyone does work on this and wants to publish their solution feel free to append a comment! Good luck and let me know how it works out!

(2005-03-31 22:19:15.0) Permalink Comments [5]

Hippie Completion

I read in Cendric Beaust's blog that the latest Eclipse snapshot now has "hippie completion". This is an editor feature where you press a keybinding and the editor automatically completes the word you're typing for you, by searching around in your current document (and if not found) in other documents.

NetBeans has had this feature for at least five years. Since Creator is built on top of NetBeans, you'll find it in Creator too.

Hippie completion is also known as hippie expansion and originated in Emacs. See for example the XEmacs documentation.

It is bound to Ctrl-K (and on the Mac, Command-K). Go ahead and try it - it's the best way to figure out how it works. If the word you want to complete has many possible matches, hit Ctrl-K repeatedly to cycle through the matches. For example, in a typical Creator file, if you type "Ht" and hit Ctrl-K, it's going to offer HtmlCommandButton, HtmlOutputText, etc. if you have buttons and text components on the page. Now aren't you glad you didn't have to type that?

While I'm on the topic of editor shortcuts, another feature you may not know about it "Go Back". Let's say you've jumped around in your editor files, by clicking on error links in the output window, or by using "Go to declaration" (alt-g if I remember correctly), etc. You can "Go Back" just like in a browser by hitting Alt-K. And to move forward again, hit Alt-L. (And yes, these have toolbar buttons in Creator, and in recent NetBeans 4.1 builds as well.)

(2005-03-31 20:07:55.0) Permalink Comments [2]

20050328 Monday March 28, 2005

Even the Tooth Fairy Is Too Busy

My daughter was pretty disappointed this morning. She lost her front tooth, and put it in a glass by her bed last night. And this morning, the tooth fairy had apparently not stopped by - or perhaps she did, but after taking a look at the tooth decided she didn't want to trade.

The last couple of weeks have been really busy. On the home front, all three of my kids have been sick, which with all the implied sleepless nights has really taken its toll on me. But we've had fun too - on Sunday my youngest son took an unintentional swim in the Vaillancourt Fountain in San Francisco. Luckily there was a clothing store nearby so he didn't have to take the train home in soaking wet cloathes!

The main reason I've been busy however is work. Those of you using Creator today will be very happy to see the fruits of our labor in the next version.

This is my favorite part of the development process. Yes, you have more freedom in earlier stages too take all kinds of input and plan to do everyhing. Yes. Yes. Yes. And a pony too? Sure, no problem.

However, my favorite part is later in the cycle. All the major systems are getting done, they're getting integrated, they're working, and it's really exciting to see hard work paying off. And especially to actually start playing with what will be the end product.

My favorite quote from the Creator team is "It's all uphill from here!". I only vaguely remember the context, but I know it was Joe who said it, so perhaps he can blog about it. Anyway, the beauty of the quote was that it was said eloquently and in context such that it meant exactly the opposite of what it sounds like. But I think it's that inflection point in development I like best - acceleration. Or maybe even the Big Bang metaphor. We've had a couple of big bangs lately, with different people integrating big changes simultaneously, and seeing it all work together is inspiring.

I'm working from my garage office, but I have a baby monitor so I can hear the kids in the house. And they sound asleep. I'd better go play the Tooth Fairy. I told my daughter this morning the fairy is probably busy and can't stop by every house every night. But I'd better take care of it tonight. After all, if she's not writing software, how busy could she be?

(2005-03-28 21:35:04.0) Permalink

20050310 Thursday March 10, 2005

Stylish Components

This article on CSS and Creator was published today.

(2005-03-10 21:59:35.0) Permalink

20050309 Wednesday March 09, 2005

Silence Is Golden!

Actually, that's just my excuse for not blogging much the last couple of weeks - and I haven't visited the forum at all either.

I'm working feverishly on some new features for an internal milestone.

But I promise to come back and post early next week, so be sure to check back!

Oh, a parting tip: Be sure to place Message List components on ALL your pages. If an error is triggered somewhere in your application, and this is detected in the JavaServer Faces code, it will typically log an error message. If you don't have a Message List component on your page you won't see the error!

Furthermore, you can use the Message List components for simple "printf" debugging. Whenever you're writing some code and it's not working - you can just use the debugger (it works, although sometimes requires the server to be restarted in debugging mode). But a really quick & dirty way to see your results is to just call the "error" method, which is defined in your page beans' super class. So just do this:

     ....
     Object o = getValue("#{foo}");
     // hmmmm I wonder what type o is?
     error("DEBUG: The class of o is " + o.getClass().getName());
     ....
When you run, the Message List component will display your message (or set of messages, if more than one was logged). This even works with multiple pages - let's say you put a Message List on each one of your pages. If you put an error() call in the action handler for a submit button, then the message you printed will show up on the new page you navigated to in its own Message List component!

Here's some more info about the Message List and notification mechanism. Be sure to scroll to the top and check out the rest of the article too. I haven't read it yet (remember, I'm swamped at the moment) but I've glanced enough at it that I can recommend it!

(2005-03-09 20:40:57.0) Permalink