home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / samples / ioc / clipbrd / clipbrd.cpp next >
Encoding:
C/C++ Source or Header  |  1996-02-22  |  19.1 KB  |  446 lines

  1. /******************************************************************************
  2. * .FILE:         clipbrd.cpp                                                  *
  3. *                                                                             *
  4. * .DESCRIPTION:  Clipboard Sample Program :            Class Implementation   *
  5. *                                                                             *
  6. * .CLASSES:      ContainerCutPasteHandler                                     *
  7. *                Department                                                   *
  8. *                                                                             *
  9. * .COPYRIGHT:                                                                 *
  10. *    Licensed Material - Program-Property of IBM                              *
  11. *    (C) Copyright IBM Corp. 1992, 1995 - All Rights Reserved                 *
  12. *                                                                             *
  13. * .DISCLAIMER:                                                                *
  14. *   The following [enclosed] code is sample code created by IBM               *
  15. *   Corporation.  This sample code is not part of any standard IBM product    *
  16. *   and is provided to you solely for the purpose of assisting you in the     *
  17. *   development of your applications.  The code is provided 'AS IS',          *
  18. *   without warranty of any kind.  IBM shall not be liable for any damages    *
  19. *   arising out of your use of the sample code, even if they have been        *
  20. *   advised of the possibility of such damages.                               *
  21. *                                                                             *
  22. * .NOTE: WE RECOMMEND USING A FIXED SPACE FONT TO LOOK AT THE SOURCE          *
  23. *                                                                             *
  24. ******************************************************************************/
  25. #ifndef _IBASE_                         //  Ensure ibase.hpp is included
  26.   #include <ibase.hpp>                  //  since that is where IC_<environ>
  27. #endif                                  //  is defined.
  28. #include <iframe.hpp>
  29. #include <ipopmenu.hpp>
  30. #include <iclipbrd.hpp>
  31. #include <icliphdr.hpp>
  32. #include <icmdhdr.hpp>
  33. #include <icnr.hpp>
  34. #include <icnrolst.hpp>
  35. #include <istring.hpp>
  36. #include <istparse.hpp>
  37. #include <iexcept.hpp>
  38. #include <itrace.hpp>
  39. #include <ireslib.hpp>
  40. #include <icoordsy.hpp>
  41. #include "clipbrd.h"
  42. #include "clipbrd.hpp"
  43.  
  44. // Define our static Separator objects:
  45. //   The first separates fields in the Department object string;
  46. //   the second separates multiple Department object strings.
  47.  
  48.  
  49. const IString Department::separator("~");
  50. const IString ContainerCutPasteHandler::separator("^");
  51.  
  52. // Define the private format of our Department object.
  53. const IString Department::renderedFormat("Department_rendered");
  54.  
  55.  
  56. //*************************************************************************
  57. // main  - Application entry point                                        *
  58. //*************************************************************************
  59. int main()
  60. {
  61.   ICoordinateSystem::setApplicationOrientation(
  62.           ICoordinateSystem::originLowerLeft );
  63.   IResourceLibrary reslib;
  64.   IFrameWindow frame(reslib.loadString(WND_MAIN), WND_MAIN);
  65.  
  66.   // Create the details view container with columns that
  67.   // displays the Department name and address.
  68.   IContainerControl container(0x8008, &frame, &frame);
  69.   IContainerColumn name(IContainerColumn::isIconViewText);
  70.   IContainerColumn address( Department::offsetOfAddress());
  71.   name.setHeadingText( STR_HEAD_1 );
  72.   address.setHeadingText( STR_HEAD_2 );
  73.   container.addColumn(&name);
  74.   container.addColumn(&address);
  75.  
  76.   // Create the Department objects and add them to
  77.   // the container.
  78.   Department* department;
  79.   department = new Department(reslib.loadString(STR_ITEM_1_1),
  80.                               reslib.loadString(STR_ITEM_1_2));
  81.   container.addObject(department);
  82.   department = new Department(reslib.loadString(STR_ITEM_2_1),
  83.                               reslib.loadString(STR_ITEM_2_2));
  84.   container.addObject(department);
  85.  
  86.   // Create the cut and paste handler (the handlers are
  87.   // added in the constructor).
  88.   ContainerCutPasteHandler handler(container);
  89.  
  90.   // Enable extended selection, switch to details view, and
  91.   // give the container the focus.
  92.   container.setExtendedSelection();
  93.   container.showDetailsView();
  94.   container.setFocus();
  95.  
  96.   // Add an icon to the frame, put the container in the
  97.   // client, and show the frame window.
  98.   frame.setIcon( frame.id() );
  99.   frame.setClient(&container);
  100.   frame.show();
  101.  
  102.   // Start processing events.
  103.   IApplication::current().run();
  104.  
  105.   return 0;
  106. }
  107.  
  108.  
  109. /*------------------------------------------------------------------------------
  110. | ContainerCutPasteHandler::ContainerCutPasteHandler                           |
  111. |                                                                              |
  112. | Construct the handlers, register our private clipboard format, and          |
  113. | attach the handlers to the container.                                        |
  114. ------------------------------------------------------------------------------*/
  115. ContainerCutPasteHandler :: ContainerCutPasteHandler ( IContainerControl& container)
  116.       : cnr(container),
  117.         objectList(new ICnrObjectSet())
  118. {
  119.   // Enable the command, menu, and clipboard handlers.
  120.   ICommandHandler::handleEventsFor(&container);
  121.   ICnrMenuHandler::handleEventsFor(&container);
  122.   IClipboardHandler::handleEventsFor(&container);
  123.  
  124.   // Register the Department object's private format.
  125.   IClipboard::registerFormat( Department::renderedFormat);
  126. }
  127.  
  128.  
  129. /*------------------------------------------------------------------------------
  130. | ContainerCutPasteHandler::command                                            |
  131. |                                                                              |
  132. | Handle the command events associated with the clipboard (Cut, Copy,          |
  133. | and Paste).                                                                  |
  134. ------------------------------------------------------------------------------*/
  135. IBase::Boolean ContainerCutPasteHandler::command ( ICommandEvent& event)
  136. {
  137.   switch(event.commandId())
  138.   {
  139.     case MI_CUT           :
  140.     case MI_COPY          :
  141.     {
  142.       // Empty the clipboard to establish ownership
  143.       IClipboard clipboard(event.window()->handle());
  144.       clipboard.empty();
  145.  
  146.       // Find the cursored object in the container.
  147.       Department* cursoredObject = (Department*)(container().cursoredObject());
  148.  
  149.       // Utilize delayed rendering to put the data of the private
  150.       // format on the clipboard.  Maintain an "objectList" collection
  151.       // to keep track of the objects cut or copied onto the clipboard.
  152.       // Then, use the collection to render objects in the private
  153.       // format.  Store text data for the objects so that applications
  154.       // that don't support the private format can paste the data into a
  155.       // text editor.
  156.  
  157.       // Clear the collection used to keep track of clipboard objects.
  158.       objectList->removeAll();
  159.  
  160.       // If the cursored object is selected, loop through all other
  161.       // selected objects and store the objects in our set.
  162.       if (container().isSelected(cursoredObject))
  163.       {
  164.         unsigned long count = 0;
  165.         IString objectsAsText("\0");
  166.         IContainerControl::ObjectCursor cursor(container(), IContainerObject::selected);
  167.         for (cursor.setToFirst(); cursor.isValid(); cursor.setToNext())
  168.         {
  169.           count++;
  170.           Department* selectedObject = (Department*)(container().objectAt(cursor));
  171.           objectList->add(selectedObject);
  172.           objectsAsText = objectsAsText +  selectedObject->text();
  173.         }
  174.  
  175.         // Put the data on the clipboard.  We put our private
  176.         // format first since it has the most information.
  177.         // We use 0 for the data pointer of our private format
  178.         // because we want to delay the rendering until
  179.         // the paste operation.
  180.  
  181.         clipboard.setData(Department::renderedFormat, 0, 0);
  182.         clipboard.setText(objectsAsText);
  183.  
  184.         // If this is a Cut, put the data on the clipboard
  185.         // instead of using delayed rendering because we delete
  186.         // the object. Therefore we request the data
  187.         // to force the delayed rendering by our handler.
  188.         if (event.commandId() == MI_CUT)
  189.         {
  190.           char* data = (char*)clipboard.data(Department::renderedFormat);
  191.           container().deleteSelectedObjects();
  192.         }
  193.       }
  194.       else
  195.       {
  196.         // If the object is not selected, repeat the above procedure
  197.         // for the cursored object.
  198.         objectList->add(cursoredObject);
  199.  
  200.         // Put the data on the clipboard (requesting
  201.         // delayed rendering).
  202.         clipboard.setData(Department::renderedFormat, 0,0);
  203.  
  204.         // If this is a Cut request, force the ClipboardCutPasteHandler
  205.         // to render the data by requesting the data.  Then, delete the
  206.         // cursored object.
  207.         if (event.commandId() == MI_CUT) {
  208.           char* data = (char*)clipboard.data(Department::renderedFormat);
  209.           container().removeObject(cursoredObject);
  210.           delete cursoredObject;
  211.         }
  212.       }
  213.       return true;
  214.     }
  215.     case MI_PASTE         :
  216.     {
  217.       IClipboard clipboard(event.window()->handle());
  218.  
  219.       // If the clipboard has data of the private format,
  220.       // get the data and build objects from it.
  221.       // Note:  To see the text format of the data, paste
  222.       // from the clipboard using any text editor that
  223.       // supports the clipboard.
  224.       if (clipboard.hasData(Department::renderedFormat))
  225.       {
  226.          IString strCount, strObject, objectsAsString;
  227.  
  228.          // Query the data on the clipboard.
  229.          char* data = (char*)clipboard.data(Department::renderedFormat);
  230.  
  231.          // Parse the string into our data fields.
  232.          data >> strCount >> separator >> objectsAsString;
  233.  
  234.          // Extract the number of objects stored in the string.
  235.          unsigned long count = strCount.asUnsigned();
  236.  
  237.          // Turn refresh off to eliminate multiple painting.
  238.          container().setRefreshOff();
  239.  
  240.          // Construct new objects from the data.
  241.          for( int i=0; i<count; i++)
  242.          {
  243.            objectsAsString >> strObject >> separator >> objectsAsString;
  244.            Department* department = new Department();
  245.            department->initializeFromString(strObject);
  246.            container().addObject(department);
  247.          }
  248.  
  249.          // Enable refresh and refresh the container.
  250.          container().setRefreshOn();
  251.          container().refresh();
  252.       }
  253.       return true;
  254.     }
  255.   }
  256. return false;
  257. }
  258.  
  259.  
  260. /*------------------------------------------------------------------------------
  261. | ContainerCutPasteHandler::makePopUpMenu                                      |
  262. |                                                                              |
  263. | Create a pop-up menu with the clipboard actions.                             |
  264. ------------------------------------------------------------------------------*/
  265. IBase::Boolean ContainerCutPasteHandler::makePopUpMenu(IMenuEvent& event)
  266. {
  267.   IPopUpMenu* popUpMenu = new IPopUpMenu(CNR_POPUPMENU,
  268.                                          event.window());
  269.  
  270.   // Enable the allowable menu items in the pop-up menu.
  271.   if (popupMenuObject()) {
  272.     ((IContainerControl*)event.window())->setCursor(popupMenuObject());
  273.     popUpMenu->disableItem(MI_PASTE);
  274.   }
  275.   else
  276.   {
  277.     popUpMenu->disableItem(MI_CUT);
  278.     popUpMenu->disableItem(MI_COPY);
  279.   }
  280.  
  281.   //  Show the menu.
  282.   popUpMenu->setAutoDeleteObject();
  283.   popUpMenu->show(event.mousePosition());
  284.   return true;
  285. }
  286.  
  287. /*------------------------------------------------------------------------------
  288. | ContainerCutPasteHandler::clipboardEmptied                                   |
  289. |                                                                              |
  290. | This function is responsible for cleaning up data when the clipboard is      |
  291. | emptied and has nothing to do for now.                                       |
  292. ------------------------------------------------------------------------------*/
  293. IBase::Boolean ContainerCutPasteHandler::clipboardEmptied ( IEvent& )
  294. {
  295.   return true;
  296. }
  297.  
  298. /*------------------------------------------------------------------------------
  299. | ContainerCutPasteHandler::renderFormat                                       |
  300. |                                                                              |
  301. | Put our private format data on the clipboard.                                |
  302. ------------------------------------------------------------------------------*/
  303. IBase::Boolean ContainerCutPasteHandler::renderFormat( IEvent& event,
  304.                                                const IString&  format)
  305. {
  306.   // Use the handler's collection to find the Department objects
  307.   // whose data we need to put on the clipboard.
  308.   // Note:  If data gets copied to the clipboard for a Department
  309.   //        object and the object is deleted before the paste
  310.   //        operation, we will not be able to supply the object's
  311.   //        data.  If this is a problem, do not use delayed
  312.   //        rendering or post a message to the container telling
  313.   //        it to renderAllFormats whenever objects are deleted in
  314.   //        the container.
  315.   IClipboard clipboard(event.window()->handle());
  316.   if (clipboard.hasData(Department::renderedFormat))
  317.   {
  318.      // Cursor the objects and build the string.
  319.      ICnrObjectSet::Cursor cursor(*objectList);
  320.  
  321.      IString objectsAsString("\0");
  322.      unsigned long count = 0;
  323.  
  324.      // Loop through our collection and query the object for
  325.      // its data.
  326.      for( cursor.setToFirst(); cursor.isValid(); cursor.setToNext())
  327.      {
  328.        count++;
  329.        Department* department = (Department*)objectList->elementAt(cursor);
  330.  
  331.        // Document that no support is present for rendering objects
  332.        // after they are removed from the container.
  333.        IASSERTSTATE(container().containsObject(department));
  334.  
  335.        objectsAsString = objectsAsString + separator
  336.                                       + department->asString();
  337.      }
  338.      // Build the final string and put the data on the clipboard.
  339.      objectsAsString  =  IString(count) + objectsAsString;
  340.      clipboard.setData(Department::renderedFormat,
  341.                        (const char*)objectsAsString,
  342.                        objectsAsString.size()+1);
  343.   }
  344. return true;
  345.  
  346. }
  347.  
  348.  
  349. /*------------------------------------------------------------------------------
  350. | ContainerCutPasteHandler::renderAllFormats                                   |
  351. |                                                                              |
  352. | Pass this on to our function to render a single format since we only use     |
  353. | one format with delayed rendering.                                           |
  354. ------------------------------------------------------------------------------*/
  355. IBase::Boolean ContainerCutPasteHandler::renderAllFormats( IEvent& event)
  356. {
  357.   return renderFormat(event, Department::renderedFormat);
  358. }
  359.  
  360.  
  361. /*------------------------------------------------------------------------------
  362. | Department::name                                                             |
  363. |                                                                              |
  364. | Return the name of the Department object.                                    |
  365. ------------------------------------------------------------------------------*/
  366. IString Department::name( ) const
  367. {
  368.   return iconText();
  369. }
  370.  
  371. /*------------------------------------------------------------------------------
  372. | Department::address                                                          |
  373. |                                                                              |
  374. | Return the address of the Department object.                                 |
  375. ------------------------------------------------------------------------------*/
  376. IString Department::address( ) const
  377. {
  378.   return strAddress;
  379. }
  380.  
  381. /*------------------------------------------------------------------------------
  382. | Department::setName                                                          |
  383. |                                                                              |
  384. | Set the name of the Department object.                                       |
  385. ------------------------------------------------------------------------------*/
  386. Department& Department::setName( const IString& name)
  387. {
  388.   setIconText(name);
  389.   return *this;
  390. }
  391.  
  392. /*------------------------------------------------------------------------------
  393. | Department::setAddress                                                       |
  394. |                                                                              |
  395. | Set the address of the Department object.                                    |
  396. ------------------------------------------------------------------------------*/
  397. Department& Department::setAddress( const IString& address)
  398. {
  399.   strAddress = address;
  400.   return *this;
  401. }
  402.  
  403. /*------------------------------------------------------------------------------
  404. | Department::asString                                                         |
  405. |                                                                              |
  406. | Render the Department object as a String that we can later use to            |
  407. | reconstruct a Department object.                                             |
  408. ------------------------------------------------------------------------------*/
  409. IString Department::asString ( ) const
  410. {
  411.   IString strObject = name() + separator + address();
  412.   return strObject;
  413. }
  414.  
  415. /*------------------------------------------------------------------------------
  416. | Department::text                                                             |
  417. |                                                                              |
  418. | Render the Department object as a text string with Name formatted to         |
  419. | 30 characters, and address formatted to 50 characters with both              |
  420. | followed by a new line character.  Use this format for storing a plain       |
  421. | text format of our object on the clipboard.                                  |
  422. ------------------------------------------------------------------------------*/
  423. IString Department::text ( ) const
  424. {
  425.   IString strObject(name().subString(1,30) + address().subString(1,50) + "\n");
  426.   return strObject;
  427. }
  428.  
  429.  
  430. /*------------------------------------------------------------------------------
  431. | Department::initializeFromString                                             |
  432. |                                                                              |
  433. | Set the fields of the object by parsing the passed string.                   |
  434. ------------------------------------------------------------------------------*/
  435. Department& Department::initializeFromString ( const IString& renderedString )
  436. {
  437.   IString strName, strAddress;
  438.   renderedString >> strName >> separator >> strAddress;
  439.   setName (strName);
  440.   setAddress(strAddress);
  441.  
  442.   return *this;
  443. }
  444.  
  445.  
  446.