Thursday, May 3, 2007

SnTT: Single-View User Interface Problems (and Solutions)

Lately, I've been doing a lot of user interface work. I've updated the interfaces on three of our applications and created a new interface for the Team Room (7) template. I also used a completely different (for us) style on a new database I developed, which is what I want to share today.

This is a database for which we wanted to keep the interface simple. The primary users are more focused on mainframe programming and don't use a lot of Notes applications, so rather than giving them a list of views to choose from and hundreds of documents to wade through, I embedded a view on a form (called, very creatively, User Interface) and let them choose the category they want to see using a radio button and drop down list on the form. When it is opened, the database creates a document using the UI form and displays the category for the user who opened the database (as in "My Documents"). The embedded view is set to Fit to Window for both height and width.

The original idea was to display the UI form in the top frame of a two-frame frameset. The bottom frame, collapsed by default, would be for previewing documents in the embedded view.

All seemed to be going well until I ran into a category that had too many entries to fit on one screen. In that case, I could see a scroll bar at the right of the view but the last two documents could not be seen. After a while, I discovered that was because Notes does not include the height of text above the embedded view when it calculates the height of the embedded view to fit it to the window. In other words, my embedded view extended below the bottom of the screen by the amount of space I had above it on the form.

Because this was my interface (not an individual document), I didn't want a scroll bar at the right side at all times. I didn't want the user to have to scroll both the interface form and the embedded view, and I didn't want the top part of the form to scroll off the screen so I could see the bottom of the view. So, what to do? I had a couple of ideas that involved tables but I couldn't get the table row height to automatically go to the window height. Setting the height of the embedded view also didn't work because it didn't scroll correctly if the preview pane opened up big enough to hide part of the view. I also thought of a little more traditional two-pane setup but liked the basic idea I had better. "A-HA!," I thought, "I'll create a frameset with three frames." The "A-HA" was easier than the implementation ended up being.

The top frame contains a form with the radio button and drop down list in it, the middle frame contains the embedded view, and the bottom frame is the preview frame. Here is the frameset in Designer:

Because the embedded view is the only thing on the form in the middle frame, setting its height to Fit to Window does not present any scrolling problems; the scroll bar appears when it is needed due to the number of documents in view or when the preview pane is open. The problem is communicating changes in the fields in the top frame to the view in the middle frame so that the view displays the proper category. I decided to use an environment variable for that communication, setting it in the top frame and reading it in the middle frame. I was going to use the OnChange event of the drop down field to trigger the update but @formulas can't be used there. I also found that a) I couldn't set the variable using @formulas and b) I couldn't update the middle frame using LotusScript. GRRRR! I still don't know why neither @Environment nor @SetEnvironment worked. Maybe I needed to restart my client or something.

At any rate, I ended up adding a button next to the drop down with two @formulas: one that runs a small LotusScript agent to set the environment variable and one that refreshes the frame containing the view. I also put an @Environment command in the QueryOpen of the form in the top frame (it worked there!) to set the default value of the variable. After all that work, it looks the way I wanted it and scrolls properly:

I don't love the 'Go' button I had to add but I couldn't come up with another way to trigger the updates I needed to refresh the embedded view. I thought later about using JavaScript to update the view frame and refresh it but I don't know JavaScript very well and couldn't find a good example for what I wanted to do. Maybe I'll revisit it later.

But in the meantime, maybe this is something you can add to your own toolset as you think about your application interfaces.



Anonymous said...

Height: Fit to Window is WAY busted. I've complained to IBM about this through several vectors.

I've also proposed to them the idea of an EmbeddedFrameset, which might have made this effort a little easier.

The part that sucks about what you ultimately had to do (and I don't mean that in a "it's a bad solution" way) is that your top contents can't extend past the frame border. So you can't have a drop-down that eats up space over the view itself.

Personally, I usually just suffer through setting the embedded view to a static height. I love that you took the energy to make it fluid.

This is a great example of getting away from the 3-pane model that's so prevalent in Notes designs. Nice work.

Don McNally said...

Nathan, thanks for your comments and the compliment.

I checked this morning and the drop down actually does overlay the lower frame. I don't know if the field type makes a difference but I used a Combobox. Maybe a Dialog List wouldn't behave the same way.

Slawek Rogulski said...

You could try this. Place the combo box and radio button, etc in the header of the form. Then the view goes in the body of the form, just below the header. Set the left margin where the view is to 0.75" which will align it to the left edge of the window.

This way you avoid having to use another frame and the intra-frame communication that goes with that. You of course still need the document preview frame.

The view will be refreshed to show the right category when you change the value of the combo box field. You of course need to set the field to refresh fields on value change.

The header can be set to resizeable, which can also give the impression of a top frame. So you can allow the users to minimize the header thus gaining more space for the view. Once they have chosen the category they want to work with that is. And I do not know of a programmatic way to do it via a button for example.

Don McNally said...

Slawek, thanks for the comments. I hadn't thought about using a header but I'm not sure it would resolve the problem. What I was trying to resolve was incorrect scroll bars on an embedded view. The embedded view doesn't seem to know about the space above it on the form so the scroll bars don't always appear when they need to. It's bad enough when you just have the form containing the view open, but then add the preview frame and it gets downright ugly.

I didn't want to make the user scroll the form and then scroll the embedded view if needed.

I may try the header idea if I get a chance but I think the embedded view would still not scroll correctly - it still doesn't know how much appears above it on the form.

Thanks for stopping by!

Slawek Rogulski said...

Don, I have used the form header/body technique before. It has worked. I was able to set the view height to "fir to window" and the scroll bars behaved normally. There was no double scroll bards, from the view and the form. I guess in this case fit to window means fit to form body.
Basically the form then becomes like a frameset and the view is in the lower frame. You just need to make sure that the "body" of the form only has the view. Of course, you can have hidden fields and other hidden elements.
If you want I can send you a demo ...
Oh, and I have also placed more than one view in the "body" and had them programaticaly switched by an action/outlines/etc.

Don McNally said...

Implemented and documented Slawek's solution here: