home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / powergui / notebook / smrtguid / smrtguid.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-29  |  23.2 KB  |  786 lines

  1. //************************************************************
  2. // Notebook Control - Smart Guide Notebook
  3. //
  4. // Copyright (C) 1994, Law, Leong, Love, Olson, Tsuji.
  5. // Copyright (c) 1997 John Wiley & Sons, Inc.
  6. // All Rights Reserved.
  7. //************************************************************
  8. #include <iframe.hpp>
  9. #include <inotebk.hpp>
  10. #include <ipagehdr.hpp>
  11. #include <isetcv.hpp>
  12. #include <ipushbut.hpp>
  13. #include <ifont.hpp>
  14. #include <iexcept.hpp>
  15. #include <icmdhdr.hpp>
  16. #include <ihelp.hpp>
  17. #include <iseq.h>
  18. #include "smrtguid.hpp"
  19.  
  20. class SmartPageInfo;
  21.  
  22. // SmartTree holds a collection of SmartPageInfo objects in graph
  23. // layout with a single root.  A SmartPageInfo object
  24. // maintains the information for a single node of the tree. The
  25. // primary piece of information is the SmartPage* for
  26. // the node of the tree.  If the SmartPageInfo represents a page
  27. // already added to the notebook, it also contains the IPageHandle
  28. // for the notebook page and the IWindow* for the window displayed
  29. // on the page.  Finally the SmartPageInfo stores the number of
  30. // child nodes to facilitate traversal.
  31. #ifdef IC_PM
  32.    #include <itree.h>
  33.    class SmartTree : public ITree<SmartPageInfo*, 25>
  34.    {
  35.    public:
  36.       SmartTree ( ) {}
  37.    };
  38. #else
  39.    #include <imwt.h>
  40.    class SmartTree : public IMultiwayTree<25, SmartPageInfo*>
  41.    {
  42.    public:
  43.       SmartTree ( ) {}
  44.    };
  45. #endif
  46.  
  47. class SmartPageInfoList : public ISequence<SmartPageInfo*>
  48. {
  49. public:
  50.   SmartPageInfoList () : ISequence<SmartPageInfo*>(10) {}
  51.  
  52. };
  53.  
  54.  
  55. class SmartPageInfo
  56. {
  57. public:
  58.    SmartPageInfo ( SmartPage* smartPage,
  59.                    IWindow*   pageWindow=0)
  60.       : fSmartPage (smartPage),
  61.         fPageWindow (pageWindow),
  62.         fPageHandle (),
  63.         fChildCount (0)
  64.     {}
  65. SmartPage
  66.  *smartPage     ( )  { return fSmartPage; }
  67.  
  68. void
  69.   setPageWindow ( IWindow* pageWindow) { fPageWindow = pageWindow; }
  70.  
  71. IWindow
  72.  *pageWindow    ( )  { return fPageWindow; }
  73.  
  74. void
  75.   setPageHandle ( const IPageHandle& pageHandle )
  76.   { fPageHandle = pageHandle; }
  77. IPageHandle
  78.   pageHandle    ( )  { return fPageHandle; }
  79.  
  80. void
  81.   incrementChildCount ( ) { fChildCount++; }
  82.  
  83. unsigned long
  84.   childCount          ( ) const { return fChildCount; }
  85.  
  86.  
  87. private:
  88. SmartPage
  89.  *fSmartPage;
  90. IWindow
  91.  *fPageWindow;
  92. IPageHandle
  93.   fPageHandle;
  94. unsigned long
  95.   fChildCount;
  96. };
  97.  
  98.  
  99. ///
  100. ///   SmartGuide::Cursor functions
  101. ///
  102. ///   The Cursor supports cursoring the objects of the Tree:
  103. ///     1) in their selected order.  In affect, it returns
  104. ///        those pages that should be displayed in the notebook.
  105. ///     2) by descending the tree in bottomUp order (See the
  106. ///        collection class description of IPostOrder for
  107. ///        details)
  108. ///     3) by descending the tree in topDown order ( See the
  109. ///        collection class description of IPreOrder for
  110. ///        details)
  111. ///   SmartGuide cursoring is implemented using the cursor
  112. ///   for the SmartTree
  113. ///
  114. SmartGuide::Cursor::Cursor ( SmartGuide&           smartGuide,
  115.                             SmartGuide::IterationOrder  order)
  116.           : fTreeCursor( new SmartTree::Cursor(*(smartGuide.fSmartTree))),
  117.             fSmartGuide ( smartGuide),
  118.             fOrder ( order )
  119. {
  120.  
  121. }
  122.  
  123. SmartGuide::Cursor::~Cursor ( )
  124. {
  125.    delete (SmartTree::Cursor*)fTreeCursor;
  126. }
  127.  
  128. Boolean SmartGuide::Cursor::setToFirst( )
  129. {
  130.    Boolean nodeFound;
  131.    ITreeIterationOrder treeOrder = IPreorder;
  132.    if (fOrder == bottomUp)
  133.      treeOrder = IPostorder;
  134.  
  135.    if (fOrder == selectedOrder)
  136.      nodeFound = fSmartGuide.fSmartTree->setToRoot(
  137.                                            *(SmartTree::Cursor*)fTreeCursor);
  138.    else
  139.      nodeFound = fSmartGuide.fSmartTree->setToFirst(
  140.                                            *(SmartTree::Cursor*)fTreeCursor, treeOrder);
  141.    return nodeFound;
  142. }
  143.  
  144. Boolean SmartGuide::Cursor::setToNext( )
  145. {
  146.    ITreeIterationOrder treeOrder = IPreorder;
  147.    IBoolean nodeFound = false;
  148.    if (fOrder == SmartGuide::bottomUp)
  149.      treeOrder = IPostorder;
  150.    if (fOrder == bottomUp || fOrder == topDown)
  151.       nodeFound = fSmartGuide.fSmartTree->setToNext(*(SmartTree::Cursor*)fTreeCursor, treeOrder);
  152.    else
  153.    {
  154.       SmartPageInfo* pageInfo = fSmartGuide.fSmartTree->elementAt(*(SmartTree::Cursor*)fTreeCursor);
  155.       SmartPage* page = pageInfo->smartPage();
  156.  
  157.       // Tree indexes are one based, ours are 0 based.  If more than one
  158.       // child, find the selected choice, otherwise go down only leg.
  159.       unsigned long choice = 1;
  160.       if (pageInfo->childCount() > 1)
  161.         choice = page->currentChoice() + 1;
  162.       nodeFound = fSmartGuide.fSmartTree->setToChild(choice, *(SmartTree::Cursor*)fTreeCursor);
  163.    }
  164.    return nodeFound;
  165. }
  166.  
  167.  
  168. Boolean SmartGuide::Cursor::setToPrevious( )
  169. {
  170.    ITreeIterationOrder treeOrder = IPreorder;
  171.    Boolean nodeFound = false;
  172.    if (fOrder == SmartGuide::bottomUp)
  173.      treeOrder = IPostorder;
  174.    if (fOrder == bottomUp || fOrder == topDown)
  175.      nodeFound = fSmartGuide.fSmartTree->setToPrevious(*(SmartTree::Cursor*)fTreeCursor, treeOrder);
  176.    else
  177.      nodeFound = fSmartGuide.fSmartTree->setToParent(*(SmartTree::Cursor*)fTreeCursor);
  178.  
  179.    return nodeFound;
  180. }
  181.  
  182.  
  183. Boolean SmartGuide::Cursor::setToLast( )
  184. {
  185.    Boolean nodeFound = false;
  186.    ITreeIterationOrder treeOrder = IPreorder;
  187.    SmartTree* smartTree = fSmartGuide.fSmartTree;
  188.    if (fOrder == SmartGuide::bottomUp)
  189.      treeOrder = IPostorder;
  190.    if (fOrder == bottomUp || fOrder == topDown)
  191.      nodeFound = smartTree->setToLast(*(SmartTree::Cursor*)fTreeCursor, treeOrder);
  192.    else
  193.    {
  194.       // For selected order, we need to chase down the selection
  195.       // tree until we reach a leaf node.
  196.       Boolean rootFound = smartTree->setToRoot(*(SmartTree::Cursor*)fTreeCursor);
  197.       if (rootFound)
  198.       {
  199.         SmartPageInfo* pageInfo = smartTree->elementAt(*(SmartTree::Cursor*)fTreeCursor);
  200.         for (;smartTree->isLeaf(*(SmartTree::Cursor*)fTreeCursor) == false;)
  201.         {
  202.           SmartPage* page = pageInfo->smartPage();
  203.           unsigned long childIndex = page->currentChoice() + 1;
  204.           nodeFound = smartTree->setToChild(childIndex,
  205.                                            *(SmartTree::Cursor*)fTreeCursor);
  206.         }
  207.       } /* endif */
  208.    }
  209.    return nodeFound;
  210. }
  211.  
  212.  
  213. Boolean SmartGuide::Cursor::isValid( ) const
  214. {
  215.  
  216.    return ((SmartTree::Cursor*)fTreeCursor)->isValid();
  217. }
  218.  
  219. void SmartGuide::Cursor::setCurrent ( unsigned long smartPageHandle )
  220. {
  221.   SmartPageInfo* pageInfo = (SmartPageInfo*)smartPageHandle;
  222.   Boolean smartPageFound = false;
  223.   SmartTree* smartTree = fSmartGuide.fSmartTree;
  224.   SmartTree::Cursor* cursor = (SmartTree::Cursor*)fTreeCursor;
  225.   for ( smartTree->setToFirst( *cursor, IPreorder);
  226.         cursor->isValid() && smartPageFound==false;
  227.         smartTree->setToNext( *cursor, IPreorder))
  228.   {
  229.      SmartPageInfo* cursorPageInfo = smartTree->elementAt( *cursor);
  230.      if (cursorPageInfo == pageInfo)
  231.      {
  232.         smartPageFound = true;
  233.         return;
  234.      }
  235.   }
  236.   IASSERTSTATE(smartPageFound==true)
  237. }
  238.  
  239.  
  240.  
  241.  
  242. ///
  243. ///   SmartGuidePageHandler Definition
  244. ///
  245. class SmartGuidePageHandler : public IPageHandler
  246. {
  247. public:
  248.    SmartGuidePageHandler ( SmartGuide& smartGuide)
  249.    : fSmartGuide(smartGuide)
  250.    {}
  251. protected:
  252. virtual Boolean
  253.   select  ( IPageSelectEvent& event )
  254. {
  255.   return fSmartGuide.handlePageSelect ( event);
  256. }
  257. /*------------------------------ Hidden Members ------------------------------*/
  258.   SmartGuidePageHandler ( const SmartGuidePageHandler& );
  259. SmartGuidePageHandler
  260.  &operator=   ( const SmartGuidePageHandler& );
  261. SmartGuide
  262.  &fSmartGuide;
  263. };
  264.  
  265.  
  266. ///
  267. ///  Smart Guide Command Handler (one per
  268. ///  smart guide)
  269. class SmartGuideCommandHandler : public ICommandHandler
  270. {
  271. public:
  272.    SmartGuideCommandHandler ( SmartGuide& smartGuide)
  273.     : fSmartGuide ( smartGuide ) {}
  274. protected:
  275. Boolean
  276.   command ( ICommandEvent& );
  277.  
  278. private:
  279. /*------------------------------ Hidden Members ------------------------------*/
  280.   SmartGuideCommandHandler ( const SmartGuideCommandHandler& );
  281. SmartGuideCommandHandler
  282.  &operator=   ( const SmartGuideCommandHandler& );
  283. SmartGuide
  284.  &fSmartGuide;
  285. };
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292. ///
  293. ///   SmartGuide functions
  294. ///
  295. SmartGuide::SmartGuide ( const IString&  guideName)
  296.              :  fGuideName(guideName),
  297.                 fSmartTree (new SmartTree),
  298.                 fPageInfoList(0),
  299.                 fCurrentPageInfo(0),
  300.                 fFrameWindow (0),
  301.                 fNotebook(0),
  302.                 fBackButton(0),
  303.                 fNextButton(0),
  304.                 fCancelButton(0),
  305.                 fDoneButton(0),
  306.                 fHelpButton(0),
  307.                 fPageHandler(0),
  308.                 fCommandHandler(0)
  309. {
  310. }
  311.  
  312. SmartGuide& SmartGuide::show ( )
  313. {
  314.  
  315.    SmartPage* firstPage = 0;
  316.  
  317.    IASSERTSTATE(fSmartTree->numberOfElements() != 0)
  318.  
  319.  
  320.    // Establish the minimum size for a page
  321.    SmartGuide::Cursor cursor (*this, topDown);
  322.    ISize minimumSize(0,0);
  323.    unsigned long minimumTabLength = 0;
  324.    IFont notebookFont(fNotebook);
  325.    for(cursor.setToFirst();
  326.        cursor.isValid();
  327.        cursor.setToNext())
  328.    {
  329.       SmartPageInfo* smartPageInfo = pageInfoAtLocation(cursor);
  330.       SmartPage* smartPage = smartPageInfo->smartPage();
  331.       // Store the first page
  332.       if (firstPage==0)
  333.       {
  334.          firstPage = smartPage;
  335.          fCurrentPageInfo = smartPageInfo;
  336.       }
  337.  
  338.       // Establish the minimum tab size.
  339.       IString tabText = smartPage->tabText();
  340.       tabText.change(" ", "_");
  341.       unsigned long tabLength = notebookFont.minTextWidth(tabText);
  342.       if (tabLength>minimumTabLength)
  343.          minimumTabLength = tabLength;
  344.  
  345.       // Establish the minimum page size.
  346.       ISize size = smartPage->minimumSize();
  347.       if (size > minimumSize)
  348.         minimumSize = size;
  349.    }
  350.  
  351.    // Create the frame window.
  352.    minimumSize += ISize(100, 100);
  353.    fFrameWindow = new IFrameWindow( fGuideName);
  354.  
  355.    // Create the notebook in the client area.
  356.    INotebook::Style style = INotebook::classDefaultStyle;
  357. //   #ifndef IC_PM
  358. //     style |= INotebook::pmCompatible;
  359. //   #endif
  360.  
  361.    fNotebook = new INotebook(1, fFrameWindow, fFrameWindow,
  362.                              IRectangle(), style);
  363.    fFrameWindow->setClient(fNotebook);
  364.  
  365.    // Change the settings of the notebook.
  366.    fNotebook->setOrientation(INotebook::backpagesRightTabsTop);
  367.    fNotebook->setBinding(INotebook::spiral);
  368.    fNotebook->setTabShape(INotebook::rounded);
  369.    fNotebook->setTabTextAlignment(INotebook::center);
  370.  
  371.   // Build the notebook pages
  372.   refreshPages();
  373.  
  374.   // Set the size of tabs in the notebook.
  375.   fNotebook->setMajorTabSize(ISize(minimumTabLength+35,
  376.                                    notebookFont.maxCharHeight()+8));
  377.  
  378.    // Setup push buttons in a canvas as frame extensions.
  379.    ISetCanvas* buttons = new ISetCanvas( WID_BUTTONS,
  380.                                          fFrameWindow,
  381.                                          fFrameWindow);
  382.    fFrameWindow->addExtension(buttons, IFrameWindow::belowClient);
  383.    fBackButton = new IPushButton( WID_BACK,
  384.                                   buttons,
  385.                                   buttons);
  386.    fNextButton = new IPushButton( WID_NEXT,
  387.                                   buttons,
  388.                                   buttons);
  389.    fCancelButton = new IPushButton( WID_CANCEL,
  390.                                   buttons,
  391.                                   buttons);
  392.    fDoneButton = new IPushButton( WID_DONE,
  393.                                   buttons,
  394.                                   buttons);
  395.    fHelpButton = new IPushButton( WID_HELP,
  396.                                               buttons,
  397.                                               buttons);
  398.    fBackButton->setText("<< Back");
  399.    fBackButton->disable();
  400.    fNextButton->setText("Next >>");
  401.  
  402.    fCancelButton->enableGroup();
  403.    fCancelButton->setText("Cancel");
  404.    fDoneButton->setText("Done");
  405.  
  406.    fHelpButton->enableGroup();
  407.    fHelpButton->setText("Help");
  408.  
  409.    // Separate the buttons by group.
  410.    buttons->setGroupPad(20);
  411.  
  412.   // Setup our Command Handler for the buttons (and CID_REFRESH
  413.   // via the notebook.
  414.   fCommandHandler = new SmartGuideCommandHandler(*this);
  415.   fCommandHandler->handleEventsFor(fFrameWindow);
  416.   fCommandHandler->handleEventsFor(fNotebook);
  417.  
  418.   // Setup our page handler for delayed addition of pages.
  419.   fPageHandler = new SmartGuidePageHandler( *this);
  420.   fPageHandler->handleEventsFor(fNotebook);
  421.  
  422.   // Give the notebook the focus and show the frame.
  423.   fNotebook->setFocus();
  424.   fFrameWindow->show();
  425.   return *this;
  426. }
  427.  
  428.  
  429. SmartGuide& SmartGuide::refreshPages  ( )
  430. {
  431.   // Note: This function assumes fCurrentPageInfo is pointing
  432.   // at the "current" page in the SmartGuide.  This is typically
  433.   // either the root page when the SmartGuide is first created, or
  434.   // the page undergoing a selection change, and thus causing
  435.   // the notebook to need rebuilding.
  436.   IASSERTSTATE(fCurrentPageInfo!=0);
  437.  
  438.  
  439.   // Store the current page info list and create a new one.
  440.   SmartPageInfoList* currentPageInfoList = fPageInfoList;
  441.   fPageInfoList = new SmartPageInfoList;
  442.  
  443.  
  444.   // Build the new page info list by determining the newly selected path.
  445.   SmartGuide::Cursor selectionCursor(*this, selectedOrder);
  446.   for(selectionCursor.setToFirst();
  447.       selectionCursor.isValid();
  448.       selectionCursor.setToNext())
  449.   {
  450.      // Get the page information and add it to the page info list.
  451.      SmartPageInfo* cursorPageInfo =
  452.               pageInfoAtLocation( selectionCursor);
  453.      fPageInfoList->addAsLast(cursorPageInfo);
  454.   }
  455.  
  456.  
  457.  
  458.   // Compare the old and new page info lists to decide which pages
  459.   // to remove and which pages to add to the notebook.
  460.   IPageHandle pageHandle = 0;
  461.   INotebook::PageSettings pageSettings(
  462.           INotebook::PageSettings::majorTab
  463.         | INotebook::PageSettings::autoPageSize);
  464.   Boolean differenceFound = false;
  465.   SmartPageInfoList::Cursor newListCursor (*fPageInfoList);
  466.   SmartPageInfoList::Cursor* currentListCursor = 0;
  467.   if(currentPageInfoList)
  468.   {
  469.     currentListCursor = new SmartPageInfoList::Cursor(*currentPageInfoList);
  470.     currentListCursor->setToFirst();
  471.   }
  472.   else
  473.     differenceFound = true;
  474.  
  475.   for(newListCursor.setToFirst();
  476.       newListCursor.isValid();
  477.       newListCursor.setToNext())
  478.   {
  479.  
  480.     SmartPageInfo* newPageInfo = fPageInfoList->elementAt(newListCursor);
  481.     SmartPage* newSmartPage = newPageInfo->smartPage();
  482.     if(!differenceFound)
  483.     {
  484.        SmartPageInfo* currentPageInfo = currentPageInfoList->elementAt(*currentListCursor);
  485.        if(currentPageInfo!=newPageInfo)
  486.        {
  487.           // Once we get a difference between the two lists, remove the
  488.           // remaining pages from the notebook.
  489.           differenceFound = true;
  490.           for(; currentListCursor->isValid(); currentListCursor->setToNext())
  491.           {
  492.              currentPageInfo = currentPageInfoList->elementAt(*currentListCursor);
  493.              fNotebook->removePage(currentPageInfo->pageHandle());
  494.              currentPageInfo->setPageHandle(0);
  495.           }
  496.        }
  497.        else
  498.          currentListCursor->setToNext();
  499.     }
  500.     if(differenceFound)
  501.     {
  502.        // Create the Page Window if one doesn't exist for the current
  503.        // page of the notebook.  This should only happen
  504.        // for the root page of the notebook as all other pages are
  505.        // created when the page is selected.
  506.        pageSettings.setTabText(newSmartPage->tabText());
  507.        if (newPageInfo==fCurrentPageInfo && fCurrentPageInfo->pageWindow()==0)
  508.        {
  509.          IWindow* firstWindow = fCurrentPageInfo->smartPage()->
  510.                            createAndOrphanPage( fNotebook,
  511.                                                 fNotebook,
  512.                                                 IRectangle(IPoint(0,0),newPageSize()));
  513.          fCurrentPageInfo->setPageWindow(firstWindow);
  514.          pageHandle =  fNotebook->addLastPage(
  515.                                   pageSettings, firstWindow);
  516.        }
  517.        else if (newPageInfo->pageWindow())
  518.          pageHandle =  fNotebook->addLastPage(
  519.                                   pageSettings, newPageInfo->pageWindow());
  520.        else
  521.          pageHandle = fNotebook->addLastPage(pageSettings);
  522.        newPageInfo->setPageHandle( pageHandle);
  523.     }
  524.   }
  525.   delete currentPageInfoList;
  526.   currentPageInfoList = 0;
  527.  
  528.   return *this;
  529. }
  530.  
  531.  
  532. unsigned long SmartGuide::addPage ( SmartPage*    smartPage,
  533.                                     unsigned long referencePageHandle)
  534. {
  535.   Boolean fPageAdded = false;
  536.   SmartPageInfo* pageInfo = 0;
  537.   SmartPageInfo* referencePageInfo = (SmartPageInfo*)referencePageHandle;
  538.  
  539.   // If no reference page, then add as the root
  540.   if (referencePageHandle == 0) {
  541.      pageInfo = new SmartPageInfo (smartPage);
  542.      fSmartTree->addAsRoot(pageInfo);
  543.   }
  544.   // Else find the reference page and add the page as a
  545.   // child.
  546.   else
  547.   {
  548.      SmartTree::Cursor cursor (*fSmartTree);
  549.      for (fSmartTree->setToFirst(cursor, IPreorder);
  550.           cursor.isValid() && fPageAdded==false;
  551.           fSmartTree->setToNext (cursor, IPreorder) )
  552.      {
  553.         SmartPageInfo* cursorPageInfo = fSmartTree->elementAt(cursor);
  554.         if (cursorPageInfo == referencePageInfo)
  555.         {
  556.            pageInfo = new SmartPageInfo(smartPage);
  557.            cursorPageInfo->incrementChildCount();
  558.            fSmartTree->addAsChild( cursor,
  559.                                    cursorPageInfo->childCount(),
  560.                                    pageInfo);
  561.            fPageAdded=true;
  562.         } /* endif */
  563.      } /* endfor */
  564.   IASSERTSTATE(fPageAdded == true)
  565.   }
  566.   return (unsigned long)pageInfo;
  567. }
  568.  
  569. Boolean SmartGuide::isOKToClose( IString& closeErrorIfFalse )
  570. {
  571.   // This is where you determine if each smart page in
  572.   // in the current stack has enough information to
  573.   // close.
  574.   Boolean okToClose = true;
  575.   SmartGuide::Cursor cursor(*this, selectedOrder);
  576.   IString errorMessage("");
  577.   for(cursor.setToFirst();
  578.       cursor.isValid() && okToClose == true;
  579.       cursor.setToNext())
  580.   {
  581.      SmartPage* smartPage = pageAtLocation(cursor);
  582.      okToClose = smartPage->isOKToClose(closeErrorIfFalse);
  583.      if(!okToClose)
  584.      {
  585.         fCurrentPageInfo = pageInfoAtLocation(cursor);
  586.         break;
  587.      }
  588.   }
  589.   return okToClose;
  590. }
  591.  
  592.  
  593. SmartPage* SmartGuide::pageAtLocation ( Cursor& cursor) const
  594. {
  595.    return pageInfoAtLocation(cursor)->smartPage();
  596. }
  597.  
  598. SmartPageInfo* SmartGuide::pageInfoAtLocation ( Cursor& cursor) const
  599. {
  600.    return fSmartTree->elementAt(*(SmartTree::Cursor*)cursor.fTreeCursor);
  601. }
  602.  
  603.  
  604. SmartPageInfo* SmartGuide::pageInfoWithHandle ( const IPageHandle& pageHandle) const
  605. {
  606.    SmartGuide::Cursor cursor( *(SmartGuide*)this, selectedOrder);
  607.    for(cursor.setToFirst();
  608.        cursor.isValid();
  609.        cursor.setToNext())
  610.    {
  611.      SmartPageInfo* cursorPageInfo = pageInfoAtLocation(cursor);
  612.      if (cursorPageInfo->pageHandle() == pageHandle)
  613.        return cursorPageInfo;
  614.    }
  615.    return 0;
  616. }
  617.  
  618. IString SmartGuide::asString( ) const
  619. {
  620.   return fGuideName;
  621. }
  622. IString SmartGuide::asDebugInfo( ) const
  623. {
  624.   IString str("\nSelection path:");
  625.   SmartGuide::Cursor cursor(*(SmartGuide*)this, selectedOrder);
  626.   for(cursor.setToFirst();
  627.       cursor.isValid();
  628.       cursor.setToNext())
  629.   {
  630.      SmartPageInfo* pageInfo=pageInfoAtLocation(cursor);
  631.      str += "\n  "+pageInfo->smartPage()->tabText()+"("
  632.          +IString((unsigned long)pageInfo).d2x()
  633.          + ") Selection: "
  634.          + IString(pageInfo->smartPage()->currentChoice());
  635.   }
  636.  
  637.   str += "\n\nTopDown Dump:";
  638.   SmartGuide::Cursor cursor2(*(SmartGuide*)this, topDown);
  639.   for(cursor2.setToFirst();
  640.       cursor2.isValid();
  641.       cursor2.setToNext())
  642.   {
  643.      SmartPageInfo* pageInfo=pageInfoAtLocation(cursor2);
  644.      str += "\n  "+pageInfo->smartPage()->tabText()+"("
  645.          +IString((unsigned long)pageInfo).d2x()
  646.          + ") Selection: "
  647.          + IString(pageInfo->smartPage()->currentChoice());
  648.   }
  649.   return str;
  650. }
  651.  
  652.  
  653. Boolean SmartGuide::handleHelp     ( )
  654. {
  655.   // Not implemented.
  656.   return true;
  657. }
  658.  
  659. Boolean SmartGuide::handleBack     ( )
  660. {
  661.   SmartGuide::Cursor cursor(*this, selectedOrder);
  662.   cursor.setCurrent((unsigned long)(void*)fCurrentPageInfo);
  663.   cursor.setToPrevious();
  664.  
  665.   fCurrentPageInfo = pageInfoAtLocation(cursor);
  666.   fNotebook->turnToPage(fCurrentPageInfo->pageHandle());
  667.  
  668.   return true;
  669. }
  670.  
  671. Boolean SmartGuide::handleNext( )
  672. {
  673.   SmartGuide::Cursor cursor(*this, selectedOrder);
  674.   cursor.setCurrent((unsigned long)(void*)fCurrentPageInfo);
  675.   cursor.setToNext();
  676.   IASSERTSTATE(cursor.isValid())
  677.  
  678.   fCurrentPageInfo = pageInfoAtLocation(cursor);
  679.   fNotebook->turnToPage(fCurrentPageInfo->pageHandle());
  680.  
  681.   return true;
  682. }
  683.  
  684. Boolean SmartGuide::handleCancel( )
  685. {
  686.   fFrameWindow->close();
  687.   return true;
  688. }
  689.  
  690. Boolean SmartGuide::handleDone ( )
  691. {
  692.   IString errorMessage("");
  693.   if(isOKToClose(errorMessage))
  694.     fFrameWindow->close();
  695.   else
  696.   {
  697.     fNotebook->setStatusText(fCurrentPageInfo->pageHandle(),errorMessage);
  698.     fNotebook->turnToPage(fCurrentPageInfo->pageHandle());
  699.   }
  700.   return true;
  701. }
  702.  
  703.  
  704. ISize SmartGuide::newPageSize ( ) const
  705. {
  706.   return fLastPageSize;
  707. }
  708.  
  709. Boolean SmartGuide::handleRefresh ( )
  710. {
  711.   refreshPages();
  712.   return true;
  713. }
  714.  
  715. Boolean SmartGuide::handlePageSelect  ( IPageSelectEvent& event )
  716. {
  717.   IPageHandle selectedPage = event.pageHandle();
  718.  
  719.   INotebook* notebook = event.notebook();
  720.   INotebook::PageSettings pageData =
  721.                 event.notebook()->pageSettings(selectedPage);
  722.   fCurrentPageInfo = pageInfoWithHandle(selectedPage);
  723.   SmartPage* smartPage = fCurrentPageInfo->smartPage();
  724.  
  725.   // Create the window if it doesn't already exist.
  726.   if (fCurrentPageInfo->pageWindow() == 0)
  727.   {
  728.     IWindow* nextPage = smartPage->createAndOrphanPage(
  729.                                         notebook,
  730.                                         notebook,
  731.                                         newPageSize());
  732.     fCurrentPageInfo->setPageWindow(nextPage);
  733.  
  734.     // Size the window to the size of the page.
  735. //    nextPage->sizeTo(notebook->pageSize());
  736.  
  737.     // Put the page on the notebook
  738.     notebook->setWindow( selectedPage, nextPage);
  739.     nextPage->show();
  740.   }
  741.  
  742.   // Disable or enable Back/Next buttons
  743.   IPageHandle firstPage = fNotebook->firstPage();
  744.   IPageHandle lastPage = fNotebook->lastPage();
  745.   if (firstPage==selectedPage)
  746.     fBackButton->disable();
  747.   else
  748.     fBackButton->enable();
  749.   if (lastPage==selectedPage)
  750.     fNextButton->disable();
  751.   else
  752.     fNextButton->enable();
  753.  
  754.   return false;
  755. }
  756.  
  757. SmartGuide& SmartGuide::setHelpWindow ( IHelpWindow& helpWindow)
  758. { fHelpWindow = &helpWindow; return *this; }
  759.  
  760.  
  761. Boolean SmartGuideCommandHandler::command ( ICommandEvent& event)
  762. {
  763.    switch (event.commandId()) {
  764.      case  WID_BACK :
  765.         fSmartGuide.handleBack( );
  766.         break;
  767.      case  WID_NEXT :
  768.         fSmartGuide.handleNext( );
  769.         break;
  770.      case  WID_CANCEL :
  771.         fSmartGuide.handleCancel( );
  772.         break;
  773.      case  WID_DONE :
  774.         fSmartGuide.handleDone( );
  775.         break;
  776.      case  WID_HELP :
  777.         fSmartGuide.handleHelp( );
  778.         break;
  779.      case  CID_REFRESH :
  780.         fSmartGuide.refreshPages( );
  781.         break;
  782.    } /* endswitch */
  783.    return true;
  784. }
  785.  
  786.