Creating Preview Components

This chapter describes how to create your own preview component. A listing of a sample component is included.

Overview

Preview components that create previews have a type of 'pmak' and a subtype that matches the type of the file for which they create previews.

Preview components that display previews have a type of 'pnot' and a subtype that matches the type of the resource that they display.

You can use the following constants to refer to the request codes for each of the functions that your preview component must support.

enum {
  kPreviewShowDataSelector             = 1, /* PreviewShowData */
  kPreviewMakePreviewSelector          = 2, /* PreviewMakePreview */
  kPreviewMakePreviewReferenceSelector = 3, /* PreviewMakePreviewReference */
  kPreviewEventSelector                = 4  /* PreviewEvent */
};

This section presents a sample program that displays a preview component for the display of PICS animation files. First it implements the required Component Manager functions. Then it converts the PICT image data into a format for display as a preview.

Implementing Required Component Functions

Listing 5-1 supplies the component dispatchers for the preview component together with the can do, version, open, and close functions.

Listing 5-1  Implementing the required Component Manager functions

typedef struct {
    ComponentInstance       self;
} PICSPreviewRecord, **PICSPreviewGlobals;
 
/* entry point for all Component Manager requests */
pascal ComponentResult PICSPreviewDispatch
                            (ComponentParameters *params, Handle store)
{
    OSErr err = badComponentSelector;
    ComponentFunction componentProc = 0;
 
    switch (params->what) {
        case kComponentOpenSelect:
            componentProc = PICSPreviewOpen; break;
        case kComponentCloseSelect:
            componentProc = PICSPreviewClose; break;
        case kComponentCanDoSelect:
            componentProc = PICSPreviewCanDo; break;
        case kComponentVersionSelect:
            componentProc = PICSPreviewVersion; break;
        case kPreviewShowDataSelector:
            componentProc = PICSPreviewShowData; break;
    }
 
    if (componentProc)
        err = CallComponentFunctionWithStorage (store, params,
                                                componentProc);
    return err;
}
 
pascal ComponentResult PICSPreviewCanDo
                            (PICSPreviewGlobals store, short ftnNumber)
{
    switch (ftnNumber) {
        case kComponentOpenSelect:
        case kComponentCloseSelect:
        case kComponentCanDoSelect:
        case kComponentVersionSelect:
        case kPreviewShowDataSelector:
           return true;
       default:
           return false;
    }
}
 
pascal ComponentResult PICSPreviewVersion
                         (PICSPreviewGlobals store)
{
    return 0x00010001;
}
 
pascal ComponentResult PICSPreviewOpen (PICSPreviewGlobals store,
                                         ComponentInstance self)
{
    store = (PICSPreviewGlobals)NewHandle
                          (sizeof (PICSPreviewRecord));
    if (!store) return MemError();
    SetComponentInstanceStorage (self, (Handle)store);
    (**store).self = self;
 
    return noErr;
}
 
pascal ComponentResult PICSPreviewClose
                       (PICSPreviewGlobals store,
                         ComponentInstance self)
{
    if (store) DisposeHandle ((Handle)store);
    return noErr;
}

Displaying Image Data as a Preview

To display a file’s image preview, your PreviewShowData function is called. Listing 5-2 includes the PICSPreviewShowData function, which previews a PICS file. The function loads the first PICT image from the PICS file and uses the PICT file preview component to display it.

Listing 5-2  Converting data into a form that can be displayed as a preview

pascal ComponentResult PICSPreviewShowData(
            PICSPreviewGlobals store, OSType dataType, Handle data,
            const Rect *inHere)
{
    OSErr err = noErr;
    short resRef = 0, saveRes = CurResFile();
    FSSpec theFile;
    Boolean whoCares;
    Handle thePict = nil;
    ComponentInstance ci;
 
    /* because your component has the pnotComponentNeedsNoCache
        flag set, it should only be called to display files */
    if (dataType != rAliasType)
        return paramErr;
 
    /* open up the file to preview */
    if (err = ResolveAlias (nil, (AliasHandle)data, &theFile,
                               &whoCares)) goto bail;
    resRef = FSpOpenResFile (&theFile, fsRdPerm);
    if (err = ResError()) goto bail;
 
    /* get the first 'PICT' */
    UseResFile (resRef);
    thePict = Get1IndResource ('PICT', 1);
    if (!thePict) goto bail;
 
    /* use the PICT preview component to display the preview */
    if (ci = OpenDefaultComponent (ShowFilePreviewComponentType, 'PICT'))
    {
        PreviewShowData (ci, 'PICT', thePict, inHere);
        CloseComponent (ci);
    }
 
bail:
    if (resRef) CloseResFile (resRef);
    if (thePict) DisposeHandle (thePict);
    UseResFile (saveRes);
    return err;
}