« Make Attractive Exports of Categorized Notes Views | Main| Jon Galloway's Helpful Guide to De-Sludgifying Windows XP »

Two-Row View Action Bars in Lotus Notes?

QuickImage Category    


How's that for an attention grabber?  Well, let me quickly assuage any concerns you may have that I am promoting two-row action bars for Notes views because I can't fit all my actions on one (I can).  The actual design goal that led me to the innovation described here was to place a line of descriptive text about the current view above the action bar like that in the DDM (Domino Domain Manager) database, shown here:

A picture named M2

The ultimate solution I came up with utilizes the @UpdateFormulaContext function, which is as powerful as it is underappreciated.  Those of you familiar with it may already have a good idea of what's ahead in this post, but read on, as it gets better...

OK, so why not just copy the code from the DDM template?

Great question, especially considering that DDM is a very impressive example of great Notes database design, as fellow Domino blogger Andy Broyles discusses in depth here.  The reason stems from my larger design goal, which was to build a standard Notes database architecture that would be reasonably easy for novice developers to understand, and which could form the foundation of *any* custom application development.  In contrast, the DDM database was built for a single, if highly ambitious, purpose, and can afford to use more complex techniques and design element interdependencies that might confuse many developers.

DDM views have a lot going on in terms of view events, and all rely on the lsClassDMMView script library, which contains the code that ultimately controls the "view comment" description that I am trying to emulate.  That script libary is also hard-coded with all the text strings for each view, and I wanted to make the strings configurable so they could be changed without code modifications.  Perhaps more importantly, I didn't want to require an update to a script library (which might then require recompiling a lot of other code) every time I added a view or folder to a database.  Since I might at some point enable users without designer access to create views or folders programmatically, the need for configurability becomes even more pressing.  And finally, I was concerned that developers with limited Lotusscript experience (and probably no clue what a custom class or OO are all about) might unwittingly break the code when attempting customizations.

A picture named M3

In designing the view comment and multi-tab features of DDM, Thomas Gumz and Scott O'Keefe placed those header elements into a small frame directly above the "NotesView" frame.  The NotesView frame contained just the view, with all its action buttons.  The problem that I needed to work around to meet my design goal was how to refresh the content in such a frame as the view selection changed, WITHOUT calling any view events like QueryOpen.  Sure, I could change the outline entry for a particular view from a simple "Named Element - View - ViewName" type to an "Action" type, then refresh the ViewHeader frame and load the view into the NotesView frame with something like:

@SetTargetFrame("NotesViewHeader");
@SetEnvironment("viewcomment"; "All documents, sorted by something");
@Command(efreshFrame;
@SetTargetFrame("NotesView");
@Command(penView "vw_alldocsbysomething")

The problem with with the Action approach is that it "breaks" the outline focus when you close and reopen the database with "Restore as last viewed by user" enabled.  In most cases when you select an outline entry in order to open a view, that entry becomes highlighted, and *remains* highlighted after closing and reopening the database. However, if the entry is an action and not a "Named Element" type, the highlight won't be active when the database is reopened.  The bottom line is that outline entries that point to views need to be of the Named Element type for things to work properly.

A picture named M4

So, if you can't get a "view comment" in a separate frame to update as the view selection changes, what is the alternative?

Well, If refreshing a separate frame as the view selection changes is out of the question, then the only option left is to put the view comment in the SAME frame as the view, and the only place to do that is in the action bar.  Fortunately action button *labels* are now computable, so you can put the view comment on an action button label and make the button inert, hide the button borders so the button blends into the Action bar background, and generally format the button so it doesn't look like a button.

But what about all the "real" actions already there?  You know the ones that do stuff and ought to *look* like actual buttons?

The solution to this part of the problem is where @UpdateFormulaContext comes in.  @UpdateFormulaContext allows us to move our standard view actions OUTSIDE the view frame and into the view header frame, even if the action needs to access selected documents in the view or otherwise target the view in some way for processing.  Although this is essentially the opposite of the approach used by DDM, where action buttons appear below the view comment, it was an acceptable compromise.  Here's how it looks to the user:

A picture named M2

So, similar to the approach taken in the DDM database, I am using a separate header frame above the NotesView frame.  The essential difference is that instead of tabs and view comment text, what shows in this frame is a form with several action buttons.  The frame itself is sized so that only the action bar is visible. Several of those buttons need to get focus on the NotesView frame, including the Expand, Collapse, Export, Delete, Help, and View Unread/View All (this is toggle similar to the mail template).  Using the Export Selected action as an example, here's how this approach works:

A picture named M3

Where the button code is the following:

@SetTargetFrame("NotesView");
@UpdateFormulaContext;
@Command([OpenView]; @ViewTitle);
@Command([ToolsRunMacro]; "(Export Selected Documents to Excel)")

As you can see, there isn't much to it.  The only part that seems odd is the OpenView command, since the current view is obviously already open.  But it turns out that it is necessary, and doesn't seem to cause any problems such as an extra screen redraw.  The net effect is identical to having the action button in the view itself and just running @Command([ToolsRunMacro]; "(Export Selected Documents to Excel)").  Incidentally, I wrote recently wrote in depth about this export functionality here.

Setting aside the "two row action bar" innovation described here, the actions that you see in the screenshots have themselves been pretty well thought out and are designed to be visible only when relevant, and to behave differently depending on the view appearing in the NotesView frame.  There are limitations to how closely these "fake" view actions can behave just like the real ones.  Most notably, the button labels and hide when formulas will not recompute as the view selection changes.  In addition, I've come up with a cool technique using profile documents for figuring out when to hide the Search and View Unread/View All buttons when the database either isn't full text indexed or doesn't track unread marks.  That will be a subject for a future post, but you will be able to disect the code for yourself soon enough.

I plan to make the entirety of the code shown here available soon in the context of a new OpenNTF project I'm calling "SuperNTF".  If you're really in a hurry to use this basic technique right away, an earlier version happens to already be available as part of my DST Fix Tool that I posted on OpenNTF last month.

Comments

1 - I too had a desire to manage that descriptive string in a more thoughtful and maintainable manner.

What I can up with is pretty elegant, if I do say so myself.

Basically, I am using the view's 'comment' ( from the first tab og teh view's property dialog) as the text string.

In the cView class' PostOpenEvent, I have added the following code:

Set m_oView = Source.View
Set db = m_oView.Parent
Set doc = db.GetDocumentByUNID(m_oView.UniversalID)
Set item = doc.GetFirstItem("$Comment")

... Then later on in the code, with the other ini setting code...

Call m_oSession.SetEnvironmentVar(INI_VIEW_HELP, item.text, False)

...

End Sub


The code grabs the view's Note, assigns the $Comment field to a NotesItem and then writes the content of that Item to the notes.ini, just like DDM would expect.

One additional thing that I do to my DDM based applications (not shown in my example) is add a prefix to the environment varibles via an ownerless profile document field value...otherwise you will get different applications step on each other's DDM variables.


As you stated, the DDM View tab structure is pretty complicated and somewhat fragile if the coder is not use to Lotusscript classes; but if they are, then this is a nice 'clean' way to preserve the original structure, yet give the 'description' a more maintainable existence. Emoticon

2 - Andy, very clever trick using the view comment. While I'm still putting priority on avoiding view events of any kind for application-specific views, I've decided that they're OK for "infrastructure" views. By that I mean views that are part of the standard, static, views used for universal database functionality like configuration. Keyword, View, and Form configurations, Trash, All Documents, and Activity History would be included in this category.

In those cases the assumption will be that no customization is necessary since these are generally not user-facing elements. It is therefore theoretically "safe" to use more complex coding to achieve the desired functionality since novice developers will have little reason to touch the code.

The "two row action bar" technique shown here would not be used for these views. I'm actually thinking I will use the DDM tab approach with only slight modification for the configuration part of the database. Each configuration activity would have it's own tab. The view comment text would be stored in either the main database configuration document or a special "translation" document that might enable multiple language capability. In the latter case, you could select a different language on the db config doc and have many of the standard labels change language in one go. That'll be for a future release though.

I will probably use your profile doc prefix approach on the environment variables as part of this effort, so thanks for sharing your experience Emoticon.

3 - Hi. I am looking out for a script / code to get top 10 entries in my Lotus Notes (v5) database. I would like to use this list in my website. Can someone please help me? PM me in case you need more details.

Your Host

KevinPettitt.jpg
Kevin Pettitt View Kevin Pettitt's profile on LinkedIn

Tools I Use

Idea Jam

Subscribe to This Blog

 Full Posts  Comments

MyYahoo
netvibes Add to Netvibes

Contact

Hosted by

OpenNTF

Disclaimer

This site is in no way affiliated, endorsed, sanctioned, supported, nor blessed by Lotus Software nor IBM Corporation, nor any of my past or future clients (although they are welcome to do so). The opinions, theories, facts, etc. presented here are my own and in no way represent any official pronouncement by me on behalf of any other entity.

© 2005-2017 Kevin Pettitt - all rights reserved as listed below.

Creative Commons License
Unless otherwise labeled by its originating author, the content found on this site is made available under the terms of an Attribution / NonCommercial / ShareAlike