home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / NeoIntroTCL3.0 folder / TCL / NeoDemo / Source / CNeoDemoDoc.cp < prev    next >
Encoding:
Text File  |  1994-08-29  |  23.1 KB  |  965 lines  |  [TEXT/KAHL]

  1. /****
  2.  * CNeoDemoDoc.c
  3.  *
  4.  *    Document methods for a typical application.
  5.  *
  6.  *  Copyright © 1992 NeoLogic Systems.  All rights reserved.
  7.  *
  8.  ****/
  9.  
  10. #include "NeoTypes.h"
  11. #include <string.h>
  12. #include <Packages.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <Timer.h>
  16. #include "Global.h"
  17. #include "Constants.h"
  18. #include "CError.h"
  19. #include "Commands.h"
  20. #include "CDesktop.h"
  21. #include "CBartender.h"
  22. #include "CScrollBar.h"
  23. #include "CPopupMenu.h"
  24. #include "CDecorator.h"
  25. #include CNeoMetaClassH
  26. #include CNeoDatabaseNativeH
  27. #include "CNeoScrapStream.h"
  28. #include "CNDCamera.h"
  29. #include "CNDImagePICT.h"
  30. #include "CNDImageTIFF.h"
  31. #include "CNDImageGIF.h"
  32. #include "CNeoDemoDoc.h"
  33. #include "CNDPicture.h"
  34. #include "CNDFilePicture.h"
  35. #include "CNeoDialogText.h"
  36. #include "CNeoDLOGDialog.h"
  37. #include "CNeoDemoApp.h"
  38. #include "CNeoPopupPane.h"
  39. #include "CNeoDemoScrollPane.h"
  40.  
  41. #define        kNeoDemoDialog                    1000    // resource ID of dialog
  42.  
  43. #define kMaxSSpeeds                            10
  44. short    sSpeedCnt                            = 0;
  45. short    sSpeedMenu2IDTable[kMaxSSpeeds]        = {0};
  46.  
  47. static Boolean    gMarkDirty = TRUE;
  48.  
  49. extern    CBartender    *    gBartender;        /* The menu handling object */
  50. extern    CDecorator    *    gDecorator;        /* Window dressing object    */
  51. extern    CDesktop    *    gDesktop;        /* The enclosure for all windows */
  52. extern    CBureaucrat    *    gGopher;        /* The current boss in the chain of command */
  53.  
  54. /***
  55.  * CNeoDemoDoc
  56.  *
  57.  *    This is your document's initialization method.
  58.  *    If your document has its own instance variables, initialize
  59.  *    them here.
  60.  *
  61.  *    The least you need to do is invoke the default method.
  62.  *
  63.  ***/
  64. CNeoDemoDoc::CNeoDemoDoc(CApplication *aSupervisor, const Boolean aPrintable, const Boolean aNewFile, const Boolean aRemote)
  65. #ifdef qNeoShare
  66.     : CNeoDocShareTCL(kNeoDemoSig, kNeoDemoFileType, aPrintable, aNewFile, aRemote)
  67. #else
  68.     : CNeoDocTCL(kNeoDemoSig, kNeoDemoFileType, aPrintable, aNewFile, TRUE, aRemote)
  69. #endif
  70. {
  71.     short            index;
  72.     CArray *        array;
  73.     CNeoDatabase *        file;
  74.  
  75.     /* set up the image array */
  76.     array = new (CArray);
  77.     fImageArray = array;
  78.     array->IArray(sizeof(NeoID));
  79.  
  80.     fIndex = 0;
  81.     fSelectKey = nil;
  82. }
  83.  
  84. CNeoDemoDoc::~CNeoDemoDoc(void)
  85. {
  86.     if (fImageArray) {
  87.         emptyImageArray();
  88.         delete fImageArray;
  89.         fImageArray = nil;
  90.     }
  91.  
  92.     if (fSelectKey) {
  93.         delete fSelectKey;
  94.         fSelectKey = nil;
  95.     }
  96. }
  97.  
  98. /***
  99.  * buildWindow
  100.  *
  101.  *    This is the auxiliary window-building method that the
  102.  *    NewFile() and OpenFile() methods use to create a window.
  103.  *
  104.  ***/
  105.  
  106. void CNeoDemoDoc::buildWindow(void)
  107.  
  108. {
  109.     CNeoDLOGDialog    *dlog;
  110.  
  111.         /**
  112.          **    First create the window and initialize
  113.          **    it. The first argument is the resource ID
  114.          **    of the window. The second argument specifies
  115.          **    whether the window is a floating window.
  116.          **    The third argument is the window's enclosure; it
  117.          **    should always be gDesktop. The last argument is
  118.          **    the window's supervisor in the Chain of Command;
  119.          **    it should always be the Document object.
  120.          **
  121.          **/
  122.  
  123.     dlog = new CNeoDLOGDialog(kNeoDemoDialog, gDesktop, this);
  124.     itsWindow = dlog;
  125.  
  126.     // set the main pane to the dialog panorama
  127.     itsMainPane = (CPane*) dlog->FindViewByID(kDialogPanoramaID);
  128.  
  129.     itsGopher = itsMainPane;
  130.  
  131.         /**
  132.          ** Use CenterWindow to center the window in the middle
  133.          ** of the screen.
  134.          **/
  135.  
  136.     gDecorator->CenterWindow(itsWindow);
  137.  
  138.     inherited::buildWindow();
  139. }
  140.  
  141. /***
  142.  * DoSave
  143.  *
  144.  *    This method handles what happens when the user chooses Save from the
  145.  *    File menu. This method should return TRUE if the file save was successful.
  146.  *    If there is no file associated with the document, you should send a
  147.  *    DoSaveFileAs() message.
  148.  *
  149.  ***/
  150.  
  151. Boolean CNeoDemoDoc::DoSave(void)
  152. {
  153.     CNDImage *    image;
  154.  
  155.     if (itsWindow &&
  156.         fIndex) {
  157.         image = getImage(fIndex);
  158.         if (image) {
  159.             updateImage(image);
  160.             image->unrefer();
  161.         }
  162.     }
  163.  
  164.     return inherited::DoSave();
  165. }
  166.  
  167.  
  168. /***
  169.  * NewFile
  170.  *
  171.  *    When the user chooses New from the File menu, the createDocument()
  172.  *    method in your Application class will send a newly created document
  173.  *    this message. This method needs to create a new window, ready to
  174.  *    work on a new document.
  175.  *
  176.  *    Since this method and the OpenFile() method share the code for creating
  177.  *    the window, you should use an auxiliary window-building method.
  178.  *
  179.  ***/
  180. void CNeoDemoDoc::NewFile(void)
  181. {
  182.     short            exposures[10];
  183.     CNDCamera *        camera;
  184.     CNeoDatabase *    file;
  185.  
  186.     inherited::NewFile();
  187.  
  188.     /**
  189.      ** Add application-specific classes to the file
  190.      **/
  191.     if (fNewDatabase) {
  192.         file = ((CNeoDatabase *)itsFile);
  193.  
  194.         exposures[0] = -500;        /* 1/500 */
  195.         exposures[1] = -125;        /* 1/125 */
  196.         exposures[2] = -64;            /* 1/64 */
  197.         exposures[3] = -32;            /* 1/32 */
  198.         exposures[4] = -16;            /* 1/16 */
  199.         exposures[5] = -8;            /* 1/8 */
  200.         exposures[6] = -4;            /* 1/4 */
  201.         exposures[7] = -2;            /* 1/2 */
  202.         exposures[8] = 1;            /* 1 */
  203.         camera = new CNDCamera("\pCanon", 9, exposures);
  204.         camera->fID = 1;
  205.         file->addObject(camera);
  206.         camera->unrefer();
  207.  
  208.         exposures[0] = -1000;        /* 1/1000 */
  209.         exposures[1] = -500;        /* 1/500 */
  210.         exposures[2] = -125;        /* 1/125 */
  211.         exposures[3] = -64;            /* 1/64 */
  212.         exposures[4] = -16;            /* 1/16 */
  213.         exposures[5] = -4;            /* 1/4 */
  214.         exposures[6] = 1;            /* 1 */
  215.         camera = new CNDCamera("\pHasselblad", 7, exposures);
  216.         camera->fID = 2;
  217.         ((CNeoDatabase *)itsFile)->addObject(camera);
  218.         camera->unrefer();
  219.  
  220.         exposures[0] = -125;        /* 1/125 */
  221.         camera = new CNDCamera("\pKodak", 1, exposures);
  222.         camera->fID = 3;
  223.         file->addObject(camera);
  224.         camera->unrefer();
  225.  
  226.         exposures[0] = -1000;        /* 1/1000 */
  227.         exposures[1] = -500;        /* 1/500 */
  228.         exposures[2] = -125;        /* 1/125 */
  229.         exposures[3] = -64;            /* 1/64 */
  230.         exposures[4] = -32;            /* 1/32 */
  231.         exposures[5] = -16;            /* 1/16 */
  232.         exposures[6] = -8;            /* 1/8 */
  233.         exposures[7] = -4;            /* 1/4 */
  234.         exposures[8] = -2;            /* 1/2 */
  235.         exposures[9] = 1;            /* 1 */
  236.         camera = new CNDCamera("\pNikon", 10, exposures);
  237.         camera->fID = 4;
  238.         file->addObject(camera);
  239.         camera->unrefer();
  240.     }
  241.  
  242.     buildCameraMenu();
  243.     setItems(nil);    /* initialize picture to empty & all strings to empty */
  244. }
  245.  
  246.  
  247. /***
  248.  * OpenFile
  249.  *
  250.  *    When the user chooses Open… from the File menu, the OpenDocument()
  251.  *    method in your Application class will let the user choose a file
  252.  *    and then send a newly created document this message. The information
  253.  *    about the file is in the SFReply record.
  254.  *
  255.  *    In this method, you need to open the file and display its contents
  256.  *    in a window. This method uses the auxiliary window-building method.
  257.  *
  258.  ***/
  259.  
  260. void CNeoDemoDoc::OpenFile(SFReply *macSFReply)
  261. {
  262.     NEOTRY
  263.     {
  264.         fOpenMode = fsRdWrPerm;
  265.         inherited::OpenFile(macSFReply);
  266.  
  267.         buildCameraMenu();
  268.         setSelectionByKeyword(kNDImageID, "");
  269.  
  270.         itsWindow->Select();            /* Don't forget to make the window active */
  271.     }
  272.  
  273.     NEOCATCH
  274.     {
  275.         /*
  276.          * This exception handler will be executed if an exception occurs
  277.          * anywhere within the scope of the TRY node above.
  278.          * You should perform any cleanup of things that won't be needed
  279.          * since the document could not be opened. By convention,
  280.          * the creator of an object is responsible for sending it
  281.          * the unrefer message. This means that we should only dispose
  282.          * of things that would not be taken care of in unrefer.
  283.          * In this case, we just make sure that the Handle theData
  284.          * has been disposed of. The exception will propagate up to
  285.          * CApplications's exception handler, which handles displaying
  286.          * an error alert.
  287.          */
  288.     }
  289.     NEOENDTRY;
  290. }
  291.  
  292.  
  293. /***
  294.  * UpdateMenus
  295.  *
  296.  *  In this method you can enable menu commands that apply when
  297.  *  your document is active.
  298.  *
  299.  *  Be sure to call the inherited method to get the default behavior.
  300.  *  The inherited method enables these commands: cmdClose, cmdSaveAs,
  301.  *  cmdSave, cmdRevert, cmdPageSetup, cmdPrint, cmdUndo.
  302.  *
  303. ***/
  304.  
  305.  void CNeoDemoDoc::UpdateMenus()
  306.  
  307.  {
  308.   inherited::UpdateMenus();
  309.  
  310.     /* Enable your menu commands here (enable each one with a call to
  311.        gBartender->EnableCmd(command_number)).
  312.     */
  313.   gBartender->EnableCmd(cmdCut);
  314.   gBartender->EnableCmd(cmdCopy);
  315.   gBartender->EnableCmd(cmdPaste);
  316.   gBartender->DisableCmd(cmdRevert);
  317.   gBartender->DisableCmd(cmdUndo);
  318.  
  319.  }
  320.  
  321. void CNeoDemoDoc::Zoom(Boolean aOut)
  322. {
  323.     fSignal->Zoom(aOut);
  324. }
  325.  
  326. /* Rebuild the camera menu */
  327. void CNeoDemoDoc::buildCameraMenu(void)
  328. {
  329.     short        index;
  330.     MenuHandle    menu = fPopBody->GetMenu()->GetMacMenu();
  331.  
  332.     /* delete all items in the exposures menu except "Unknown" */
  333.     for (index = CountMItems(menu); index > 1; index--)
  334.         DelMenuItem(menu, index);
  335.     CNDCamera::ClearCameraTable();
  336.  
  337.     CNeoPersist::FindEvery(((CNeoDatabase *)itsFile), kNDCameraID, FALSE, (NeoTestFunc1)CNDCamera::MakeCameraMenu, (void *)menu);
  338. }
  339.  
  340. /* Rebuild the shutter speed menu */
  341. void CNeoDemoDoc::buildShutterMenu(const NeoID aCameraID)
  342. {
  343.     short        index;
  344.     short        count;
  345.     short        item;
  346.     float        shutter;
  347.     MenuHandle    menu;
  348.     CNDCamera *    camera;
  349.     CNeoString    string;
  350.  
  351.     /* delete all items in the exposures menu except "Unknown" */
  352.     NeoFailNil(menu = fPopExposure->GetMenu()->GetMacMenu());
  353.     for (index = CountMItems(menu); index > 1; index--)
  354.         DelMenuItem(menu, index);
  355.  
  356.     if (aCameraID) {
  357.         camera = (CNDCamera *)CNeoPersist::FindByID((CNeoDatabase *)itsFile, kNDCameraID, aCameraID, FALSE, nil, nil);
  358.         if (!camera)
  359.             return;
  360.  
  361.         count = camera->getShutterCount();
  362.         for (index = 0; index < count; index++) {
  363.             if (index < kMaxSSpeeds) {
  364.                 item = index +2;
  365.                 shutter = camera->getShutter(index);
  366.                 sSpeedMenu2IDTable[index] = shutter;
  367.                 if (shutter > 0) {
  368.                     if (shutter == 1)
  369.                         string[0] = sprintf((char *)&string[1],"1 Sec.");
  370.                     else
  371.                         string[0] = sprintf((char *)&string[1],"%ld Secs.", (long)shutter);
  372.                 }
  373.                 else
  374.                     string[0] = sprintf((char *)&string[1],"1/%ldth Sec.", (long)-shutter);
  375.                 AppendMenu(menu, "\pfoo");
  376.                 SetItem(menu, item, string);
  377.                 if (shutter == -125) {                    /* make 1/125 the default */
  378.                     fPopExposure->SelectItem(item, pmForceOn);
  379.                     fPopExposure->NewMenuSelection(item);
  380.                 }
  381.             }
  382.         }
  383.         sSpeedCnt = count;
  384.         camera->unrefer();
  385.     }
  386. }
  387.  
  388. Boolean CNeoDemoDoc::doCutCopy(const Boolean aCut)
  389. {
  390.     Boolean            pass    = TRUE;
  391.     Handle            scrap    = nil;
  392.     CNDImage *        image;
  393.     CNeoScrapStream    stream('IMGE');        // stream object that reads images
  394.  
  395.     if (!fIndex)                        // If there is no current image
  396.         return pass;                    // then there is nothing to do.
  397.  
  398.     image = getImage(fIndex);            // Get the current image.
  399.     if (image) {                        // It better be there!
  400.         updateImage(image);                // Just in case user has changed it.
  401.  
  402.         image->writeObject(&stream, kNeoAllTag);    // Write it to scrap.
  403.  
  404.         if (aCut) {                        // Is this a Cut operation?
  405.             ((CNeoDatabase*)itsFile)->removeObject(image);
  406.             removeImage(fIndex);        // Remove the image from the file.
  407.         }
  408.         image->unrefer();                // Remove our reference to it.
  409.         pass = FALSE;                    // No need to pass this command on.
  410.     }
  411.  
  412.     return pass;
  413. }
  414.  
  415. Boolean CNeoDemoDoc::doPaste(void)
  416. {
  417.     Boolean            pass    = TRUE;
  418.     long            length;
  419.     Handle            scrap;
  420.     PicHandle        pict;
  421.     CNDImage *        image;
  422.     CNeoScrapStream    stream('IMGE');
  423.  
  424.     if (fIndex > 0)
  425.         updateImage(nil);
  426.  
  427.     switch(getImageType()) {
  428.         case kNDImage:                                /* use a default type */
  429.         case kNDImagePICT:
  430.             image = (CNDImage*)new CNDImagePICT;
  431.             break;
  432.  
  433.         case kNDImageTIFF:
  434.             image =(CNDImage*) new CNDImageTIFF;
  435.             break;
  436.  
  437.         case kNDImageGIF:
  438.             image = (CNDImage*)new CNDImageGIF;
  439.             break;
  440.     }
  441.  
  442.     image->fID = ((CNeoDatabase *)itsFile)->getUniqueID();
  443.     fIndex++;                                        /* make new image object after current one being viewed */
  444.     fImageArray->InsertAtIndex(&image->fID, fIndex);/* insert object into doc's image array */
  445.     image->setDirty();                                /* set dirty so that updateImage really works */
  446.     dirty = TRUE;                                    /* Mark document dirty as well. */
  447.     inherited::UpdateMenus();
  448.     if (fIndex == 1)
  449.         updateImage(image);
  450.  
  451.     image->readObject(&stream, kNeoAllTag);
  452.  
  453.     pict = (PicHandle)image->getBlob();
  454.     if (pict) {
  455.         showBorders(TRUE);
  456.         ((CNeoDatabase *)itsFile)->addObject(image);    // add it to file
  457.         setItems(image);                            // OK, so let's see it
  458.         pass = FALSE;                                // no need to pass it on
  459.     }
  460.     else {                                            // false paste
  461.         fImageArray->DeleteItem(fIndex);            // remove from array
  462.         fIndex--;                                    // go back to previous
  463.     }
  464.     image->unrefer();                                // remove reference
  465.  
  466.     return pass;
  467. }
  468.  
  469. void CNeoDemoDoc::emptyImageArray(void)
  470. {
  471.     short        index;
  472.  
  473.     if (fImageArray &&
  474.         fImageArray->numItems)
  475.         for (index = fImageArray->numItems; index > 0; index--)
  476.             fImageArray->DeleteItem(index);
  477. }
  478.  
  479. NeoID CNeoDemoDoc::getCameraID(void)
  480. {
  481.     NeoID        id;
  482.     CNDImage *    image;
  483.  
  484.     if (fIndex) {
  485.         image = getImage(fIndex);
  486.         NeoAssert(image);
  487.         id = image->fCamera;
  488.         image->unrefer();
  489.     }
  490.     else
  491.         id = 0;
  492.  
  493.     return id;
  494. }
  495.  
  496. CNDImage *CNeoDemoDoc::getImage(const short aIndex)
  497. {
  498.     NeoID        id;
  499.  
  500.     NeoAssert(aIndex >= 0 && aIndex <= fImageArray->numItems);
  501.  
  502.     fImageArray->GetArrayItem(&id, aIndex);
  503.  
  504.     return (CNDImage *)CNeoPersist::FindByID((CNeoDatabase*)itsFile, kNDImageID, id, TRUE, nil, nil);
  505. }
  506.  
  507. short CNeoDemoDoc::getImageCount(void)
  508. {
  509.     return fImageArray->numItems;
  510. }
  511.  
  512. /* return item# of type selected in dialog popup menu */
  513. short    CNeoDemoDoc::getImageType(void)
  514. {
  515.     /* 1=PICT  2=TIFF  3=GIF  4=Any */
  516.     return fPopObj->GetCheckedItem();
  517. }
  518.  
  519. void CNeoDemoDoc::gotoImage(short aIndex, const Boolean aRedraw)
  520. {
  521.     Boolean            update;
  522.     CNDImage *        image;
  523.     CBureaucrat *    gopher;
  524.  
  525.     if (fIndex == aIndex)
  526.         return;
  527.  
  528.     fIndex = aIndex;
  529.  
  530.     NeoAssert(aIndex <= fImageArray->numItems);
  531.     if (!aIndex) {                                /* may not be any image objects */
  532.         setItems(nil);
  533.         return;
  534.     }
  535.  
  536.     // Hide text edit borders
  537.     showBorders(FALSE);
  538.  
  539.     // Make the dialog the gopher (to turn caret blinking off).
  540.     if (gGopher &&
  541.         itsMainPane == gGopher) {
  542.         gopher = gGopher;
  543.         gGopher->BecomeGopher(FALSE);
  544.         gopher->itsSupervisor->BecomeGopher(TRUE);
  545.     }
  546.  
  547.     image = getImage(aIndex);
  548.     if (image) {                                /* retrieve image object from image array */
  549.         gMarkDirty = FALSE;
  550.         setItems(image);
  551.         gMarkDirty = TRUE;
  552.         image->unrefer();
  553.     }
  554.  
  555.     if (aRedraw)
  556.         itsWindow->Update();
  557. }
  558.  
  559. /* Return a keyword select key that matches the specified keyword value.
  560.  */
  561. CNeoKeywordSelect *CNeoDemoDoc::getKeywordKey(char *aKeyword)
  562. {
  563.     short            index;
  564.     char            keyword[33];
  565.  
  566.     /* Translate the keyword to lower case */
  567.     for (index = 0; aKeyword[index]; index++)
  568.         if (aKeyword[index] >= 'A' &&
  569.             aKeyword[index] <= 'Z')
  570.             keyword[index] = aKeyword[index] +32;
  571.         else
  572.             keyword[index] = aKeyword[index];
  573.     keyword[index] = 0;
  574.  
  575.     if (fSelectKey)
  576.         fSelectKey->setKeyword(keyword);
  577.     else
  578.         NeoFailNil(fSelectKey = CNDImage::GetKeywordKey(keyword));
  579.  
  580.     return fSelectKey;
  581. }
  582.  
  583. void CNeoDemoDoc::removeImage(const short aIndex)
  584. {
  585.     Boolean        redraw    = FALSE;
  586.     short        index;
  587.     Str255        str;
  588.  
  589.     fImageArray->DeleteItem(aIndex);                /* gone from current list */
  590.  
  591.     if (fIndex == aIndex) {
  592.         redraw = TRUE;
  593.         if (fIndex > fImageArray->numItems)
  594.             fIndex = fImageArray->numItems;
  595.     }
  596.     else if (aIndex < fIndex)
  597.         fIndex--;
  598.  
  599.     fScrollObj->itsHorizSBar->SetMaxValue(fImageArray->numItems -1);    /* adjust scroll bar limit */
  600.     fScrollObj->itsHorizSBar->SetValue(fIndex -1);
  601.     fScrollObj->Refresh();
  602.  
  603.     /* set static text object for "<picture#> / <max#>"  */
  604.     str[0] = sprintf((char *)&str[1], "%ld / %ld", (long)fIndex, (long)fImageArray->numItems);
  605.     fTextInfo->SetTextString(str);
  606.     fTextInfo->Refresh();
  607.  
  608.     dirty = TRUE;                                    /* Mark document dirty as well. */
  609.  
  610.     if (redraw) {
  611.         inherited::UpdateMenus();
  612.         index = fIndex;
  613.         fIndex = -1;                                /* invalidate fIndex so that gotoImage redraws */
  614.         gotoImage(index, FALSE);                    /* get one after deleted image on screen */
  615.     }
  616. }
  617.  
  618. void CNeoDemoDoc::setCameraID(const NeoID aID)
  619. {
  620.     Boolean            found    = FALSE;
  621.     short            item    = aID;
  622.     short            max;
  623.     short            index;
  624.  
  625.     if (item) {
  626.         max = fPopBody->GetMenu()->GetNumItems() +1;
  627.         if (item)
  628.             for (index = 2; index < max; index++)            // one-based indexing with the first being the "unknown" menu item
  629.                 if (CNDCamera::GetCameraID(index) == item) {
  630.                     item = index;
  631.                     found = TRUE;
  632.                     break;
  633.                 }
  634.         if (!found)
  635.             item = 1;                                // select "Unknown"
  636.     }
  637.     else
  638.         item = 1;
  639.  
  640.     if (fPopBody->GetCheckedItem() != item) {
  641.         fPopBody->SelectItem(item, pmForceOn);
  642.         fPopBody->NewMenuSelection(item);
  643.  
  644.         /* Rebuild the shutter speed menu */
  645.         buildShutterMenu(aID);
  646.     }
  647.     fPopBody->Refresh();
  648. }
  649.  
  650. void CNeoDemoDoc::setImageDirty(CCollaborator *aProvider, void* aParam, const Boolean aMenu)
  651. {
  652.     short            item;
  653.     NeoID            cameraID;
  654.     CNDImage *        image;
  655.     CNeoDatabase *    database;
  656.  
  657.     if (aMenu) {
  658.         item = *(short *)aParam;
  659.         if (!item)
  660.             return;
  661.  
  662.         if ((CPopupPane *)aProvider == fPopBody) {
  663.             if (item > 1)
  664.                 cameraID = CNDCamera::GetCameraID(item);
  665.             else
  666.                 cameraID = 0;
  667.             buildShutterMenu(cameraID);
  668.         }
  669.         if (!gMarkDirty)
  670.             return;
  671.     }
  672.  
  673.     if (fIndex &&
  674.         fIndex <= fImageArray->numItems) {
  675.         image = getImage(fIndex);
  676.         if (image) {
  677.             database = gNeoDatabase;
  678.             gNeoDatabase = (CNeoDatabase *)itsFile;
  679.             image->setDirty();
  680.             image->unrefer();
  681.             dirty = TRUE;                        // Mark Document dirty as well.
  682.             inherited::UpdateMenus();
  683.             gNeoDatabase = database;
  684.         }
  685.     }
  686. }
  687.  
  688. void CNeoDemoDoc::setItems(CNDImage *aImage)
  689. {
  690.     Boolean            found;
  691.     short            item;
  692.     short            index;
  693.     short            max;
  694.     unsigned long    secs;
  695.     Handle            handle;
  696.     PicHandle        pict;
  697.     Str255            str;
  698.     char            text[255];
  699.  
  700.     fScrollObj->itsHorizSBar->SetMaxValue(aImage ? fImageArray->numItems -1 : 0);
  701.     fScrollObj->itsHorizSBar->SetValue(aImage ? fIndex -1 : 0);    /* adjust scroll bar value */
  702.     fScrollObj->Refresh();
  703.  
  704.     if (aImage) {
  705.         switch(aImage->getClassID()) {
  706.         case kNDImageID:                                /* use a default type */
  707.         case kNDImagePICTID:
  708.             Neostrncpy((char *)str, (char *)"\pPICT", 5);
  709.             break;
  710.  
  711.         case kNDImageTIFFID:
  712.             Neostrncpy((char *)str, (char *)"\pTIFF", 5);
  713.             break;
  714.  
  715.         case kNDImageGIFID:
  716.             Neostrncpy((char *)str, (char *)"\pGIF", 4);
  717.             break;
  718.         }
  719.     }
  720.     else
  721.         str[0] = 0;
  722.  
  723.     fTextType->SetTextString(str);
  724.     fTextType->Refresh();
  725.  
  726.     /* reset CNDFilePicture object's image pointer */
  727.     fPictObj->setImage(aImage);
  728.     fPictObj->Refresh();
  729.  
  730.     /* set static text object for "<picture#> / <max#>"  */
  731.     str[0] = sprintf((char *)&str[1], "%ld / %ld", (long)fIndex, (long)fImageArray->numItems);
  732.     fTextInfo->SetTextString(str);
  733.     fTextInfo->Refresh();
  734.  
  735.     /* set static text for picture editable fields */
  736.     if (aImage)
  737.         BlockMove((unsigned char *)aImage->fName, str, aImage->fName[0] +1);
  738.     else
  739.         str[0] = 0;
  740.     fTextName->SetTextString(str);
  741.     fTextName->Refresh();
  742.  
  743.     if (aImage &&
  744.         aImage->fBy[0])
  745.         BlockMove((unsigned char *)aImage->fBy, str, aImage->fBy[0] +1);
  746.     else {
  747.         handle = GetResource('STR ',-16096);        /* system user name in system resource */
  748.         BlockMove(*(unsigned char **)handle, str, **(unsigned char **)handle +1);
  749.     }
  750.     fTextBy->SetTextString(str);
  751.     fTextBy->Refresh();
  752.  
  753.     if (aImage &&
  754.         aImage->fDate[0])
  755.         BlockMove((unsigned char *)aImage->fDate, str, aImage->fDate[0] +1);
  756.     else {
  757.         GetDateTime(&secs);
  758.         IUDateString(secs, 0, str);
  759.     }
  760.     fTextDate->SetTextString(str);
  761.     fTextDate->Refresh();
  762.  
  763.     if (aImage)
  764.         item = aImage->fFilm;
  765.     else
  766.         item = 1;
  767.     if (fPopFilm->GetCheckedItem() != item) {
  768.         fPopFilm->SelectItem(item, pmForceOn);
  769.         fPopFilm->NewMenuSelection(item);
  770.     }
  771.  
  772.     if (aImage)
  773.         BlockMove((unsigned char *)aImage->fCatalog, str, aImage->fCatalog[0] +1);
  774.     else
  775.         str[0] = 0;
  776.     fTextCatalog->SetTextString(str);
  777.     fTextCatalog->Refresh();
  778.  
  779.     setCameraID(aImage ? aImage->fCamera : 0);
  780.  
  781.     if (aImage)
  782.         item = aImage->fExposure;
  783.     else
  784.         item = 0;
  785.     found = FALSE;
  786.     max = fPopExposure->GetMenu()->GetNumItems() -1;
  787.     if (item != 0)
  788.         for (index = 0; index < max; index++)
  789.             if (sSpeedMenu2IDTable[index] == item) {
  790.                 item = index +2;
  791.                 found = TRUE;
  792.                 break;
  793.             }
  794.     if (!found)
  795.         item = 1;                                // select "Unknown"
  796.     fPopExposure->SelectItem(item, pmForceOn);
  797.     fPopExposure->NewMenuSelection(item);
  798.  
  799.     if (aImage)
  800.         item = aImage->fFocal;
  801.     else
  802.         item = 1;
  803.     if (fPopFocal->GetCheckedItem() != item) {
  804.         fPopFocal->SelectItem(item, pmForceOn);
  805.         fPopFocal->NewMenuSelection(item);
  806.     }
  807.  
  808.     if (aImage)
  809.         item = aImage->fFStop;
  810.     else
  811.         item = 1;
  812.     if (fPopFStop->GetCheckedItem() != item) {
  813.         fPopFStop->SelectItem(item, pmForceOn);
  814.         fPopFStop->NewMenuSelection(item);
  815.     }
  816.  
  817.     if (aImage) {
  818.         aImage->buildKeyWordStr((char *)&str[1]);    /* construct single string from keywords array */
  819.         str[0] = 'a';
  820.         str[0] = strlen((char *)str) -1;
  821.     }
  822.     else
  823.         str[0] = 0;
  824.     fTextKeywords->SetTextString(str);
  825.     fTextKeywords->Refresh();
  826. }
  827.  
  828. /* empty our image list - add all items matching the popup type (including 'any')
  829.     that also match the ID.
  830.     NeoID is kNDImagePICTID, kNDImageTIFFID, kNDImageGIFID, or kNDImageID.
  831. */
  832. short CNeoDemoDoc::setSelectionByID(const NeoID aClassID, const NeoID aID)
  833. {
  834.     /* get current data into image object of database before starting search */
  835.     updateImage(nil);
  836.  
  837.     emptyImageArray();
  838.  
  839.     CNeoPersist::FindByID((CNeoDatabase*)itsFile, aClassID, aID, (aClassID == kNDImageID), (NeoTestFunc1)CNDImage::GetImageID, (void *)fImageArray);
  840.  
  841.     fIndex = 0;
  842.     fScrollObj->itsHorizSBar->SetMaxValue(fImageArray->numItems -1);
  843.  
  844.     if (fImageArray->numItems > 0)
  845.         gotoImage(1, FALSE);
  846.     else
  847.         setItems(nil);
  848.  
  849.     return fImageArray->numItems;
  850. }
  851.  
  852. /* empty our image list - add all items matching the popup type (including 'any')
  853.     that also match the text in 'keyword' edit box.
  854.     Called from 'CNDButton::DoClick' method.
  855.     NeoID is kNDImagePICTID, kNDImageTIFFID, kNDImageGIFID, or kNDImageID.
  856. */
  857. short CNeoDemoDoc::setSelectionByKeyword(const NeoID aClassID, char *aKeyword)
  858. {
  859.     CNeoKeywordSelect *    key;
  860.  
  861.     // get current data into image object of database before starting search
  862.     updateImage(nil);
  863.  
  864.     emptyImageArray();
  865.  
  866.     key = getKeywordKey(aKeyword);
  867.     getDatabase()->findObject(aClassID, key, (aClassID == kNDImageID), (NeoTestFunc1)CNDImage::GetImageID, (void *)fImageArray);
  868.  
  869.     fIndex = 0;
  870.     fScrollObj->itsHorizSBar->SetMaxValue(fImageArray->numItems -1);
  871.  
  872.     if (fImageArray->numItems > 0)
  873.         gotoImage(1, FALSE);
  874.     else
  875.         setItems(nil);
  876.  
  877.     return fImageArray->numItems;
  878. }
  879.  
  880. void CNeoDemoDoc::showBorders(const Boolean aShow)
  881. {
  882.         fTextName->showBorder(aShow);
  883.         fTextBy->showBorder(aShow);
  884.         fTextDate->showBorder(aShow);
  885.         fTextCatalog->showBorder(aShow);
  886.         fTextKeywords->showBorder(aShow);
  887. }
  888.  
  889. /* before scroll, find, or quit */
  890. void CNeoDemoDoc::updateImage(CNDImage *aImage)
  891. {
  892.     short        item;
  893.     long        length;
  894.     Handle        text;
  895.     CNDImage *    image;
  896.     char        keywords[256];
  897.  
  898.     if (aImage) {
  899.         image = aImage;
  900.         image->referTo();
  901.     }
  902.     else if (!fImageArray->numItems)
  903.         return;
  904.     else {
  905.         image = getImage(fIndex);
  906.         if (!image)
  907.             return;
  908.     }
  909.  
  910.     if (!image->isDirty()) {
  911.         image->unrefer();
  912.         return;
  913.     }
  914.  
  915.     text = fTextName->GetTextHandle();
  916.     length = fTextName->GetLength();
  917.     NeoBlockMove(*text, (char *)&image->fName[1], length);
  918.     image->fName[0] = length;
  919.  
  920.     text = fTextBy->GetTextHandle();
  921.     length = fTextBy->GetLength();
  922.     NeoBlockMove(*text, (char *)&image->fBy[1], length);
  923.     image->fBy[0] = length;
  924.  
  925.     text = fTextDate->GetTextHandle();
  926.     length = fTextDate->GetLength();
  927.     NeoBlockMove(*text, (char *)&image->fDate[1], length);
  928.     image->fDate[0] = length;
  929.  
  930.     image->fFilm = fPopFilm->GetCheckedItem();
  931.  
  932.     text = fTextCatalog->GetTextHandle();
  933.     length = fTextCatalog->GetLength();
  934.     NeoBlockMove(*text, (char *)&image->fCatalog[1], length);
  935.     image->fCatalog[0] = length;
  936.  
  937.     item = fPopBody->GetCheckedItem();
  938.     if (item > 1)
  939.         image->fCamera = CNDCamera::GetCameraID(item);
  940.     else
  941.         image->fCamera = 0;
  942.  
  943.     image->fFocal = fPopFocal->GetCheckedItem();
  944.  
  945.     image->fFStop = fPopFStop->GetCheckedItem();
  946.  
  947.     item = fPopExposure->GetCheckedItem();
  948.     if (item > 1)
  949.         image->fExposure = sSpeedMenu2IDTable[item -2];
  950.     else
  951.         image->fExposure = 0;
  952.  
  953.     text = fTextKeywords->GetTextHandle();
  954.     length = fTextKeywords->GetLength();
  955.     if (length > 255)
  956.         length = 255;
  957.  
  958.     /* parse comma delimited keywords string */
  959.     NeoBlockMove(*text, keywords, length);
  960.     keywords[length] = 0;
  961.     image->parseKeywords(keywords);
  962.     image->unrefer();
  963. }
  964.  
  965.