home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / powergui / help / helpothr / helpothr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  14.4 KB  |  506 lines

  1. //*********************************************************
  2. // Using Help - Help for Special Cases
  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 <ibase.hpp>         // For IC_PM or IC_WIN.
  9. #ifdef IC_PM
  10.   #define INCL_WINWINDOWMGR  // For WinQueryActiveWindow.
  11.   #include <os2.h>
  12. #endif
  13.  
  14. #include <iapp.hpp>
  15. #include <icnrctl.hpp>
  16. #include <icnrhdr.hpp>
  17. #include <idmcnrit.hpp>
  18. #include <idmsrch.hpp>
  19. #include <idmevent.hpp>
  20. #include <ifiledlg.hpp>
  21. #include <iframe.hpp>
  22. #include <ihelp.hpp>
  23. #include <ipushbut.hpp>
  24. #include <isetcv.hpp>
  25. #include <icconst.h>
  26.  
  27. #include "helpothr.hpp"
  28. #include "childhlp.hpp"
  29. #include "helpothr.h"
  30.  
  31. #ifdef IC_PM
  32.   #ifdef IPF_COMPATIBLE
  33.     #undef IPF_COMPATIBLE
  34.   #endif
  35. #endif
  36.  
  37. #ifdef IC_PM
  38.   static ChildHelpHandler childHelpHdr;
  39. #endif
  40.  
  41. void main ( )
  42. {
  43.   // Create a primary window with a container.
  44.   IFrameWindow
  45.     primary( "Help Example for Special Cases", ID_PRIMARY );
  46.   IContainerControl
  47.     client( ID_CLIENT, &primary, &primary );
  48.   client
  49.    .setTitle( "This example shows help for a container, notebook, "
  50.               "file dialog, and drag and drop." )
  51.    .showTitle()
  52.    .showTitleSeparator()
  53.    .showIconView()
  54.    .arrangeIconView()
  55.    .setDeleteObjectsOnClose()
  56.    .enableTabStop();
  57.   primary.setClient( &client );
  58.  
  59.   // Get default processing for an "open" and "help" event.
  60.   ICnrHandler
  61.     cnrHandler;
  62.   cnrHandler
  63.    .handleEventsFor( &client );
  64.  
  65.   // Support drag and drop of container objects.
  66.   IDMHandler::enableDragDropFor( &client );
  67.   CnrDragHelpProvider
  68.     provider;
  69.   client
  70.    .setItemProvider( &provider );
  71.  
  72.   ISystemPointerHandle
  73.     icon( ISystemPointerHandle::information );
  74.   CnrObject
  75.    *cnrObject = new CnrObject();
  76.   (*cnrObject)
  77.    .setIcon( icon )
  78.    .setIconText( "Object 1" );
  79.   client
  80.    .addObject( cnrObject );
  81.  
  82.   // Add a push button for displaying a file dialog and the command
  83.   // handler that processes the push button.
  84.   ISetCanvas
  85.     buttons( 1, &primary, &primary );
  86.   IPushButton
  87.     showFileDialog( ID_SHOWFILEDLG, &buttons, &buttons );
  88.   showFileDialog
  89.    .enableDefault()
  90.    .setText( "Show file dialog" )
  91.    .enableTabStop()
  92.    .enableGroup();
  93.   primary
  94.    .addExtension( &buttons, IFrameWindow::belowClient );
  95.   ShowFileDialogCmdHdr
  96.     cmdHdr;
  97.   cmdHdr
  98.    .handleEventsFor( &primary );
  99.  
  100.   // Create the help window and associate it with the primary window.
  101.   IHelpWindow::Settings
  102.     settings;
  103.   settings
  104.    .setTitle( "Help Example for Special Cases - Help" )
  105.    .setLibraries( "HELPOTHR.HLP" )
  106.    .setHelpTable( ID_HELPTABLE );
  107. #ifdef IPF_COMPATIBLE
  108.   IHelpWindow
  109.     help( settings, &primary,
  110.           IHelpWindow::classDefaultStyle
  111.            | IHelpWindow::ipfCompatible );
  112. #else
  113.   IHelpWindow
  114.     help( settings, &primary );
  115. #endif
  116.  
  117.   primary
  118.    .setFocus()
  119.    .show();
  120.  
  121.   IApplication::current().run();
  122. }
  123.  
  124. void CnrObject::handleOpen ( IContainerControl* container )
  125. {
  126.   ObjectView* frame =
  127.      new ObjectView( ID_SECONDARY, 0, container->parent() );
  128.   frame->setAutoDeleteObject();
  129.   IHelpWindow
  130.    *help = IHelpWindow::helpWindow( frame );
  131.   help->setAssociatedWindow( frame );
  132.   (*frame)
  133.    .setFocus()
  134.    .show();
  135. }
  136.  
  137. unsigned long CnrObject::helpId ( ) const
  138. {
  139.   // Return the help panel identifier for a container object.
  140.   return PANEL_CONTAINER;
  141. }
  142.  
  143. IContainerObject* CnrObject::objectCopy ( )
  144. {
  145.   // Copy the object to support copying via drag and drop.
  146.   CnrObject* copy = new CnrObject( *this );
  147.   return (IContainerObject *)copy;
  148. }
  149.  
  150. IBase::Boolean
  151.   CnrDragHelpProvider::provideHelpFor ( IDMTargetHelpEvent& event )
  152. {
  153.   IHelpWindow
  154.    *help = IHelpWindow::helpWindow( event.dispatchingWindow() );
  155.   help->show( IResourceId( PANEL_DROP ));
  156.   return true;
  157. }
  158.  
  159. IBase::Boolean NotebookTabHelpHdr::help ( IPageHelpEvent& event )
  160. {
  161.   // Display help for a notebook tab.  Get a previously stored help
  162.   // panel identifier from the user data of the page window.
  163.   Boolean
  164.     stopProcessingEvent = false;
  165.   IPageHandle
  166.     page = event.pageHandle();
  167.   INotebook::PageSettings
  168.     settings = event.notebook()->pageSettings( page );
  169.   unsigned long
  170.     panel = settings.userData();
  171.   if ( panel )
  172.   {
  173.      event.helpWindow()->show( IResourceId( panel ) );
  174.      stopProcessingEvent = true;
  175.   }
  176.   return stopProcessingEvent;
  177. }
  178.  
  179. #ifdef IC_PM
  180. // This function is called only when running in the OS/2
  181. // operating system.  For Windows, we instead use the
  182. // IWindow::setHelpId function for dynamically controlling the
  183. // general help panel of a canvas page window at runtime.
  184. IBase::Boolean
  185.   DynamicPageHelpHdr::handleError ( IHelpErrorEvent& event )
  186. {
  187.   Boolean
  188.     stopProcessingEvent = false;
  189.   if ( event.error() == IHelpErrorEvent::invalidHelpWindow )
  190.   {
  191.      // The help system cannot find the help panel to display,
  192.      // which in this case is PANEL_NONE, the general help
  193.      // panel for the notebook's frame window.  Hooking this
  194.      // error case allows us to dynamically display the
  195.      // general help panel based on the top page window.
  196.      unsigned long
  197.        helpPanel = 0;
  198.      IFrameWindow
  199.       *frame = (IFrameWindow*)event.dispatchingWindow();
  200.      INotebook
  201.       *notebook = (INotebook*)frame->client();
  202.  
  203.      if ( WinQueryActiveWindow( IWindow::desktopWindow()->handle() )
  204.                                                     != frame->handle() )
  205.      {
  206.         // Help for a notebook tab that has already been handled
  207.         // via IPageHandler::help by displaying a help panel
  208.         // (the help window is the active window now).  We need
  209.         // this check to avoid showing two help panels for a tab.
  210.      }
  211.      else
  212.      {
  213.         // Help for a non-frame window notebook page window.
  214.         IPageHandle
  215.           page = notebook->topPage();
  216.         IWindow
  217.          *pageWindow = notebook->window( page );
  218.         unsigned long
  219.           id = pageWindow->id();
  220.  
  221.         if ( id == ID_PAGE1 )
  222.         {
  223.            helpPanel = PANEL_PAGE1;
  224.         }
  225.         else if ( id == ID_PAGE2 )
  226.         {
  227.            helpPanel = PANEL_PAGE2;
  228.         }
  229.      }
  230.  
  231.      if ( helpPanel )
  232.      {
  233.         IHelpWindow
  234.          *help = IHelpWindow::helpWindow( frame );
  235.         help->show( IResourceId( helpPanel ) );
  236.         stopProcessingEvent = true;
  237.      }
  238.   }
  239.   return stopProcessingEvent;
  240. }
  241. #endif
  242.  
  243. IBase::Boolean DynamicPageHelpHdr::subitemNotFound
  244.                            ( IHelpSubitemNotFoundEvent& event )
  245. {
  246.   Boolean
  247.     stopProcessingEvent = false;
  248.   if ( event.isWindow() )
  249.   {
  250.      // The help system cannot find an entry in a help subtable for
  251.      // the control with the input focus.  By omitting the entry,
  252.      // we can hook this error case to dynamically display the
  253.      // contextual help panel for the current control.  In our case,
  254.      // we can display different help panels for two controls with
  255.      // the same window identifier.
  256.      unsigned long
  257.        topicId = event.topicId(),
  258.        subtopicId = event.subtopicId(),
  259.        helpPanel = 0;
  260.      if ( topicId == ID_PAGE1  &&  subtopicId == ID_ENTRY3 )
  261.      {
  262.         helpPanel = PANEL_ENTRY3;
  263.      }
  264. #ifdef IC_PM
  265.      // For Windows, we can also use the IWindow::setHelpId function
  266.      // for dynamically controlling the contextual help panel of a
  267.      // control.  We call IWindow::setHelpId in place of using the
  268.      // below code, which would have worked just as well, for the
  269.      // ID_ENTRYC entry field.
  270.      else if ( topicId == ID_PAGE2  &&  subtopicId == ID_ENTRYC )
  271.      {
  272.         helpPanel = PANEL_ENTRYC;
  273.      }
  274. #endif
  275.  
  276.      if ( helpPanel )
  277.      {
  278.         IFrameWindow
  279.          *frame = (IFrameWindow*)event.dispatchingWindow();
  280.         IHelpWindow
  281.          *help = IHelpWindow::helpWindow( frame );
  282.         help->show( IResourceId( helpPanel ) );
  283.         event.setResult( true );
  284.         stopProcessingEvent = true;
  285.      }
  286.   }
  287.   return stopProcessingEvent;
  288. }
  289.  
  290. ObjectView::ObjectView ( unsigned long id,
  291.                          IWindow* parent,
  292.                          IWindow* owner )
  293.   : IFrameWindow ( id, parent, owner, IRectangle(),
  294.                    IFrameWindow::defaultStyle()
  295.                     | IFrameWindow::dialogBackground ),
  296.     notebook ( ID_CLIENT, this, this ),
  297.     page1 ( ID_PAGE1, ¬ebook, ¬ebook ),
  298.     heading1 ( ID_DUMMY, &page1, &page1 ),
  299.     prompt1  ( ID_DUMMY, &page1, &page1 ),
  300.     prompt2  ( ID_DUMMY, &page1, &page1 ),
  301.     prompt3  ( ID_DUMMY, &page1, &page1 ),
  302.     entry1 ( ID_ENTRY1, &page1, &page1 ),
  303.     entry2 ( ID_ENTRY2, &page1, &page1 ),
  304.     entry3 ( ID_ENTRY3, &page1, &page1 ),
  305.     page2 ( ID_PAGE2, ¬ebook, ¬ebook ),
  306.     headingA ( ID_DUMMY, &page2, &page2 ),
  307.     promptA  ( ID_DUMMY, &page2, &page2 ),
  308.     promptB  ( ID_DUMMY, &page2, &page2 ),
  309.     promptC  ( ID_DUMMY, &page2, &page2 ),
  310.     entryA ( ID_ENTRYA, &page2, &page2 ),
  311.     entryB ( ID_ENTRYB, &page2, &page2 ),
  312.     entryC ( ID_ENTRYC, &page2, &page2 ),
  313.     page3 ( ID_PAGE3, ¬ebook, ¬ebook, IRectangle(),
  314.             IFrameWindow::dialogBackground ),
  315.     page3a ( ID_CLIENT, &page3, &page3 ),
  316.     headingX ( ID_DUMMY, &page3a, &page3a ),
  317.     promptX  ( ID_DUMMY, &page3a, &page3a ),
  318.     promptY  ( ID_DUMMY, &page3a, &page3a ),
  319.     entryX ( ID_ENTRYX, &page3a, &page3a ),
  320.     entryY ( ID_ENTRYY, &page3a, &page3a ),
  321.     dialog ( ID_DIALOG, ¬ebook, ¬ebook )
  322. {
  323.   ITitle
  324.     title( this, "Object1 - View" );
  325.   this->setClient( ¬ebook );
  326.  
  327.   // Set-up the first page.
  328.   heading1
  329.    .setText( "This is a canvas page window." );
  330.   prompt1
  331.    .setText( "Has contextual help" );
  332.   prompt2
  333.    .setText( "No contextual help" );
  334.   prompt3
  335.    .setText( "Dynamic contextual help" );
  336.   entry1
  337.    .enableTabStop()
  338.    .enableGroup();
  339.   entry2
  340.    .enableTabStop();
  341.   entry3
  342.    .enableTabStop();
  343.   page1
  344.    .addToCell( &heading1, 2, 2, 3 )
  345.    .addToCell( &prompt1,  2, 4 )
  346.    .addToCell( &prompt2,  2, 6 )
  347.    .addToCell( &prompt3,  2, 8 )
  348.    .addToCell( &entry1,   4, 4 )
  349.    .addToCell( &entry2,   4, 6 )
  350.    .addToCell( &entry3,   4, 8 );
  351.   page1
  352.    .setColumnWidth( 4, 1, true )
  353.    .setColumnWidth( 7, IMultiCellCanvas::defaultCell().width() )
  354.    .setRowHeight( 1, 20, true )
  355.    .setRowHeight( 3, 20, true )
  356.    .setRowHeight( 5, 20, true )
  357.    .setRowHeight( 7, 20, true )
  358.    .setRowHeight( 9, 20, true )
  359.    .sizeTo( page1.minimumSize() );
  360.  
  361.   // Set-up the second page.
  362.   headingA
  363.    .setText( "This is another canvas page window." );
  364.   promptA
  365.    .setText( "Has contextual help" );
  366.   promptB
  367.    .setText( "No contextual help" );
  368.   promptC
  369.    .setText( "Dynamic contextual help" );
  370. #ifdef IC_WIN
  371.   // For OS/2, we use IHelpHandler virtual functions in place of
  372.   // calls to IWindow::setHelpId for dynamically controlling the
  373.   // contextual help panels of the entry fields and general help
  374.   // panel of this canvas.
  375.   entryA
  376.    .setHelpId( PANEL_ENTRYA );
  377.   entryC
  378.    .setHelpId( PANEL_ENTRYC );
  379.   page2
  380.    .setHelpId( PANEL_PAGE2 );
  381. #endif
  382.   entryA
  383.    .enableTabStop()
  384.    .enableGroup();
  385.   entryB.enableTabStop();
  386.   entryC.enableTabStop();
  387.   page2
  388.    .addToCell( &headingA, 2, 2, 3 )
  389.    .addToCell( &promptA,  2, 4 )
  390.    .addToCell( &promptB,  2, 6 )
  391.    .addToCell( &promptC,  2, 8 )
  392.    .addToCell( &entryA,   4, 4 )
  393.    .addToCell( &entryB,   4, 6 )
  394.    .addToCell( &entryC,   4, 8 );
  395.   page2
  396.    .setColumnWidth( 4, 1, true )
  397.    .setColumnWidth( 7, IMultiCellCanvas::defaultCell().width() )
  398.    .setRowHeight( 1, 20, true )
  399.    .setRowHeight( 3, 20, true )
  400.    .setRowHeight( 5, 20, true )
  401.    .setRowHeight( 7, 20, true )
  402.    .setRowHeight( 9, 20, true )
  403.    .sizeTo( page2.minimumSize() );
  404.  
  405.   // Set-up the third page.
  406. #ifdef IC_PM
  407.   childHelpHdr
  408.    .handleEventsFor( &page3 );
  409. #endif
  410.   headingX
  411.    .setText( "This is another canvas in a frame page window." );
  412.   promptX
  413.    .setText( "Has contextual help" );
  414.   promptY
  415.    .setText( "No contextual help" );
  416.   entryX
  417.    .enableTabStop()
  418.    .enableGroup();
  419.   entryY.enableTabStop();
  420.   page3a
  421.    .addToCell( &headingX, 2, 2, 3 )
  422.    .addToCell( &promptX,  2, 4 )
  423.    .addToCell( &promptY,  2, 6 )
  424.    .addToCell( &entryX,   4, 4 )
  425.    .addToCell( &entryY,   4, 6 );
  426.   page3a
  427.    .setColumnWidth( 4, 1, true )
  428.    .setColumnWidth( 7, IMultiCellCanvas::defaultCell().width() )
  429.    .setRowHeight( 1, 20, true )
  430.    .setRowHeight( 3, 20, true )
  431.    .setRowHeight( 5, 20, true )
  432.    .setRowHeight( 7, 20, true )
  433.    .sizeTo( page3a.minimumSize() );
  434.   page3
  435.    .setClient( &page3a );
  436.   page3
  437.    .setMinimumSize( page3.frameRectFor( page3a.rect() ).size() );
  438.  
  439.   // Set-up the fourth page.
  440. #ifdef IC_PM
  441.   childHelpHdr
  442.    .handleEventsFor( &dialog );
  443. #endif
  444.   IColor background =
  445.     notebook.backgroundColor();
  446.   notebook
  447.    .setMinorTabSize( ISize( ) )
  448.    .setBinding( INotebook::spiral )
  449.    .setPageBackgroundColor( background )
  450.    .setMajorTabBackgroundColor( background );
  451.   tabHelpHdr
  452.    .handleEventsFor( ¬ebook );
  453.   dynamicPageHelpHdr
  454.    .handleEventsFor( this );
  455.  
  456.   // Add the pages to the notebook.
  457.   // Store the help panel identifiers for the notebook tabs as
  458.   // user data for the page.
  459.   INotebook::PageSettings
  460.     pageInfo( "1st", 0,
  461.               INotebook::PageSettings::autoPageSize
  462.                | INotebook::PageSettings::majorTab );
  463.   pageInfo
  464.    .setUserData( PANEL_PAGE1_TAB );
  465.   notebook
  466.    .addFirstPage( pageInfo, &page1 );
  467.   pageInfo
  468.    .setTabText( "2nd" )
  469.    .setUserData( PANEL_PAGE2_TAB );
  470.   notebook
  471.    .addLastPage( pageInfo, &page2 );
  472.   pageInfo
  473.    .setTabText( "3rd" )
  474.    .setUserData( PANEL_PAGE3_TAB );
  475.   notebook
  476.    .addLastPage( pageInfo, &page3 );
  477.   pageInfo
  478.    .setTabText( "4rth" )
  479.    .setUserData( PANEL_DIALOG_TAB );
  480.   notebook
  481.    .addLastPage( pageInfo, &dialog );
  482.  
  483.   IPoint
  484.     nextShellPoint = IFrameWindow::nextShellRect().bottomLeft();
  485.   (*this)
  486.    .moveSizeToClient( IRectangle( nextShellPoint,
  487.                                   (ISize)notebook.minimumSize() ));
  488.   notebook
  489.    .setFocus();
  490. }
  491.  
  492. IBase::Boolean ShowFileDialogCmdHdr::command ( ICommandEvent& event )
  493. {
  494.   Boolean
  495.     stopProcessingEvent = false;
  496.   if ( event.commandId() == ID_SHOWFILEDLG )
  497.   {
  498.      IFileDialog
  499.        fileDialog( 0,
  500.                    event.dispatchingWindow(),
  501.                    IFileDialog::classDefaultStyle
  502.                     | IFileDialog::helpButton );
  503.   }
  504.   return stopProcessingEvent;
  505. }
  506.