« Nathan ripples the walls | Main| Reverse API using local objects as method containers »

SnTT: There is No Spoon

Category show-n-tell thursday


In case you've been wondering what's so exciting - indeed, revolutionary - about The Revolution, I decided to whip up a quick example of a possible use case for this technique: I call it the "In-Memory Placeholder Manager" (sample database available for download). It allows users to temporarily flag documents for later retrieval... I was going to call them "bookmarks" instead, but changed the term for two reasons:
  1. The term "bookmark" would be misleading, because these aren't the same as Notes bookmarks (stored in bookmark.nsf) or browser bookmarks, both of which are written to disk... this is entirely in-memory, stored for the entirety of a user's session in the database, but immediately discarded when the database is closed.
  2. "Placeholder" is apt (in my opinion) because this is exactly what Nathan's technique allows: a true object pointer shared across UI contexts. This can hold anything - for example, product objects (i.e. NotesSession, NotesDatabase), ActiveX objects, and instances of user-defined classes, whether they be base classes or derived.
The basic idea I'm envisioning here is a knowledge base application, where users navigate between documents and may identify a topic they want to revisit later in the same session but not necessarily during later visits to the application. This might not be a terribly useful feature, but it does demonstrate how information that would otherwise need to be written to disk somewhere in order to be accessible from both views and documents can be passed between them.

To get your head around what's going on here, first (if you haven't already) read Nathan's explanation of this technique - especially Part 2. He outlines exactly how we can establish a handle on an object in one context and then hand it off to another, like some weird programmatic relay runner. The key, I feel, is that the object he's passing has a public cache property Dim'ed as a Variant, so once it's instantiated, anything can be crammed in there.

But in keeping with my rebellious nature, I wanted just a little bit more... so in the sample code for this post, you'll see that I've changed the cache member to a private List, and added getObject and injectObject methods to the ContextWrapper class. The end result is that we can pass as many objects as we want... without necessarily having to know in advance what those objects will be. What makes me a bit dizzy is that, since it's the List's container we're sharing, new objects can be passed after we've already established the handle. For example, the view could get a handle on some other database and pass it to a document in the same database as the view... and then the document could launch a view in the database that it was passed a handle to... then, perhaps, a user would select some documents in that view and click a button, which would inject a NotesDocumentCollection containing those documents into the shared object. At that point, the original view and the document opened from that view both have a handle on that document collection and, as an additional benefit of remotely bound events (see Part 1), the document and / or view can act on those documents without the view containing them even having to tell them to. Yeah, I know, mind-bending stuff. My brain's been tingling since Friday morning, with no signs of stopping any time soon. Don't worry, it's not a tumor.

Oh... yeah, one more thing: since all of this wacky object passing relies upon remotely bound events, the sample database requires that the view have a handle on any open document in order to pass the shared object to it. So I added a little bit of hijackery to the QueryOpendocument event of the view. It sets Continue to False, which prevents the document from opening. Although that would seem to defeat the purpose, when the event is triggered, we're given a handle on the document to be opened, so we can open it in such a way that we get a handle on the corresponding NotesUIDocument and can then bind its QueryRecalc event, and in turn, trigger that event, which ensures the shared object is passed:

Sub Queryopendocument(Source As Notesuiview, Continue As Variant)
Let Continue = False 'We hijack the open so we can trigger an auto-recalc
Call openBoundDocument(Source.Documents.GetFirstDocument())
End Sub

Public Sub openBoundDocument(p_docBinding As NotesDocument)
Set uiContainer = myCache.wrkSpc.EditDocument(True,p_docBinding)
On Event queryRecalc From uiContainer Call remoteDocQueryRecalc
Call uiContainer.Refresh()
Let uiContainer.EditMode = False
End Sub


Huzzah.

By the way, ever since Nathan told me about ColourLovers.com, I've been itching to use the Pigs in Space theme in a non-production application, so please excuse the gratuitous excess of color in the sample database for this post. I'm sure the next sample I post for download will be as predictably bland as most of what I've shared with y'all.

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)

Contact Me

Hire Me

Elsewhere

What the Quote?

"Of course they still make Tang. Whaddaya think the astronauts drink?"

Steven Rodgers

"Papa Felpie's? That's an odd name for a restaurant."

Brent Bowers

"Dance, my puppets!!! DANCE!!!"

Nathan Freeman

"Wow, that's depressing. But hey, that's death. And this is broccoli. [Belch]"

Tim Tripcony

"It's hard to tell, when you have three legs."

Laura Tripcony

Apparel

Lotus Rocks

I write the code that makes the young girls cry

Current Terror Alert Level

Assorted Linkage

ClustrMap