NetHopper 3.0 DataViewer Plug-In API

Data Viewer Introduction

A Data Viewer implements user interface for displaying a particular kind of data. For instance, a JPEG viewer takes binary data of MIME type image/jpeg and displays it in a Newton view. An HTML viewer takes HTML text data and displays it in a Newton view..

The default Data Viewer plug-ins will be for plain text and HTML.

Note that all Data Viewers are contained within a parent "Container" view. The Container deals with scrolling events (up/down, left/right) and with opening, caching, and closing the Viewer at the appropriate times. The default Containers provided by NetHopper will likely also implement stationery hooks so that your Viewer won't need to deal with creating yet another stationery.

How NetHopper Uses a Data Viewer

The Data Viewer life cycle:

  1. Data Viewer frame is created in RAM using your data viewer as the _proto.
  2. Data Viewer is Instantiated. The client calls your Data Viewer's Instantiate method to allow you to prepare for being Opened.
  3. Data Viewer is Opened/Shown/Drawn/Hidden/Closed as usual for a view. The container view which contains your Viewer will deal with scrolling issues (up/down, left-right scrolling). Note: You should not perform cleanup during Close because your view might be subsequently re-opened. This is because the container in which your Data Viewer resides might optimize scrolling by caching Closed but valid Data Viewers and opening them at the appropriate times.
  4. Data Viewer is Disposed. This is after your Close method has been called. This gives you a chance to do any cleanup you might need to do. (Stuff you might not want to do at Close time since you might be re-opened).

Registration Methods

The NetHopper Registration Manager unit provides a method for registering Data Handlers. All Data Handlers must use this method to tell NetHopper they are installed:

RegistrationManager:RegMIMEDataViewer(viewerSym, infoFrame);

The viewerSym must be a symbol with your developer signature appended (ex: '|FooDataViewer:ALLPEN|) to avoid collisions.

infoFrame contains the following slots:

codeFrame This is a reference to a frame that implements all of the required Data Handler methods.

name This is a user-viewable string that will be used to name your Viewer for things like helping the user decide which viewers are activated.

types This slot should contain an array of MIME types supported, as described in "Specifying MIME Types" on page 7. This array is used by NetHopper to keep track of which MIME types are supported by your Viewer. NetHopper will only provide your Viewer with data of a type that you've claimed to support.

preferencesForm This slot should contain a reference to any preferences view template you might have for configuring your Viewer. This view might contain things like a color-depth picker for an image viewer. The default value is NIL, no preference view. If this slot exists and is non-NIL, this view will be displayed when the user picks "(name) Prefs" in the NetHopper preferences view. Note that this view template must use protoPrefsRollItem as its template and must have its overview slot set to the name of this prefs view as it should appear in the NetHopper prefs.

To unregister a Data Viewer, call the UnRegMIMEDataViewer method:

RegistrationManager:UnRegMIMEDataViewer(handlerSym);

This method removes the Viewer named by handlerSym from NetHopper's Data Viewer registry.

Data Viewer-Provided Methods

The Data Viewer needs to provide several methods, described below.

Instantiate

dataViewer:Instantiate(content)

This method provides your Data Viewer with the input stream from which you can read input data, and the original transaction request frame which yielded that data. In your Instantiate method you should prepare for being Opened, but you should not yet open any views. Also, it's a good idea to wait until you receive a Start call before actually reading input data.

Parameters:

content. This is a content specification frame:

{
type: a symbol,
cacheObject: a frame or NIL,
inputStream: an input stream or NIL,
mimeType: a mime type object,
transReq: transaction request frame which describes the content source
}

The slots are defined as follows:

type. Either 'cacheObject or 'stream. This slot contains a symbol. If the symbol is 'gotStream then the inputStream slot will contain a raw input stream. If the symbol is 'gotCacheObject then the cacheObject slot will contain a cache object which you placed in the cache. (See the Cache documentation for information on how to store an arbitrary object in the cache).

cacheObject. If type is 'cacheObject, then a reference to a frame, else NIL. If the data object being returned is a cache object, this slot contains a reference to the cache object. Otherwise, this slot is NIL.

inputStream. If type is 'stream, then a reference to an input stream, else NIL. If the data object being returned is an input stream, this slot contains a reference to the input stream. Otherwise, this slot is NIL.

mimeType. The MIME type of the data. This is provided for the case where the content is cacheObject, since there's no way to tell the MIME type of an ordinary frame.

transReq. A transaction request frame which describes the source of the content, and may include information such as the content title.

Note: You only need to handle cache objects if your viewer slams arbitrary objects into the cache. If you do not place any data in the cache, or if you place raw stream data into the cache, you will only ever receive an input stream in this method.

Start

The Viewer's client calls this method to start the Viewer processing the input data. You should generally wait until you receive this call to start processing content.

dataViewer:Start(cbContext, cbMethod);

When your Viewer is done with the transaction request handed in Instantiate, call the callback method with a result code (NIL for no error, or an integer error code).

Stop

Your client will call this method to stop a document processing in progres. This method will typically be called before Start completes. If it's called after Start completes, this method is essentially a no-op.

SetMaxBounds

This method sets the absolute maximum bounds that your Data Viewer can occupy. Typically the container containing your Data Viewer calls this method with a fixed width, but it can conceivably call it with both a fixed width and height.

dataViewer:SetMaxBounds(boundsFrame);

Where the boundsFrame is a typical viewBounds frame, except that top and left are set to 0, and right and bottom are the max width and height, respectively.

View Methods

Open/Close/Show/Hide/viewDrawScript All of the usual view methods...A Data Viewer is a view!

FindKeywordStr

This method is optional. If your viewer supports find it should return the number of times the keyword string was found in your viewer's content. If you return a nonzero value then it's likely your DisplayNextFoundItem method will subsequently be called.

local int numHits := dataViewer:FindKeywordStr("keyword");

If your Viewer cannot find any instances of the keyword then it should return zero.

DisplayNextFoundItem

This method is optional. If your viewer supports find, this method may be called after your FindKeywordStr method returns nonzero.

dataViewer:DisplayNextFoundItem();

If this method is called and you've reached the limit of the found items in your Viewer, then simply wrap back to the first item.

GetHeadings

If your Viewer supports the concept of "headings", then you should a frame containing two slots:

items. An array of heading strings which will be displayed to the user.

objects.An array of heading objects which will be used to hand you back a magic cookie to allow you to goto the correct heading. (See GotoHeading) These objects can be any arbitrary data structure you choose, but they should correspond to the strings in the item list.

GotoHeading

This method is passed a single parameter: one of the heading objects you provided as a result to GetHeadings. Your viewer should scroll (or whatever) to show the heading.

Dispose

Dispose() This method is called when the container around your Data Viewer is completely finished with your Data Viewer. When you receive this message, you should completely release any resources you allocated to operate your viewer, and you should release your reference to the inputStream.

URL-Handling Methods Provided by Viewer's Container

DispatchRawURL

This method may be provided by a Data Viewer's "container" view to handle URL requests that the viewer may generate (for instance, when the user taps on a hyperlink in the view).

Because this method may or may not be present, the viewer should call it as follows:

:?DispatchRawURL(URLstring);

This method's return value is undefined, and there is no callback mechanism. Once your viewer calls this method, it can assume the URL string was either handled or dropped on the floor.

ReflowView

Send

self:Parent():?ReflowView();

to tell your parent when you need to change your viewBounds.

SetTransactionStatus

You can use this method to tell your parent your status. This status may be displayed to the end user.

self:Parent():?SetTransactionStatus(self, paramFrame);

Always pass self as the first parameter.

paramFrame is a frame containing the following slots:

icon. A bitmap icon to display to the user, if any.

titleText. A string to be displayed in the title area of a status display view, if any.

statusText. A string to be displayed in the status area of a status display view, if any.

gauge. A numeric value which will be translated into a 0 to 100 progress gauge.

When you're done passing status to your parent, you should call:

self:Parent():?SetTransactionStatus(self, NIL);

This notifies your parent that you no longer need to display status.