home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / odtlktv6.zip / ODTLKT / TOOLKIT / BOOK / ODPGGDE1.INF (.txt) next >
OS/2 Help File  |  1995-12-14  |  1MB  |  14,438 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. How to Use this Book ΓòÉΓòÉΓòÉ
  3.  
  4. This guide is intended for application developers creating programs using the 
  5. OpenDoc interface for OS/2 Warp who want to gain an understanding of the 
  6. OpenDoc programming environment and to develop part editors. 
  7.  
  8. Before you begin to use this information, it would be helpful to understand how 
  9. you can: 
  10.  
  11.      Expand the Contents to see all available topics 
  12.      Obtain additional information for a highlighted word or phrase 
  13.      Use action bar choices 
  14.      Use the programming information. 
  15.  
  16.  How to Use the Contents 
  17.  
  18.  When the Contents window first appears, some topics have a plus (+) sign 
  19.  beside them. The plus sign indicates that additional topics are available. 
  20.  
  21.  To expand the Contents if you are using a mouse, click on the plus sign. If 
  22.  you are using the keyboard, use the Up or Down Arrow key to highlight the 
  23.  topic, and press the plus (+) key. For example, Code Pages has a plus sign 
  24.  beside it. To see additional topics for that heading, click on the plus sign 
  25.  or highlight that topic and press the plus (+) key. 
  26.  
  27.  To view a topic, double-click on the topic (or press the Up or Down Arrow key 
  28.  to highlight the topic, and then press the Enter key). 
  29.  
  30.  How to Obtain Additional Information 
  31.  
  32.  After you select a topic, the information for that topic appears in a window. 
  33.  Highlighted words or phrases indicate that additional information is 
  34.  available. You will notice that certain words and phrases are highlighted in 
  35.  green letters, or in white letters on a black background. These are called 
  36.  hypertext terms. If you are using a mouse, double-click on the highlighted 
  37.  word. If you are using a keyboard, press the Tab key to move to the 
  38.  highlighted word, and then press the Enter key. Additional information then 
  39.  appears in a window. 
  40.  
  41.  How to Use Action Bar Choices 
  42.  
  43.  Several choices are available for managing information presented in the 
  44.  OpenDoc Class Reference for the Macintosh. There are three pull-down menus on 
  45.  the action bar:  the Services menu, the Options menu, and the Help menu. 
  46.  
  47.  The actions that are selectable from the Services menu operate on the active 
  48.  window currently displayed on the screen. These actions include the following: 
  49.  
  50.  Bookmark 
  51.     Allows you to set a placeholder so you can retrieve information of interest 
  52.     to you. 
  53.  
  54.     When you place a bookmark on a topic, it is added to a list of bookmarks 
  55.     you have previously set. You can view the list, and you can remove one or 
  56.     all bookmarks from the list. If you have not set any bookmarks, the list is 
  57.     empty. 
  58.  
  59.     To set a bookmark, do the following: 
  60.  
  61.       1. Select a topic from the Contents. 
  62.  
  63.       2. When that topic appears, choose the Bookmark option from the Services 
  64.          pull-down. 
  65.  
  66.       3. If you want to change the name used for the bookmark, type the new 
  67.          name in the field. 
  68.  
  69.       4. Click on the Place radio button (or press the Up or Down Arrow key to 
  70.          select it). 
  71.  
  72.       5. Click on OK (or select it and press Enter). The bookmark is then added 
  73.          to the bookmark list. 
  74.  
  75.  Search 
  76.     Allows you to find occurrences of a word or phrase in the current topic, 
  77.     selected topics, or all topics. 
  78.  
  79.     You can specify a word or phrase to be searched. You can also limit the 
  80.     search to a set of topics by first marking the topics in the Contents list. 
  81.  
  82.     To search for a word or phrase in all topics, do the following: 
  83.  
  84.       1. Choose the Search option from the Services pull-down. 
  85.  
  86.       2. Type the word or words to be searched for. 
  87.  
  88.       3. Click on All sections (or press the Up or Down Arrow keys to select 
  89.          it). 
  90.  
  91.       4. Click on Search (or select it and press Enter) to begin the search. 
  92.  
  93.       5. The list of topics where the word or phrase appears is displayed. 
  94.  
  95.  Print 
  96.     Allows you to print one or more topics. You can also print a set of topics 
  97.     by first marking the topics in the Contents list. 
  98.  
  99.     To print the document Contents list, do the following: 
  100.  
  101.       1. Choose Print from the Services pull-down. 
  102.  
  103.       2. Click on Contents (or press the Up or Down Arrow key to select it). 
  104.  
  105.       3. Click on Print (or select it and press Enter). 
  106.  
  107.       4. The Contents list is printed on your printer. 
  108.  
  109.  Copy 
  110.     Allows you to copy a topic that you are viewing to the System Clipboard or 
  111.     to a file that you can edit. You will find this particularly useful for 
  112.     copying syntax definitions and program samples into the application that 
  113.     you are developing. 
  114.  
  115.     You can copy a topic that you are viewing in two ways: 
  116.  
  117.         Copy copies the topic that you are viewing into the System Clipboard. 
  118.          If you are using a Presentation Manager editor (for example, the 
  119.          System Editor) that copies or cuts (or both) to the System Clipboard, 
  120.          and pastes to the System Clipboard, you can easily add the copied 
  121.          information to your program source module. 
  122.  
  123.         Copy to file copies the topic that you are viewing into a temporary 
  124.          file named TEXT.TMP. You can later edit that file by using any editor. 
  125.          You will find TEXT.TMP in the directory where your viewable document 
  126.          resides. 
  127.  
  128.          To copy a topic, do the following: 
  129.  
  130.            1. Expand the Contents list and select a topic. 
  131.  
  132.            2. When the topic appears, choose Copy to file from the Services 
  133.               pull-down. 
  134.  
  135.            3. The system puts the text pertaining to that topic into the 
  136.               temporary file named TEXT.TMP. 
  137.  
  138.     For information on one of the other choices in the Services pull-down, 
  139.     highlight the choice and press the F1 key. 
  140.  
  141.  The actions that are selectable from the Options menu allow you to change the 
  142.  way your Contents list is displayed. To expand the Contents and show all 
  143.  levels for all topics, choose Expand all from the Options pull-down. You can 
  144.  also press the Ctrl and * keys together. For information on one of the other 
  145.  choices in the Options pull-down, highlight the choice and press the F1 key. 
  146.  
  147.  The actions that are selectable from the Help menu allow you to select 
  148.  different types of help information. You can also press the F1 key for help 
  149.  information about the Information Presentation Facility (IPF). 
  150.  
  151.  
  152. ΓòÉΓòÉΓòÉ 1.1. OpenDoc Fundamentals ΓòÉΓòÉΓòÉ
  153.  
  154. OpenDoc is an architecture designed to enable the construction of compound, 
  155. collaborative, customizable, and cross-platform applications. It enables the 
  156. creation of compound documents, which are created and edited by several 
  157. cooperating applications working within a single document. OpenDoc also 
  158. supports scripting and extension mechanisms that allow for communication among 
  159. parts of a document. OpenDoc allows for multiple parts in a single document. 
  160. These different parts can range from a spread sheet to voice inside of the 
  161. document. 
  162.  
  163. OpenDoc consists of a set of shared libraries that can be used to build editors 
  164. and viewers for compound documents, as well as other compound software to 
  165. provide services to documents. 
  166.  
  167.  
  168. ΓòÉΓòÉΓòÉ 2. About Component Integration Laboratories ΓòÉΓòÉΓòÉ
  169.  
  170. OpenDoc is presented and maintained through an organization devoted to 
  171. promoting cross-platform standards, architectures, and protocols in a 
  172. vendor-independent fashion. This organization, Component Integration 
  173. Laboratories (CI Labs), is composed of a number of platform and application 
  174. vendors with a common interest in solving OpenDoc issues and promoting 
  175. interoperability. 
  176.  
  177. CI Labs supports several levels of participation through different membership 
  178. categories. If you are interested in shaping the future direction of component 
  179. software, or if you simply need to be kept abreast of the latest developments, 
  180. you can become a member. For an information packet, send your mailing address 
  181. to: 
  182.  
  183.       Component Integration Laboratories 
  184.       PO Box 61747 
  185.       Sunnyvale, CA  94088-1747 
  186.  
  187.       Telephone:          408-864-0300 
  188.       FAX:                408-864-0380 
  189.       Internet:           cilabs@cilabs.org 
  190.  
  191.  
  192. ΓòÉΓòÉΓòÉ 3. Introduction ΓòÉΓòÉΓòÉ
  193.  
  194. OpenDoc is a revolutionary technology that brings a new class of applications 
  195. and documents to the Windows, Mac OS, OS/2, UNIX, and other personal-computer 
  196. platforms. With OpenDoc, hardware and software developers can deliver: 
  197.  
  198.      New software technologies to individual users 
  199.      Better server integration to corporate users 
  200.      Enhanced multimedia content to all users 
  201.  
  202.  OpenDoc enables the creation of cooperative component software that supports 
  203.  compound documents, can be customized, can be used collaboratively across 
  204.  networks, and is available across multiple platforms. In doing so, OpenDoc 
  205.  fundamentally changes the nature of software development for personal 
  206.  computers. 
  207.  
  208.  This chapter starts with a review of the reasons why OpenDoc was created, 
  209.  followed by an overview of OpenDoc concepts: 
  210.  
  211.      How OpenDoc documents are structured 
  212.      How OpenDoc software handles events and user interaction 
  213.      How to extend OpenDoc's capabilities 
  214.      How to ensure cross-platform compatibility for your OpenDoc software 
  215.  
  216.  Each of these topics is described more fully in subsequent chapters. 
  217.  
  218.  
  219. ΓòÉΓòÉΓòÉ 3.1. Why OpenDoc? ΓòÉΓòÉΓòÉ
  220.  
  221. Customer demand for increasingly sophisticated and integrated software 
  222. solutions has led to large and sometimes unwieldy application packages, 
  223. feature-laden but difficult to maintain and modify. Developing, maintaining, 
  224. and upgrading these large, cumbersome applications can require a vast 
  225. organization. The programs are difficult to create, expensive to maintain, and 
  226. can take years to revise. 
  227.  
  228. Upgrades or bug fixes in one component of such an application require the 
  229. developer to release-and the customer to buy-a completely new version of the 
  230. entire package. Some developers have added extension mechanisms to their 
  231. packages to allow addition or replacement of certain components, but the 
  232. extensions are proprietary, incompatible with other applications, and 
  233. applicable to only certain parts of the package. 
  234.  
  235. Because of the barriers put up by the current application architecture, users 
  236. are often frustrated in attempting to perform common tasks: 
  237.  
  238.      Users often cannot assemble complex documents from multiple sources 
  239.       because of the many error-prone, manual operations required. 
  240.  
  241.      Users often cannot edit different kinds of content within a single 
  242.       document. Most applications support only one or a few different kinds of 
  243.       content, such as a single format for text and a single format for 
  244.       graphics. Furthermore, the editing procedures for a given kind of content 
  245.       are different across applications, complicating data transfer among 
  246.       applications. 
  247.  
  248.      Business users are forced to choose between the reliability of 
  249.       shrink-wrapped software and the extra features of custom solutions 
  250.       designed for their needs. To increase reliability while maintaining and 
  251.       adding custom features, businesses need simple and standardized designs 
  252.       and procedures. 
  253.  
  254.      Users may not be able to use an editor or tool provided by an individual 
  255.       developer or small development team because the editor may be 
  256.       incompatible with the users' current application package, and the 
  257.       developer may not have sufficient resources to develop an entire 
  258.       integrated package. 
  259.  
  260.      Computers often frustrate users' efforts to collaborate with others. 
  261.       Users cannot share documents across applications, recover changes to 
  262.       shared documents, or, with rare exceptions, manipulate the contents of 
  263.       one document from within another. 
  264.  
  265.  OpenDoc addresses these issues by enabling the development of a new kind of 
  266.  application, one that provides advantages to both users and developers in the 
  267.  increasingly competitive software markets of today and the future. OpenDoc 
  268.  replaces the architecture of conventional monolithic applications in which a 
  269.  single software package is responsible for all its documents' contents, with 
  270.  one of components, in which each software module edits its own content, no 
  271.  matter what document that content might be in. This is illustrated in the 
  272.  following figure. 
  273.  
  274.  OpenDoc allows developers, large or small, to take a modular approach to 
  275.  development and maintenance. Its component-software architecture makes the 
  276.  design, development, testing, and marketing of integrated software packages 
  277.  far easier and more reliable. Developers can make incremental improvements to 
  278.  products without a complete revision cycle and can get those improvements to 
  279.  users far more rapidly than is possible today. 
  280.  
  281.  For developers, this is a radical shift in approach, although its 
  282.  implementation is not difficult. For users, this is only a minor shift in 
  283.  working style; its main effect is to remove the barriers to constructing and 
  284.  using complex documents imposed by conventional monolithic application 
  285.  architecture. 
  286.  
  287.  OpenDoc components allow users to assemble customized compound documents out 
  288.  of diverse types of data. They also support cross-platform sharing of 
  289.  information. They resolve user frustrations with conventional applications by 
  290.  removing the barriers listed earlier: 
  291.  
  292.      OpenDoc makes it easy for users to assemble any kind of content in any 
  293.       kind of document. OpenDoc documents will accept all kinds of media for 
  294.       which application components exist, now and in the future. 
  295.  
  296.      OpenDoc makes it easy for users to edit any kind of data, in-place, in 
  297.       any document. Users can readily transfer that data to any other document 
  298.       and edit it there just as easily. This lets users focus on document 
  299.       content and lets them take advantage of the context provided by the 
  300.       surrounding document. 
  301.  
  302.      OpenDoc allows businesses to customize their software solutions by 
  303.       assembling components into shrink-wrapped packages, thereby obtaining 
  304.       needed features, increasing reliability, and saving on training costs. 
  305.       In-house developers can then enhance the packages by developing 
  306.       components that integrate smoothly with the off-the-shelf software. Some 
  307.       developers bundle components together into packages that are similar to 
  308.       conventional monolithic applications; others sell individual components 
  309.       for specialized purposes, to users or to other developers for bundling. 
  310.       Users can purchase packages and use them as is, or they can modify a 
  311.       package by adding or replacing individual components. 
  312.  
  313.      OpenDoc lowers market barriers to wide, cross-platform distribution for 
  314.       small developers. Components can be ported easily to other 
  315.       OpenDoc-supported platforms. Small development teams can create 
  316.       individual components with the knowledge that they will integrate 
  317.       smoothly with existing packages created by larger developers. 
  318.  
  319.      OpenDoc promotes collaboration, allowing users simultaneously or 
  320.       separately to build documents as a team, on a single machine or across 
  321.       networks. Documents are not owned by single applications, and changes are 
  322.       recoverable through a draft history that is available for every document. 
  323.       Pervasive scripting support, rich data-transfer capabilities, and an 
  324.       extension mechanism allow users to manipulate their own and other 
  325.       documents in powerful ways. 
  326.  
  327.  While providing all of these advantages, OpenDoc exists harmoniously with 
  328.  existing monolithic applications; the user need not abandon conventional 
  329.  applications in order to start using OpenDoc. The following table summarizes 
  330.  some of the principal advantages of the OpenDoc approach to software for both 
  331.  users and developers. 
  332.  
  333.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  334.   Γöé             ΓöéFor UsersΓöéFor Software ΓöéFor Software ΓöéFor Small   Γöé
  335.   Γöé             Γöé         ΓöéEngineering  ΓöéMarketing    ΓöéDevelopment Γöé
  336.   Γöé             Γöé         Γöé             Γöé             ΓöéTeams       Γöé
  337.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  338.   ΓöéModularity   ΓöéCan      ΓöéCan easily   ΓöéCan assemble ΓöéCan create  Γöé
  339.   Γöé             Γöéeasily   Γöétest and     Γöépackages withΓöécomponents  Γöé
  340.   Γöé             Γöéadd or   Γöéupgrade      Γöégreat        Γöéthat work   Γöé
  341.   Γöé             Γöéreplace  Γöécomponents;  Γöéflexibility  Γöéseamlessly  Γöé
  342.   Γöé             Γöédocument Γöécan reuse    Γöé             Γöéwith all    Γöé
  343.   Γöé             Γöéparts    Γöécomponents   Γöé             Γöéothers      Γöé
  344.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  345.   ΓöéSmall size   ΓöéLess     ΓöéEasier to    ΓöéEasier,      ΓöéFaster      Γöé
  346.   Γöé             Γöémemory   Γöédesign, code,Γöécheaper      Γöédevelopment Γöé
  347.   Γöé             Γöéand disk Γöédebug, and   Γöédistribution Γöéand easier  Γöé
  348.   Γöé             Γöéspace    Γöétest         Γöé             ΓöédistributionΓöé
  349.   Γöé             Γöéneeded   Γöé             Γöé             Γöéof a        Γöé
  350.   Γöé             Γöé         Γöé             Γöé             Γöécomponent   Γöé
  351.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  352.   ΓöéMultiple     ΓöéDocumentsΓöéDevelopment  ΓöéOpportunitiesΓöéApplication Γöé
  353.   Γöéplatforms    Γöétravel   Γöéeffort on oneΓöéfor increasedΓöéof limited  Γöé
  354.   Γöé             Γöéacross   Γöéplatform can Γöémarket share Γöéresources   Γöé
  355.   Γöé             ΓöéplatformsΓöéat times be  Γöé             Γöécan at timesΓöé
  356.   Γöé             Γöéso users Γöéleveraged to Γöé             Γöébe used     Γöé
  357.   Γöé             Γöécan      Γöéothers       Γöé             Γöéacross      Γöé
  358.   Γöé             Γöéselect   Γöé             Γöé             Γöédifferent   Γöé
  359.   Γöé             Γöéfamiliar Γöé             Γöé             Γöéplatforms   Γöé
  360.   Γöé             Γöéeditors  Γöé             Γöé             Γöé            Γöé
  361.   Γöé             Γöéon each  Γöé             Γöé             Γöé            Γöé
  362.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  363.   ΓöéScriptabilityΓöéUsers    ΓöéIncreased    ΓöéBetter       ΓöéIncreased   Γöé
  364.   Γöéand          Γöéhave     Γöéability for  Γöécoordination Γöéability to  Γöé
  365.   ΓöéextensibilityΓöégreater  ΓöécommunicationΓöéamong        Γöécommunicate Γöé
  366.   Γöé             Γöécontrol  Γöéamong parts  Γöécomponents inΓöéwith other  Γöé
  367.   Γöé             Γöéover     Γöé             Γöéa package    Γöécomponents  Γöé
  368.   Γöé             Γöébehavior Γöé             Γöé             Γöé            Γöé
  369.   Γöé             Γöéof       Γöé             Γöé             Γöé            Γöé
  370.   Γöé             Γöédocument Γöé             Γöé             Γöé            Γöé
  371.   Γöé             Γöéparts    Γöé             Γöé             Γöé            Γöé
  372.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  373.  
  374.  
  375. ΓòÉΓòÉΓòÉ 3.2. Overview of OpenDoc ΓòÉΓòÉΓòÉ
  376.  
  377. OpenDoc is a set of DLLs designed to facilitate the easy construction of 
  378. compound, customizable, collaborative, and cross-platform documents. To do 
  379. this, OpenDoc replaces today's application-centered user model with a 
  380. document-centered one. The user focuses on constructing a document or 
  381. performing an individual task, rather than using any particular application. 
  382. The software that manipulates a document is hidden, and users feel that they 
  383. are manipulating the parts of the document without having to launch or switch 
  384. applications. 
  385.  
  386. This document-centered model does not mean that OpenDoc supports only those 
  387. kinds of data found in paper documents. An OpenDoc document can contain data as 
  388. diverse as navigable movies, sounds, animation, database information such as 
  389. networked calendars, as well as traditional spreadsheets, graphics, and text. 
  390. OpenDoc is an ideal architecture for multimedia documents. In OpenDoc, each new 
  391. kind of medium that is developed-video, sound, animation, simulation, and so 
  392. on- can be represented as part of any document. Thus an OpenDoc document is 
  393. automatically able to contain future kinds of media, even kinds not yet 
  394. envisioned, without any modification. 
  395.  
  396. Although OpenDoc lends itself directly to complex and sophisticated layout, its 
  397. usefulness is by no means restricted to page-layout kinds of applications or 
  398. even compound documents. The scripting and extension mechanisms allow for 
  399. communication among parts of a document for any imaginable purpose. Tools such 
  400. as spelling checkers can be created as components and can then access the 
  401. contents of any parts in a document that support them; database-access 
  402. components can feed information to any parts of a document; larger programs 
  403. such as high-end printing applications can use specialized components to 
  404. manipulate the data of all parts of a document for purposes such as proof 
  405. printing and color matching. 
  406.  
  407. The rest of this chapter summarizes the main features of OpenDoc for both users 
  408. and developers. The rest of this book explains in more detail how to develop 
  409. software that provides those features. 
  410.  
  411.  
  412. ΓòÉΓòÉΓòÉ 3.3. Parts ΓòÉΓòÉΓòÉ
  413.  
  414. OpenDoc uses a few simple ideas to create a structure that integrates a wide 
  415. range of capabilities. The basic elements are documents, their parts, their 
  416. frames, and the part-editor code that manipulates them. Those elements, 
  417. represented in a set of object-oriented class libraries, define a number of 
  418. object classes. The classes provide interoperability protocols that allow 
  419. independently developed software components to cooperate in producing a single 
  420. document for the end user. Through the class libraries, these cooperating 
  421. components share user-interface resources, negotiate over document layout on 
  422. screen and on printing devices, share storage containers, and create data links 
  423. to one another. 
  424.  
  425. This section describes part editors, parts and frames, and how parts are 
  426. categorized, drawn, and stored in documents. It also describes the two 
  427. different kinds of part editors and the capability to develop other kinds of 
  428. OpenDoc components as well. 
  429.  
  430.  
  431. ΓòÉΓòÉΓòÉ 3.3.1. Documents, Parts, and Embedding ΓòÉΓòÉΓòÉ
  432.  
  433. Documents, not applications, are at the center of OpenDoc. Individual documents 
  434. are not tied to individual applications. In creating OpenDoc documents, 
  435. software components called part editors replace the conventional monolithic 
  436. applications in common use today. Each part editor is responsible only for 
  437. manipulating data of one or more specific kinds in a document. 
  438.  
  439. The user does not directly launch or execute part editors, however. The user 
  440. works with document parts (or just parts), the pieces of a document that, when 
  441. executing, include both the document data and the part-editor code that 
  442. manipulates it. See the following figure. 
  443.  
  444. A part can exist as document on its own, or it can be embedded in other parts, 
  445. allowing the user to create documents of arbitrary complexity. 
  446.  
  447.  
  448. ΓòÉΓòÉΓòÉ 3.3.1.1. Parts and the User ΓòÉΓòÉΓòÉ
  449.  
  450. In general, a user can perform all the tasks of an application by manipulating 
  451. a part instead of separately launching or executing a part editor. For example, 
  452. a user can create and use a spreadsheet part that looks and acts just like a 
  453. spreadsheet created by a spreadsheet application. However, there are four main 
  454. differences between a document consisting of parts and a document created by a 
  455. conventional application: 
  456.  
  457.      An OpenDoc document is built and manipulated differently. OpenDoc users 
  458.       can assemble a document out of parts of any kind-using their graphics 
  459.       part editor of choice, for example, to embed illustrations within a word 
  460.       processor document. Developers can write or assemble such groups of part 
  461.       editors for sale as integrated packages, or users can purchase individual 
  462.       part editors separately. 
  463.  
  464.      New parts of any kind can be added to an OpenDoc document. The user can 
  465.       purchase additional part editors-for example, a charting utility to 
  466.       accompany a spreadsheet-and immediately use them, for example, to embed 
  467.       charts into existing documents. 
  468.  
  469.      In editing, copying, or pasting a part, the user need not be aware of the 
  470.       code that is executing. In fact, the user cannot directly launch a part 
  471.       editor at all. The user manipulates the part data itself, within the 
  472.       context of the document. (It is not necessary to open the part into a 
  473.       separate window for editing). The document containing that part is opened 
  474.       and closed independently of the part's part editor. 
  475.  
  476.      The user can replace part editors. If the editor for a specific kind of 
  477.       part in a document is not available, or if the user prefers to use a 
  478.       different part editor-for example, to replace one charting utility with 
  479.       another-the user can specify that the new editor be used with all parts 
  480.       created under the previous editor. This gives the user the freedom to 
  481.       work with all of the editors of a package or replace any of them with 
  482.       others that the user prefers. 
  483.  
  484.  
  485. ΓòÉΓòÉΓòÉ 3.3.1.2. Part Editors ΓòÉΓòÉΓòÉ
  486.  
  487. A part editor has fewer responsibilities than a conventional application. Each 
  488. part editor must: 
  489.  
  490.      Display its part, both on-screen and when printing. 
  491.  
  492.      Edit its part by changing the state of the part in response to events 
  493.       caused by user actions. 
  494.  
  495.      Store its part, both persistently and at run time. 
  496.  
  497.  At run time, a part is an object that encapsulates both the state and 
  498.  behavior. The part data provides the state information, and the part editor 
  499.  provides the behavior; when bound together, they form an editable object. As 
  500.  with any object, only the state is stored when the object is stored. Also, 
  501.  multiple instantiations of an object do not mean multiple copies of the editor 
  502.  code; one part editor in memory serves as the code portion for any number of 
  503.  separate parts that it edits. 
  504.  
  505.  OpenDoc dynamically links part editors to their parts at run time, choosing an 
  506.  editor based on the kinds of parts that the document contains. Dynamic linking 
  507.  is necessary for a smooth user experience, because any sort of part might 
  508.  appear in any document at any time. 
  509.  
  510.  
  511. ΓòÉΓòÉΓòÉ 3.3.1.3. Other Software Components ΓòÉΓòÉΓòÉ
  512.  
  513. A user can apply several kinds of OpenDoc components to compound documents. A 
  514. part editor, as noted earlier, is a full-featured application component; it 
  515. allows the creation, editing, and viewing of parts of a particular kind. Part 
  516. editors are the functional replacements for conventional applications; they 
  517. represent the developer's primary investment. Like applications, part editors 
  518. are sold or licensed and are legally protected from unauthorized copying and 
  519. distribution. 
  520.  
  521. Part Viewers are application components that can display a part of particular 
  522. kind but cannot be used to create or even edit such a part. To enhance the 
  523. portability of OpenDoc compound documents across machines and across platforms, 
  524. it is important that part viewers of all kinds be widely available. Developers 
  525. are expected to create and freely distribute part viewers without restriction 
  526. for all kinds of parts that they support. A part viewer is really just a part 
  527. editor with its editing and part-creation capability removed; the developer can 
  528. create both from the same code base. 
  529.  
  530. Wide availability of a part viewer encourages purchase and use of its 
  531. equivalent part editor, because users will know that other users will be able 
  532. to view parts created with that editor. (In some cases it is possible to view a 
  533. part even when neither its editor nor viewer is present. See the discussion of 
  534. translation in Part Data Types). 
  535.  
  536. The OpenDoc architecture also allows for the development of software components 
  537. that, unlike part editors and part viewers, are not directly involved in 
  538. creating or displaying document parts. Special components called services, for 
  539. example, provide software services to parts. Spell checking or database-access 
  540. tools, when developed as service components, can increase the capabilities of 
  541. part editors. Users could apply them to a single part, to all the parts of a 
  542. document, or even across separate documents. 
  543.  
  544. Version 1.0 of OpenDoc provides complete support for part editors and part 
  545. viewers. Future releases may explicitly support services and other types of 
  546. component software as well. 
  547.  
  548.  
  549. ΓòÉΓòÉΓòÉ 3.3.1.4. Frames and Embedding ΓòÉΓòÉΓòÉ
  550.  
  551. Parts in an OpenDoc document have a hierarchical arrangement with each other. 
  552. The logical structure of a document, which underlies its graphical 
  553. presentation, consists of the embedding relationships among its parts and their 
  554. frames. 
  555.  
  556. Parts are displayed in frames, bounded areas that display a part's contents. 
  557. Frames are commonly rectangular, but may be any shape. The display frame of one 
  558. part-the frame within which the part is viewed-can itself be embedded within 
  559. the content of another part. The following figure shows such a relationship: 
  560. the inner frame is an embedded frame of the outer part, the inner part is an 
  561. embedded part of the outer part, and the outer part is the containing part of 
  562. the inner part. 
  563.  
  564. An embedded part is logically contained in its containing part, just as its 
  565. frame is visually embedded in the containing part's frame. The containing part, 
  566. however, largely ignores the characteristics of its embedded parts. A 
  567. containing part treats its embedded frames as regular elements of its own 
  568. content; it can move, select, delete, or otherwise manipulate them, without 
  569. regard to what they display. The embedded part itself takes care of all drawing 
  570. and event handling within an embedded frame. 
  571.  
  572. Every document has a single part at its top level, the root part, in which all 
  573. other parts in the document are directly or indirectly embedded. The root part 
  574. controls the basic layout structure of the document (such as text or graphics) 
  575. and the document's overall printing behavior. The following figure shows an 
  576. example of the relationships of the root part and two embedded parts. 
  577.  
  578.      Part 1, a text part, is the root part. 
  579.      Part 2, a graphics part, is embedded in part 1. 
  580.      Part 3, another text part, is embedded in part 2. 
  581.  
  582.  Each embedded part is displayed within its frame, which is embedded at some 
  583.  location in the containing part's content. (See the figure in Activation and 
  584.  Selection for an explanation of the visual characteristics of the frame 
  585.  borders). The following figure shows an example of the relationships of the 
  586.  root part and two embedded frames. 
  587.  
  588.  Because it can now contain embedded frames displaying any kind of content, the 
  589.  document is not a monolithic block of data under the control of a single 
  590.  application, but is instead composed of many smaller blocks of content 
  591.  controlled by many smaller software components. In large part, OpenDoc exists 
  592.  to provide the protocols that keep the components from getting in each other's 
  593.  way at run time and to keep documents editable and uncorrupted. 
  594.  
  595.  All parts can be embedded in other parts, and every part must be able to 
  596.  function as the root part of a document. However, not all parts are required 
  597.  to be able to contain other parts; simple or specialized utility programs such 
  598.  as clocks or sound players might not have a reason to embed other parts. Such 
  599.  parts are called noncontainer parts; they can be embedded in any part, but 
  600.  they cannot embed other parts within themselves. Parts that can embed as well 
  601.  as be embedded are called container parts. It is somewhat simpler to write an 
  602.  editor for a noncontainer part than for a container part, although container 
  603.  parts provide a far more general and flexible user experience. Unless 
  604.  embedding makes absolutely no sense for your purposes, you should create part 
  605.  editors that support embedding. 
  606.  
  607.  Parts can have more than one frame 
  608.  A part embedded in a document is not restricted to appearing in a single 
  609.  frame. Parts can have multiple frames, displaying either duplicate views or 
  610.  different aspects of the same part. See Presentation for more information. 
  611.  
  612.  
  613. ΓòÉΓòÉΓòÉ 3.3.2. Part Data Types ΓòÉΓòÉΓòÉ
  614.  
  615. Fundamental to the idea of a compound document is that it can hold different 
  616. types of data. Each part editor can manipulate only its own kinds of data, 
  617. called its intrinsic content. For a simple drawing part, for example, the 
  618. elements of its intrinsic content might be bit maps. For a simple text part, 
  619. they might be characters, words, and paragraphs. No part editor is asked to 
  620. manipulate the content elements of any part whose data it does not understand. 
  621.  
  622. OpenDoc supports both specific and general classifications of data type, so 
  623. that it can associate parts with specific part editors as well as with general 
  624. classes of part editors when appropriate. 
  625.  
  626.  
  627. ΓòÉΓòÉΓòÉ 3.3.2.1. Part Kind ΓòÉΓòÉΓòÉ
  628.  
  629. Different parts in a document hold data of different purpose and different 
  630. format, understandable to different part editors. For meaningful drawing and 
  631. editing to occur, OpenDoc must be able to associate a part editor only with 
  632. data that the editor can properly manipulate. 
  633.  
  634. OpenDoc uses the concept of part kind, a typing scheme analogous to file type, 
  635. to determine which part editor is to be associated with a given part in a 
  636. document. Because OpenDoc documents are not associated with any single 
  637. application, a file type is insufficient in this case; each part within a 
  638. document needs its own "type", or in this case, part kind. 
  639.  
  640. Part kinds are specified as ISO strings, (null-terminated 7-bit ASCII strings), 
  641. although they are usually manipulated as tokens (short, regularized 
  642. representations of those strings) by OpenDoc and by part editors. A part kind 
  643. specifies the exact data format manipulated by an editor; it may have a name 
  644. similar to the editor name, such as "SurfDraw" or "SurfBase III", although 
  645. names more descriptive of the creator and the specific data format itself, such 
  646. as "SurfCorp:Movie:AVI", are preferable. (The user of such a part would see a 
  647. different but related string describing the part kind, which in this case might 
  648. be "SurfTime movie"). 
  649.  
  650. Part-editor developers define the part kinds of their own editors. A single 
  651. editor can manipulate more than one part kind, if it is designed to do so, and 
  652. a single part can be stored with multiple representations of its data, each of 
  653. a different part kind. All parts created by an editor initially have its part 
  654. kind (or kinds), although that can change; see Changing Part Editors. 
  655.  
  656.  
  657. ΓòÉΓòÉΓòÉ 3.3.2.2. Part Category ΓòÉΓòÉΓòÉ
  658.  
  659. The concept of part kind does not address the similarities among many data 
  660. formats. For example, data stored as plain ASCII or Unicode text could 
  661. conceivably be manipulated by any of a number of part editors. Likewise, video 
  662. data stored according to a standard might be manipulated by many different 
  663. video editors. Furthermore, text that closely resembles ASCII or Unicode, and 
  664. stored video that adheres in all but a few details to a particular standard, 
  665. might nevertheless be editable or displayable to some extent by many text 
  666. editors or video editors. 
  667.  
  668. It might be unduly confining to restrict the editing or display of a part of a 
  669. given kind to the exact part editor that actually created it. Unless the user 
  670. has every part editor that created a document, the user cannot edit or even 
  671. view all parts of it. Instead, OpenDoc facilitates the substitution of part 
  672. editors by defining part category, a general description of the kind of data 
  673. manipulated by a part editor. When users speak of a "text part" or a "graphics 
  674. part", they are using an informal designation of part category. 
  675.  
  676. Like part kinds, part categories are specified as ISO strings. Part categories 
  677. have broad designations, such as "plain text," "styled text," "bitmap", or 
  678. "database." Part-editor developers work with Component Integration Laboratories 
  679. (CI Labs), a consortium created to coordinate cross-platform OpenDoc 
  680. development, to define the list of part categories recognized by OpenDoc. See 
  681. Cross-Platform Consistency and CI Labs for more information on CI Labs. See the 
  682. table under Part Categories Supported by an Editor for a list of defined part 
  683. categories. 
  684.  
  685. Each part editor specifies the part categories that it can manipulate. For each 
  686. defined part category (such as "plain text") the user can then specify a 
  687. default editor (such as "SurfWriter 3.0") to use as a default with any part in 
  688. that category whose preferred editor-the part editor that created it or last 
  689. edited it-is missing. 
  690.  
  691.  
  692. ΓòÉΓòÉΓòÉ 3.3.2.3. Embedding Versus Incorporating ΓòÉΓòÉΓòÉ
  693.  
  694. When the user pastes data into a document, the pasted data can either be 
  695. incorporated into the intrinsic content of the destination part (the part 
  696. receiving the data), or it can become a separate embedded part. As the 
  697. following figure shows, the destination part, the part receiving the data, 
  698. decides whether to embed or incorporate the data. It bases the decision on how 
  699. closely the part kind and category of the pasted data match the part kind and 
  700. category of the destination content. 
  701.  
  702. This is how the decision is made: 
  703.  
  704.      If the part kinds of pasted data and destination match, the data should 
  705.       be incorporated; the SurfWriter text shown in the preceding figure, for 
  706.       example, is pasted into the intrinsic data of the SurfWriter (text) part. 
  707.  
  708.      If the part categories are different, the pasted data should be embedded; 
  709.       the SurfPaint bitmap shown in the preceding figure, for example, is 
  710.       embedded in the SurfWriter text part. 
  711.  
  712.      If the part categories are the same but the part kinds are different (a 
  713.       possibility not shown in the preceding figure), the destination part 
  714.       should, if possible, convert the data to its own kind and then 
  715.       incorporate it. Of course, if the destination part cannot read the part 
  716.       kind of the pasted data, it should embed it as a separate part. 
  717.  
  718.  In all of these cases, it is the destination part that decides whether to 
  719.  embed or to incorporate. The user can guide that decision by manually forcing 
  720.  a paste to be an incorporation or an embedding; see Handling the Paste As 
  721.  Dialog Box for more information. 
  722.  
  723.  Note:  For the data being pasted, part kind and part category refer to the 
  724.         kind and category of the outermost, or enclosing, data. There may be 
  725.         any number of parts embedded within that data, of various kinds and 
  726.         categories. Those parts are always transferred as embedded parts, 
  727.         regardless of whether the outermost data is itself incorporated or 
  728.         embedded. 
  729.  
  730.  
  731. ΓòÉΓòÉΓòÉ 3.3.2.4. Changing Part Editors ΓòÉΓòÉΓòÉ
  732.  
  733. When a part editor stores or retrieves the data of its part, it can only 
  734. manipulate it using the part kind or kinds that the editor understands and 
  735. prefers. Furthermore, different systems may have different sets of available 
  736. part editors. Therefore, the editor assigned to a part can change over the 
  737. part's lifetime. 
  738.  
  739. For example, the user might open a document (or paste data) containing a part 
  740. of a kind for which the user does not have the original part editor. In that 
  741. case, OpenDoc substitutes the user's default editor for that part kind or part 
  742. category (if the default editor can read any of the part's existing part 
  743. kinds). If the default editor cannot read the part, OpenDoc searches for an 
  744. editor that can. Once OpenDoc locates and assigns an editor to the part, the 
  745. new editor then becomes the part's preferred editor, and it subsequently stores 
  746. the part's data using its own part kinds. See Binding for more detailed 
  747. information on this process. 
  748.  
  749. Lack of a part editor never prevents a user from opening a document. If no 
  750. editor on the user's system can read any of the part kinds in a part, the part 
  751. contents remain unviewable and uneditable, and its preferred part editor and 
  752. part kinds do not change. Nevertheless, OpenDoc still displays a gray box 
  753. representing the part within the area of the part's frame, and the user may be 
  754. given the option of translating the data into an editable format, as described 
  755. next. 
  756.  
  757.  
  758. ΓòÉΓòÉΓòÉ 3.3.2.5. Translation ΓòÉΓòÉΓòÉ
  759.  
  760. Changing the part editor for a part often means changing data formats and 
  761. therefore may involve loss of information or may not be directly possible. For 
  762. example, any text editor might be able to display and edit plain ASCII text 
  763. without loss, but a sophisticated word processor may be able to read another 
  764. word processor's data only imperfectly, if at all. 
  765.  
  766. Nevertheless, the user can in some cases choose to employ a part editor with a 
  767. part that the editor cannot directly manipulate. In such a case, OpenDoc or a 
  768. part editor performs the necessary translation to convert the part into a 
  769. format usable by the editor. Translation is possible only if the appropriate 
  770. translator, or filter, is available on the user's machine to perform the 
  771. translation between part kinds. The fidelity, or quality, of the translation 
  772. depends on the sophistication of the translators. Translators are 
  773. platform-specific utilities that are independent of OpenDoc; OpenDoc simply 
  774. provides an object wrapper for a given platform's translation facilities. 
  775.  
  776. Note:  This function is not supported in the current release of OpenDoc. 
  777.  
  778.  OpenDoc provides support for translation when a document is first opened 
  779.  during data transfers such as drag and drop, through semantic events, and at 
  780.  any time the user chooses. 
  781.  
  782.  
  783. ΓòÉΓòÉΓòÉ 3.3.3. Displaying Parts ΓòÉΓòÉΓòÉ
  784.  
  785. In preparing a compound document for viewing, two issues are of prime 
  786. importance: managing the competition for space among the parts of the document 
  787. and making provisions for each part to draw itself. 
  788.  
  789. OpenDoc provides a platform-independent interface for part editors, although 
  790. the interface does not include any drawing commands or detailed graphics 
  791. structures. OpenDoc provides an environment for managing the geometric 
  792. relationships among frames, and it defines object wrappers for accessing 
  793. platform-specific graphic and imaging structures. 
  794.  
  795.  
  796. ΓòÉΓòÉΓòÉ 3.3.3.1. Drawing Structures ΓòÉΓòÉΓòÉ
  797.  
  798. Each part in an OpenDoc document is responsible for drawing its own content 
  799. only (including, at certain times, the borders of the frames embedded within 
  800. it). Thus, a part does not draw the interiors of its embedded frames because 
  801. they contain the content of other parts (which must draw themselves). 
  802.  
  803. Drawing a document is therefore a cooperative effort, for which no part editor 
  804. is completely responsible; each part editor is notified by OpenDoc when it must 
  805. draw its own part. 
  806.  
  807. Drawing in OpenDoc relies on three fundamental graphics-system-specific 
  808. structures for which OpenDoc provides wrapper objects: 
  809.  
  810.      Canvas, a description of a drawing environment. 
  811.  
  812.       A dynamic canvas, such as a screen display, can potentially be changed 
  813.       through scrolling or paging. 
  814.  
  815.       A static canvas, such as a printer page, cannot be changed once it has 
  816.       been rendered. OpenDoc allows for different behavior when drawing onto 
  817.       dynamic and static canvases. 
  818.  
  819.      Shape, a structure that describes a geometric shape. 
  820.  
  821.      Transform, a structure that describes an offset, plus possibly a scaling 
  822.       factor or other geometric transformation. 
  823.  
  824.  When a part actually draws itself within a frame, it uses an object closely 
  825.  related to the frame. A facet is an object that is the visible representation 
  826.  of a frame (or a portion of a frame) on a canvas. A frame typically has a 
  827.  single facet, but for offscreen buffering, split views of a part, or special 
  828.  graphics effects, it may have more than one. 
  829.  
  830.  In general, frames control the geometric relationships of the content that 
  831.  they display, whereas facets control the geometric relationships of frames to 
  832.  their containing frames or windows. The facet is associated with a specific 
  833.  drawing canvas, and both frames and facets have associated shapes and 
  834.  transforms. The following figure summarizes some of the basic relationships 
  835.  among frames, facets, shapes, transforms, and canvas in drawing; for more 
  836.  detail see Transforms and Shapes. 
  837.  
  838.  The left side of the preceding figure shows the content area of an embedded 
  839.  part as a page with text on it. The portion of the part that is available for 
  840.  drawing is the portion within the frame shape assigned to the part by its 
  841.  containing part. (A part may have more than one frame, but only one is shown 
  842.  here). The frame's internal transform positions the frame over the part 
  843.  content. (Another shape, the used shape, defines the portion of the frame 
  844.  shape that is actually drawn to; in this case, the used shape equals the frame 
  845.  shape). 
  846.  
  847.  The center of the preceding figure shows the facet associated with this 
  848.  embedded part's frame. (A frame may have more than one facet, but only one is 
  849.  shown here). The clip shape defines where drawing can occur in relation to the 
  850.  content of the containing part. In this case, the containing part is the root 
  851.  part in a document window, but it could be an embedded part displayed in its 
  852.  own frame. The clip shape is typically similar to the frame shape except that, 
  853.  as shown in the preceding figure, it might have additional clipping to account 
  854.  for other parts or for elements of the containing part that overlap it. The 
  855.  facet's external transform positions the facets within the containing part's 
  856.  frame and facet. (Another shape, the active shape, defines the portion of the 
  857.  area of the facet that the embedded part will respond to events within. in 
  858.  this case, the active shape equals the frame shape). 
  859.  
  860.  The right side of the preceding figure shows the result of drawing both parts 
  861.  on the window's canvas. The portion of the embedded part defined by the frame 
  862.  is drawn in the area defined by the facet. If this embedded part is the active 
  863.  part, meaning that the user can edit its contents, OpenDoc draws the active 
  864.  frame border around it; the shape of that border is based on the facet's 
  865.  active shape. 
  866.  
  867.  
  868. ΓòÉΓòÉΓòÉ 3.3.3.2. Presentation ΓòÉΓòÉΓòÉ
  869.  
  870. There are many ways that a part editor can draw the contents of a part. A word 
  871. processor can draw its data as plain text, styled text, or complete page 
  872. layouts; a spreadsheet can draw its data as text, tables, graphs, or charts; a 
  873. 3-D drawing program can draw its shapes as wire-mesh polyhedrons, filled 
  874. polyhedrons, or surface-rendered shapes with specified lighting parameters. 
  875.  
  876. For any kind of program, individual frames of a single part can display 
  877. different portions of different views of its data. For example, in a page 
  878. layout part, one frame of a page could display the header or footer, while 
  879. another could display the text of the page, and yet another could show the 
  880. outline of the document. For a 3-D graphics part, different frames could show 
  881. different views (top, front, side) of the same object. For any kind of program, 
  882. an auxiliary palette, tool bar, or other set of controls might be placed in a 
  883. separate frame and be considered an alternative "view" of the part to which it 
  884. applies. 
  885.  
  886. OpenDoc calls such different part-display aspects part presentations and 
  887. imposes no restrictions on them. The following figure shows some examples of 
  888. different presentations for individual parts in a document. There are only two 
  889. embedded parts, but each has several display frames, and each frame has a 
  890. different presentation. 
  891.  
  892. Your part editor determines the presentations that its parts can have, and it 
  893. stores a presentation designation (for your own drawing functions to make use 
  894. of) in each of your part's frames. You can store other display-related 
  895. information as the part info data of a frame. Each frame and each facet has the 
  896. capability to store part info data that you can access; in that data, you can 
  897. store any useful private information relating to the display of your part in 
  898. that frame or facet. Only you use the part info data of your frames and facets. 
  899.  
  900.  
  901. ΓòÉΓòÉΓòÉ 3.3.3.3. View Type ΓòÉΓòÉΓòÉ
  902.  
  903. OpenDoc does not specify presentation type, but it nevertheless defines some 
  904. aspects of part display. Each part has a view type, a designation of its 
  905. fundamental display form of the part in that frame. Basically, view type states 
  906. whether a part is to be displayed in icon form or with its contents visible. 
  907.  
  908. In most situations in most documents, each part displays its contents, or some 
  909. portion of its contents, within its frame. However, a part can also display 
  910. itself as one of several kinds of icons. See the following figure for examples. 
  911.  
  912. Each basic display form (standard icon, small icon, thumbnail icon, or framed) 
  913. is a separate view type. Your part editor stores a designation of the part's 
  914. view type in each of your part's display frames. A single part can, of course, 
  915. have different view types in different frames. 
  916.  
  917. On the desktop and in Workplace Shell folders, parts are individual closed 
  918. documents and by default have an icon view type. When such a document is 
  919. opened, the part gives its frame a frame view type, and its contents (including 
  920. embedded parts) then become visible. Nevertheless, open documents can have 
  921. embedded parts displayed as icons. Keep in mind that a part with an icon view 
  922. type is not necessarily closed or inactive. A sound part, for example, might 
  923. have nothing but an icon view type, even when playing its sound. 
  924.  
  925. Each containing part specifies, by setting a value in its embedded part's 
  926. frame, the view type it prefers the embedded part to have. Your container parts 
  927. can specify the view type for each embedded frame they create; when embedded, 
  928. your parts should initially display themselves in the view type expected by 
  929. their containing parts. See, for example, View Type for more information and 
  930. guidelines. 
  931.  
  932.  
  933. ΓòÉΓòÉΓòÉ 3.3.3.4. Document Windows and Part Windows ΓòÉΓòÉΓòÉ
  934.  
  935. Compound documents are displayed in windows. A document window is a window that 
  936. holds a single OpenDoc document; that document can contain a single part or 
  937. many parts. Document windows in OpenDoc are essentially the same as the windows 
  938. that display a conventional application's documents. 
  939.  
  940. An architectural cornerstone of OpenDoc is that it provides in-place editing of 
  941. all parts in a compound document. Users can manipulate the content of any part, 
  942. no matter how deeply embedded, directly within the frame that displays the 
  943. part. 
  944.  
  945. Nevertheless, a user might wish to view more of a part than is displayed within 
  946. a frame. Even if a frame is resizable and supports scrolling of its contents, 
  947. it might be more convenient to view that frame's part separately, in its own 
  948. window. OpenDoc supports this by allowing users to open a separate window, 
  949. called a part window, which looks similar to a document window. See the 
  950. following figure for an example. 
  951.  
  952. Like document windows, part windows can themselves contain embedded parts. But 
  953. because your part is the root part in any part windows that your part editor 
  954. creates, you may take a more active role in window handling than you do for 
  955. your part when it is an embedded part in a document window. See Creating and 
  956. Using Windows for information on handling part windows. 
  957.  
  958.  
  959. ΓòÉΓòÉΓòÉ 3.3.3.5. Frame Negotiation ΓòÉΓòÉΓòÉ
  960.  
  961. In a compound document with embedded parts, the embedding hierarchy and the 
  962. frame locations determine the geometric relationships among parts. Each part 
  963. controls the positions, sizes, and shapes of the frames embedded within it. If 
  964. an embedded part needs to change the size of its frame or add another frame, it 
  965. must negotiate for that change with its containing part. This frame negotiation 
  966. allows an embedded part to communicate its needs to its containing part; 
  967. however, the containing part has ultimate control over the embedded frames' 
  968. sizes and shapes. 
  969.  
  970. The following figure shows a simple example of frame negotiation. A user edits 
  971. an embedded part, adding enough data so that the content no longer fits in the 
  972. embedded part's current frame size. The embedded part requests a larger frame 
  973. from the containing part. The containing part can either grant the request or 
  974. return a different frame size from that requested. In this example, the 
  975. containing part cannot accommodate the full size of the requested frame and so 
  976. returns a frame size to the embedded part that is larger than the previous 
  977. frame but not as large as the requested one. 
  978.  
  979. The frame-negotiation process is described in more detail in Frame Negotiation. 
  980.  
  981.  
  982. ΓòÉΓòÉΓòÉ 3.4. Event Handling ΓòÉΓòÉΓòÉ
  983.  
  984. Most part editors interact with the user primarily by responding to user 
  985. events. User events are messages sent or posted by the operating system in 
  986. response to user actions, activation or deactivation of a part or window, or 
  987. messages from other event sources. Based on information in a user event, a part 
  988. editor might redraw its part, open or close windows, perform editing 
  989. operations, transfer data, or perform any sort of menu command or other 
  990. operation. 
  991.  
  992. OpenDoc has several built-in event-handling features that help your part editor 
  993. function properly within a compound document. For example, instead of polling 
  994. for events, as a typical application does, your part editor acts when notified 
  995. by OpenDoc that an event has occurred. 
  996.  
  997. This section notes some of OpenDoc's event-handling features; for more 
  998. information on user events, see User Events. 
  999.  
  1000.  
  1001. ΓòÉΓòÉΓòÉ 3.4.1. The Document Shell and the Dispatcher ΓòÉΓòÉΓòÉ
  1002.  
  1003. Part editors respond differently to user events than conventional applications 
  1004. do. Part editors do not receive events directly; OpenDoc receives them and 
  1005. dispatches them to the proper part. 
  1006.  
  1007. Because they are not complete applications, and because they must function 
  1008. cooperatively, part editors run in an environment that itself handles some of 
  1009. the tasks that conventional applications typically perform. That environment is 
  1010. called the OpenDoc document shell; it is an executable that handles certain 
  1011. application-level tasks and provides an address space for each OpenDoc document 
  1012. within which part editors manipulate document content. 
  1013.  
  1014. Whenever an OpenDoc document is opened, OpenDoc creates an instance of the 
  1015. document shell. The shell creates global objects and uses them to open the 
  1016. document. OpenDoc then loads the part editors for all parts that appear in the 
  1017. document window; the part editors read in the data of their own parts. The 
  1018. shell receives both user events and scripting-related events (see Scripting 
  1019. Support). The shell uses the OpenDoc dispatcher to dispatch those events to the 
  1020. proper part editors, based on event location and ownership of shared resources 
  1021. such as menus. 
  1022.  
  1023. The document shell is described in The Document Shell. How the dispatcher sends 
  1024. events to parts is described in How User Events Are Handled. 
  1025.  
  1026.  
  1027. ΓòÉΓòÉΓòÉ 3.4.2. Handling User Commands ΓòÉΓòÉΓòÉ
  1028.  
  1029. As a result of user actions or commands, OpenDoc interacts with part editors to 
  1030. perform these common application activities: 
  1031.  
  1032.      Part activation 
  1033.      Menu handling 
  1034.      Undo 
  1035.  
  1036.  In general, the document shell receives events and passes the appropriate 
  1037.  information to the proper part. 
  1038.  
  1039.  
  1040. ΓòÉΓòÉΓòÉ 3.4.2.1. Activation and Selection ΓòÉΓòÉΓòÉ
  1041.  
  1042. In response to user actions, individual parts in a document become active and 
  1043. thus editable. A part is active if it possesses the selection focus; the user 
  1044. can select and modify its contents in this state. The active part may also 
  1045. possess the menu and keystroke focus; see Focus Transfer for more information 
  1046. on foci. 
  1047.  
  1048. Parts activate themselves in OpenDoc, and the individual parts in a document 
  1049. must cooperate to transfer the selection focus among each other as appropriate. 
  1050. Note that when a part is not in the active (editable) state, it need not be 
  1051. idle; multiple parts within an OpenDoc document can perform different tasks at 
  1052. the same time. 
  1053.  
  1054. Switching among individual parts within a document can involve a much less 
  1055. intrusive context switch than switching from one conventional application to 
  1056. another. Users are less likely to be irritated, because the wait before they 
  1057. can edit a newly activated part is not all that perceptible. 
  1058.  
  1059. The active state is different from the selected state. When a part is selected, 
  1060. its frame is made available for manipulation. Because embedded frames are 
  1061. considered to be content elements of their containing part, they can be 
  1062. selected and then moved, adjusted, cut, or copied just like text, graphic 
  1063. objects, or any other content elements. Thus, whereas an active part is 
  1064. manipulated by its own part editor, a selected part is manipulated-as a 
  1065. frame-by its containing part. The following figure shows the visual differences 
  1066. among the inactive, selected, and active states of an embedded part. 
  1067.  
  1068. Note that an inactive part, one that is not being edited, need not have a 
  1069. visible frame border. A selected part's frame border is drawn by the containing 
  1070. part; its shape typically corresponds to the frame shape, and its appearance 
  1071. should follow guidelines for selected frames. An active part's frame border is 
  1072. drawn by OpenDoc; its shape corresponds to the active shape of the embedded 
  1073. part's facet, and its appearance is fixed for each platform. 
  1074.  
  1075. When a part activates, more than its own frame border changes. The following 
  1076. figure illustrates some of the visual changes to a window caused by part 
  1077. activation. 
  1078.  
  1079. In the figure, the text part is active first. OpenDoc has drawn the active 
  1080. frame border around its frame, it has a highlighted selection, and it displays 
  1081. its own menus. Then the text part becomes inactive and the graphics part 
  1082. becomes active. The text part removes its menus and its highlighting. The 
  1083. graphics part displays its own menus and also displays two palettes (in 
  1084. separate windows). OpenDoc now draws the active border around the graphics 
  1085. part's frame. 
  1086.  
  1087. Activation generally occurs in response to mouse clicks within the area of a 
  1088. frame (specifically, within the area of a facet's active shape). OpenDoc 
  1089. follows an inside-out activation model, in which a single mouse click causes 
  1090. activation of the smallest (actually, the most deeply embedded) enclosing frame 
  1091. at the pointer location. In the case of a deeply nested embedded frame, as 
  1092. shown in the following figure, a single click within the frame of the most 
  1093. deeply embedded part activates that part and allows the user to start editing 
  1094. immediately. 
  1095.  
  1096. By contrast, some compound-document architectures use an outside-in activation 
  1097. mode, in which the user selects the outermost (nonactive) frame with one click 
  1098. and activates it with the second click. Thus, many clicks might be necessary 
  1099. for the user to activate a deeply embedded part. In the preceding figure, for 
  1100. example, the user would have to click four times to start editing. 
  1101.  
  1102. Despite the advantages of inside-out activation, a containing part may at times 
  1103. not want an embedded part to be activated when the user clicks within its 
  1104. frame; it may instead want the part to become selected. For example, when you 
  1105. want the user to be able to move-but not edit-a part embedded within your part, 
  1106. you would rather have it selected than activated by a mouse click. OpenDoc 
  1107. allows you to specify this behavior for an embedded part by placing its frame 
  1108. in a bundled state. A bundled frame acts like a frame with outside-in 
  1109. selection, in that a single click selects the frame. (However, unlike with 
  1110. outside-in selection, subsequent clicks do not then activate the part; you have 
  1111. to unbundle it before it can be activated). 
  1112.  
  1113. Your part does not receive window-activation events directly. The OpenDoc 
  1114. dispatcher notifies your part when its window becomes active or inactive, as 
  1115. described in Handling Activate Events. It also notifies the containing part, 
  1116. rather than the embedded part, when an embedded part should become selected. 
  1117.  
  1118.  
  1119. ΓòÉΓòÉΓòÉ 3.4.2.2. Menus ΓòÉΓòÉΓòÉ
  1120.  
  1121. Menu organization and menu handling are different on different platforms. 
  1122. OpenDoc encapsulates certain aspects of menu behavior in a platform-neutral 
  1123. menu bar object. That object gives your part editor access to its own and to 
  1124. OpenDoc's menus. 
  1125.  
  1126. There are four menus that are available whenever an OpenDoc document is active. 
  1127. It is recommended that these menus remain unchanged by the part editor, with 
  1128. the exception of adding more choices. The part is free to put up as many other 
  1129. menus as desired by the developer. 
  1130.  
  1131. The four standard menus are: 
  1132.  
  1133.      The Document menu is basic to the OpenDoc user interface. It provides a 
  1134.       replacement for the application-oriented File or equivalent menus. The 
  1135.       contents of the Document menu reflect the OpenDoc document-centered 
  1136.       approach. For example, there is no Quit or Exit command. In OpenDoc, the 
  1137.       user closes a document rather than quits applications. 
  1138.  
  1139.       The Document menu contains choices that affect the top-level part shown 
  1140.       in the window. 
  1141.  
  1142.      The Edit menu is another standard OpenDoc menu that allows the user to 
  1143.       operate on your part or its contents when it is the active part. 
  1144.  
  1145.       This menu contains standard choices on selected parts or selected 
  1146.       intrinsic data. For example, there are options to create a new part of 
  1147.       the same type as the selected part and to undo and redo user actions. 
  1148.  
  1149.      The View menu contains choices that affect the view of the active part. 
  1150.       It also controls the display of related windows, such as tool bars or 
  1151.       palettes. All container parts should support the Icon, Tree, and Details 
  1152.       views. 
  1153.  
  1154.      The Help menu contains choices that provide help on the active part. 
  1155.  
  1156.  In addition to the menu bar, each part has a pop-up menu just like other 
  1157.  objects in the WorkPlace Shell. The only difference between the pop-up menu 
  1158.  and choices in the menu bar menu is that in pop-up menus unavailable choices 
  1159.  are not shown. In menu bar menus, unavailable choices are grayed. 
  1160.  
  1161.  More information on the individual menus is in Menus. 
  1162.  
  1163.  Most of the items in the Document menu are handled by the document shell; see 
  1164.  Handling the Document Menu and Document Menu for more information. 
  1165.  
  1166.  Your part editor can add menus of its own, and it can modify-within strict 
  1167.  limits and according to certain rules-the standard OpenDoc menus. 
  1168.  
  1169.  
  1170. ΓòÉΓòÉΓòÉ 3.4.2.3. Undo ΓòÉΓòÉΓòÉ
  1171.  
  1172. Applications on many platforms provide a form of undo, a capability that allows 
  1173. a user to reverse the effects of a recently executed command. OpenDoc provides 
  1174. better support for undo than do most current platforms, in at least two ways: 
  1175.  
  1176.      The undo action can cross document boundaries. This is important because 
  1177.       a single drag-and-drop action can affect more than one part or document. 
  1178.  
  1179.      OpenDoc allows multiple sequential undo actions. The user can undo 
  1180.       multiple sequential commands, rather than only one. 
  1181.  
  1182.  OpenDoc support for undo is described in more detail in Implementing Undo. 
  1183.  
  1184.  
  1185. ΓòÉΓòÉΓòÉ 3.5. Storage and Data Transfer ΓòÉΓòÉΓòÉ
  1186.  
  1187. All the data of all parts in a document, plus all information about frames and 
  1188. embedding, is stored in a single document file. OpenDoc does not require the 
  1189. user to manually manage the various file formats that make up a compound 
  1190. document; OpenDoc manages and holds all the pieces. This makes storage easier 
  1191. for developers and exchanging documents easier for users. 
  1192.  
  1193. OpenDoc uses the same data-storage concepts for data transfer (clipboard, drag 
  1194. and drop, and linking) that it uses for document storage. 
  1195.  
  1196.  
  1197. ΓòÉΓòÉΓòÉ 3.5.1. Storage Basics ΓòÉΓòÉΓòÉ
  1198.  
  1199. The OpenDoc storage system manages persistent storage for parts. It is a 
  1200. high-level persistent storage mechanism that enables multiple part editors to 
  1201. share a single document file effectively. The storage system is implemented on 
  1202. top of the native storage facilities for each platform that supports OpenDoc. 
  1203.  
  1204. Storage in OpenDoc is based on a system of structured elements, each of which 
  1205. can contain one or more data streams. The data of each part in a document is 
  1206. kept in at least one storage unit, distinct from the data of other parts. 
  1207. Storage units can also include references to other storage units, and OpenDoc 
  1208. uses chains of such references to store the embedding relationships of the 
  1209. parts within a document. 
  1210.  
  1211. Storage units and other elements of structured storage of OpenDoc are described 
  1212. further in Storage. 
  1213.  
  1214.  
  1215. ΓòÉΓòÉΓòÉ 3.5.2. Document Drafts ΓòÉΓòÉΓòÉ
  1216.  
  1217. OpenDoc documents have a history that can be preserved and inspected through 
  1218. the mechanism of drafts. A draft is a captured record of the state of a 
  1219. document at a given time; the user decides when to save the current state of a 
  1220. document as a new draft and when to delete older drafts. All drafts are stored 
  1221. together in the same document, with no redundantly stored data. 
  1222.  
  1223. The OpenDoc draft mechanism helps in the creation of shared documents. When 
  1224. several users share a document, each in turn can save the current state of the 
  1225. document as a draft and then make any desired changes. Users can always look 
  1226. back through the drafts of the document they and others have created. Also, if 
  1227. translation occurs during the process of sharing documents, the user can 
  1228. consult an older draft to regain access to formatting information that might 
  1229. have been lost in translation. The following figure shows an example of a 
  1230. dialog box through which the user can manipulate drafts. 
  1231.  
  1232. Parts also interact with their drafts to create the objects needed for 
  1233. embedding other parts and to create links to data sources. See Drafts for more 
  1234. information. 
  1235.  
  1236.  
  1237. ΓòÉΓòÉΓòÉ 3.5.3. Templates ΓòÉΓòÉΓòÉ
  1238.  
  1239. OpenDoc gives the user additional aids for constructing compound documents. One 
  1240. aid, central to the user's ability to create new kinds of parts, is templates. 
  1241.  
  1242. Templates are specialized parts or documents used in creating other parts. A 
  1243. template is never opened; when the user attempts to open a template, a copy of 
  1244. that part is created and opened instead. Users can create templates with 
  1245. specific formatting and content, to create letterhead, forms, or types of 
  1246. documents. Template parts can be embedded in documents, or they can exist as 
  1247. stand-alone documents themselves. 
  1248.  
  1249. The following figure shows an icon for a template document on the desktop. The 
  1250. user drags the template icon and drops it onto the document, at which time a 
  1251. copy of the template part is embedded in the document and opened into a frame, 
  1252. displaying the part's initial contents. 
  1253.  
  1254. It is typically through templates that users first gain access to your part 
  1255. editor. When you develop and ship a part editor, you can also provide one or 
  1256. more template documents. Part registration creates a default template as well. 
  1257. To create a part using your part editor, the user does not launch the editor; 
  1258. instead, the user double-clicks on your template document or drags it into an 
  1259. open document window. 
  1260.  
  1261.  
  1262. ΓòÉΓòÉΓòÉ 3.5.4. Data Transfer ΓòÉΓòÉΓòÉ
  1263.  
  1264. OpenDoc includes several built-in data-transfer features that allow users to 
  1265. create and edit OpenDoc documents more easily than is usual with conventional 
  1266. applications. Users can put any kind of media into a document with simple 
  1267. commands, and OpenDoc helps your part editor respond to those commands. 
  1268.  
  1269. In OpenDoc data transfer, the source is the part (or the portion of its 
  1270. content) that provides the data being transferred, and the destination is the 
  1271. part (or the location in its content) that receives the transferred data. 
  1272.  
  1273. When source data in one format is transferred to a destination whose data is 
  1274. written in another format, translation may be necessary; see Translation. 
  1275. Translation usually involves loss of data, and is less necessary if part 
  1276. editors provide standard content formats, as promoted by CI Labs; see 
  1277. Cross-Platform Consistency and CI Labs. 
  1278.  
  1279.  
  1280. ΓòÉΓòÉΓòÉ 3.5.4.1. Clipboard ΓòÉΓòÉΓòÉ
  1281.  
  1282. Clipboard data transfer allows for easy exchange of information among 
  1283. documents, using menu commands familiar to most users. OpenDoc supports 
  1284. clipboard transfer of any kind of data, including multipart compound data, into 
  1285. any document. 
  1286.  
  1287. Clipboard transfer is a two-stage process. The user first selects some portion 
  1288. of the content of the source part (possibly including embedded parts) and 
  1289. places a copy of that content onto the clipboard buffer by executing the Cut or 
  1290. Copy command. At any subsequent time, the user can copy the clipboard data to 
  1291. the destination (back into the same part, into another part in the same 
  1292. document, or into another document) by executing the Paste command. 
  1293.  
  1294. As noted in Embedding Versus Incorporating, OpenDoc allows for an intelligent 
  1295. form of pasting in data transfer, anticipating user expectations about the 
  1296. result of a pasting operation when the destination holds a different kind of 
  1297. data from the source. Subject to user override, the destination part can decide 
  1298. whether to embed the data as a separate part, or incorporate it as content data 
  1299. into itself. 
  1300.  
  1301. Clipboard transfer is discussed in detail in Handling Pasted or Dropped Data. 
  1302.  
  1303.  
  1304. ΓòÉΓòÉΓòÉ 3.5.4.2. Drag and Drop ΓòÉΓòÉΓòÉ
  1305.  
  1306. Drag-and-drop data transfer is similar to Clipboard transfer, except that it 
  1307. involves direct user manipulation of the data being transferred, rather than 
  1308. the intermediate use of the Clipboard. OpenDoc supports drag and drop within 
  1309. documents, across documents, and to the desktop. Users can even drop 
  1310. non-OpenDoc data into OpenDoc parts. 
  1311.  
  1312. The following figure shows the use of drag and drop to transfer a piece of 
  1313. information from a spreadsheet part to a text part within a document. As with 
  1314. Clipboard transfer, OpenDoc uses intelligent pasting in drag and drop; the 
  1315. spreadsheet part includes a plain-text version of the selection being dragged, 
  1316. so that the destination part (the text part) can directly incorporate it at the 
  1317. location of the drop. 
  1318.  
  1319. Drag and drop works equally well between separate documents. As far as user 
  1320. experience is concerned, the data-transfer facilities of OpenDoc actually blur 
  1321. the distinction between a part and a document. If the user drags a closed 
  1322. document (represented as an icon on the desktop) into an open document window, 
  1323. a copy of the transferred document either becomes an embedded part in the 
  1324. window's document or is incorporated into the intrinsic content of the 
  1325. document's root part. Likewise, if the user selects the frame of an embedded 
  1326. part in an open document window and drags or otherwise moves that part to the 
  1327. desktop, it immediately becomes a separate, closed document represented by icon 
  1328. as shown in the following figure. 
  1329.  
  1330. Drag and drop is discussed in detail in Drag and Drop. 
  1331.  
  1332.  
  1333. ΓòÉΓòÉΓòÉ 3.5.4.3. Linking ΓòÉΓòÉΓòÉ
  1334.  
  1335. Linking allows the user to view, within a part's frame, data that is a live 
  1336. (updatable) copy of data in a different location-in the same frame, in a 
  1337. different frame, in a different part, or even in a different document. When the 
  1338. data in the source location changes, OpenDoc updates the copy at the 
  1339. destination, either automatically or manually, depending on user preference. 
  1340.  
  1341. Linked data can include embedded parts, and the source of a link can be in the 
  1342. same part as its destination, in a different part in the same document, or in 
  1343. an entirely different document. The following figure shows a simple example of 
  1344. linking between two parts in a document. In this example, whenever the user 
  1345. changes the values in the linked spreadsheet cells, the bar graph adjusts its 
  1346. display accordingly. 
  1347.  
  1348. Users create a link when pasting data, either by selecting Paste Link or Paste 
  1349. As. The Paste As dialog box is used to link the source of the data to its 
  1350. destination. (See The figure in Handling the Paste As Dialog Box for an example 
  1351. of the dialog box). This simple user interface to linking makes the use of 
  1352. links more attractive to users than some other systems do. 
  1353.  
  1354. Linking is discussed in detail in Linking. 
  1355.  
  1356.  
  1357. ΓòÉΓòÉΓòÉ 3.6. Extensibility ΓòÉΓòÉΓòÉ
  1358.  
  1359. The OpenDoc architecture is designed to be extended. Using built-in features, 
  1360. you can enhance the capabilities of and communications among your parts in a 
  1361. compound document, and you can even develop component software that goes well 
  1362. beyond the standard OpenDoc model of parts and compound documents. 
  1363.  
  1364. The main point of departure for enhancing OpenDoc is the extension mechanism, a 
  1365. general method for adding programming interfaces to objects. Additional 
  1366. mechanisms are the focus-module and dispatch-module interfaces, which allow you 
  1367. to add new kinds of focus and new kinds of event handling to your part editors. 
  1368.  
  1369. OpenDoc already includes three instances of extensions:  scripting support, the 
  1370. settings extension, and the view extension. This section introduces the 
  1371. features of these extensions and summarizes how you can add other extensions 
  1372. for other purposes. 
  1373.  
  1374.  
  1375. ΓòÉΓòÉΓòÉ 3.6.1. Scripting Support ΓòÉΓòÉΓòÉ
  1376.  
  1377. A major feature available with OpenDoc is the ability to make parts scriptable, 
  1378. allowing users to customize their applications to user-specific tasks. In a 
  1379. compound document environment, with scriptable parts, sophisticated users can 
  1380. use standard document-editing procedures to add application-like functionality 
  1381. to parts. Likewise, programmers can create complex client applications and 
  1382. present them in the form of compound documents. 
  1383.  
  1384. The scripting supported by OpenDoc is called content centered scripting or 
  1385. scripting based on a content model, which lists the content objects and 
  1386. operations that the part makes available for scripting. For a part to be 
  1387. scriptable, its part editor must have a content model. OpenDoc provides a way 
  1388. to deliver scripting messages, or semantic events, from a scripting system to a 
  1389. part editor, which responds to events. Object REXX is a scripting language 
  1390. based on Open Scripting Architecture. 
  1391.  
  1392. Your part editor can provide increasing levels of scripting support, including 
  1393. scriptability, recordability, and customizability. They are described in 
  1394. Semantic Events and Scripting. 
  1395.  
  1396. When a scripting action involves data transfer, OpenDoc can decide whether to 
  1397. embed the transferred data as a separate part or translate it and incorporate 
  1398. it as content data into the destination part. Translation and embedding versus 
  1399. incorporation are described in Translation. 
  1400.  
  1401. Scripts can be attached to parts, and a user-interface control such as a button 
  1402. might consist of nothing more than a part that executes a script when 
  1403. activated. Script editors also can send semantic events to parts. The following 
  1404. figure shows an example of a script editor sending a semantic event based on a 
  1405. scripting command ("Set chartType of part "sales chart" to type3D pie") to a 
  1406. document. The document shell decodes the object specifier in the event (part 
  1407. 'Sales Chart') and determines the content object that it applies to (in this 
  1408. case an embedded part; the embedded part then performs the specified operation. 
  1409.  
  1410. The scripting support in OpenDoc is an enhancement of OpenDoc's basic 
  1411. capabilities. It is recommended, but not required, that a part editor support 
  1412. scripting. 
  1413.  
  1414.  
  1415. ΓòÉΓòÉΓòÉ 3.6.2. Settings Extension ΓòÉΓòÉΓòÉ
  1416.  
  1417. The settings extension allows a part to display its properties and settings in 
  1418. a standard OS/2 notebook. OpenDoc provides Property pages that are added to the 
  1419. notebook by the part. 
  1420.  
  1421.  
  1422. ΓòÉΓòÉΓòÉ 3.6.3. View Extension ΓòÉΓòÉΓòÉ
  1423.  
  1424. The view extension allows a part to communicate with the Details view of its 
  1425. container part and supply information for additional data columns in the view 
  1426. container. 
  1427.  
  1428.  
  1429. ΓòÉΓòÉΓòÉ 3.6.4. Other Extensions ΓòÉΓòÉΓòÉ
  1430.  
  1431. The basic architecture of OpenDoc is primarily concerned with mediating the 
  1432. geometric interrelationships among parts, their sharing of user events, and 
  1433. their sharing of storage. Direct communication among parts for purposes other 
  1434. than frame negotiation is mostly beyond the basic intent of OpenDoc. If 
  1435. separate parts in a document (or across documents) need to share information, 
  1436. or if one part needs to manipulate the contents or behavior of another part, 
  1437. some extension to the capabilities of OpenDoc is needed. 
  1438.  
  1439. OpenDoc allows you to add these kinds of capabilities to part editors through 
  1440. its extension mechanism. A part editor can create an associated extension 
  1441. object that implements an additional interface to that editor's parts. Other 
  1442. part editors can then access and call that interface. 
  1443.  
  1444. The OpenDoc support for scripting is an example of an extension interface, as 
  1445. noted in the previous section. Other extension interfaces can, however, provide 
  1446. faster interaction and lower-level communication between parts than is possible 
  1447. by passing semantic events. A word processor, for example, might construct an 
  1448. extension interface to give related part editors or other tools access to its 
  1449. text. A developer of a large application package might use extensions to 
  1450. provide greater integration among its components. 
  1451.  
  1452. The following figure shows some possible examples of communication through 
  1453. OpenDoc extensions. It shows a text part and a graphics part that both 
  1454. communicate with a tool palette (a third part), so that the palette displays 
  1455. the appropriate tools for the currently active part, and communicates the 
  1456. user's tool selection back to the active part. A spelling checker provides its 
  1457. service to all parts in the document and accesses their text through their 
  1458. extensions. Furthermore, the text part and graphic part communicate directly 
  1459. through an extension mechanism; the text part updates the graphic part with the 
  1460. current figure number and caption it has assigned to the figure. 
  1461.  
  1462. In addition to the scripting extension, OpenDoc includes existing extensions 
  1463. and other kinds of enhancements that allow you to extend the OpenDoc Properties 
  1464. notebook, extend the capabilities of the OpenDoc document shell, or provide for 
  1465. additional kinds of user events or foci. Use of the OpenDoc extension mechanism 
  1466. is discussed further in Extending OpenDoc. 
  1467.  
  1468.  
  1469. ΓòÉΓòÉΓòÉ 3.7. Cross-Platform Consistency and CI Labs ΓòÉΓòÉΓòÉ
  1470.  
  1471. OpenDoc was designed from the beginning to be a cross-platform architecture. 
  1472. The programming interface to OpenDoc is general enough that it is readily 
  1473. implemented on many platforms, adapting well to different user-interface 
  1474. designs and different run-time models. Although OpenDoc does not provide a 
  1475. complete programming interface-it does not, for example, replace the graphics 
  1476. system or drawing commands for any platform-it provides consistent structure 
  1477. within which such system-specific interfaces can be used. As a result, users on 
  1478. all platforms obtain a uniform experience in embedding and manipulating all 
  1479. kinds of media. 
  1480.  
  1481. Part of this uniformity is built into OpenDoc, and part comes from additional 
  1482. platform-independent user-interface guidelines that part-editor developers must 
  1483. follow. Because platform-neutral user-interface guidelines and programming 
  1484. standards are so important, and because data integrity and data-transfer 
  1485. protocols are so critical in cross-platform settings, OpenDoc is affiliated 
  1486. with an organization devoted to solving these issues in a vendor-independent 
  1487. fashion. 
  1488.  
  1489. Component Integration Laboratories, Inc. (CI Labs) is a nonprofit association 
  1490. dedicated to promoting the adoption of OpenDoc as a vendor-neutral industry 
  1491. standard for software integration and component software. CI Labs is composed 
  1492. of a number of platform and application vendors with a common interest in 
  1493. solving OpenDoc issues and promoting interoperability. 
  1494.  
  1495. Organizations and individuals who want to participate in the move to a 
  1496. component-software model are invited to join CI Labs. CI Labs supports several 
  1497. levels of participation through different membership categories. Specific 
  1498. membership benefits vary by category, but all members influence the future 
  1499. direction of OpenDoc technology. 
  1500.  
  1501. We encourage you to add your name to one of our electronic mail information 
  1502. lists at CILABS.ORG, download files from our server at FTP.CILABS.ORG, or look 
  1503. up our Web page (http://www.cilabs.org). If for some reason you are unable to 
  1504. get files from our server, we can send you an information packet. For details 
  1505. on membership levels and how you can become a member, please provide the 
  1506. following information: 
  1507.  
  1508.       Name 
  1509.       Company Name 
  1510.       Title 
  1511.       Street Address 
  1512.       City 
  1513.       State/Province 
  1514.       Zip Code/Postal Code/Country 
  1515.       Telephone Number 
  1516.       Fax Number 
  1517.       e-mail address 
  1518.  
  1519.  You can send it through CILABS@CILABS.ORG or use our US mail address: 
  1520.  
  1521.       Component Integration Laboratories, Inc. 
  1522.       PO Box 61747 
  1523.       Sunnyvale, CA 94088-1747 
  1524.  
  1525.  Telephone         (408) 864-0300 
  1526.  FAX               (408) 864-0380 
  1527.  Internet          CILABS@CILABS.ORG 
  1528.  World Wide Web    http://www.cilabs.org 
  1529.  
  1530.  CI Labs is responsible for the development and maintenance of a number of 
  1531.  component software packages, including the following: 
  1532.  
  1533.      OpenDoc, the platform-independent class library and compound document 
  1534.       architecture that is described in this book. 
  1535.  
  1536.      Bento, a class library and format for persistent object storage. Bento 
  1537.       allows OpenDoc to store and exchange compound documents and multimedia. 
  1538.  
  1539.      Open Scripting Architecture (OSA), a scripting and program-automation 
  1540.       standard and interface that supports application-independent user 
  1541.       scripting on multiple platforms. OSA is not a scripting language; it is a 
  1542.       messaging specification and library upon which scripting languages are 
  1543.       built. 
  1544.  
  1545.      System Object Model (SOM), an efficient and powerful mechanism and set of 
  1546.       libraries for dynamic linking of objects. SOM underlies OpenDoc's dynamic 
  1547.       linking capability, and its language-neutral interface compiler permits 
  1548.       development in multiple languages, object-oriented as well as procedural, 
  1549.       even within a single software component. 
  1550.  
  1551.      Component Glue, an interface and library that enables seamless 
  1552.       interoperability between OpenDoc and Microsoft Corporation's Object 
  1553.       Linking and Embedding (OLE) technology for interapplication 
  1554.       communication. 
  1555.  
  1556.  CI Labs oversees the development and distribution of these technologies. In 
  1557.  the future, CI Labs also expects to coordinate the following activities for 
  1558.  developers of OpenDoc part editors: 
  1559.  
  1560.      Certification of part editors for consistency with OpenDoc standards and 
  1561.       for safe use in any OpenDoc document 
  1562.  
  1563.      Promotion of standard formats for exporting different kinds of document 
  1564.       content 
  1565.  
  1566.      Coordination of standards for extending the capabilities of OpenDoc, by 
  1567.       defining specific sets of OpenDoc extension interfaces 
  1568.  
  1569.  
  1570. ΓòÉΓòÉΓòÉ 4. Development Overview ΓòÉΓòÉΓòÉ
  1571.  
  1572. Creating OpenDoc software is not difficult, but it represents a shift in 
  1573. approach from conventional application development. OpenDoc part editors differ 
  1574. from conventional applications in that: 
  1575.  
  1576.      They are generally smaller than conventional applications. 
  1577.      They do not have direct access to some operating-system services such as 
  1578.       event dispatching. 
  1579.      They do not own their own documents. 
  1580.      They must work in close cooperation with other part editors. 
  1581.  
  1582.  The cross-platform design of OpenDoc means that some aspects of part 
  1583.  development may seem foreign to developers, but it also means that writing 
  1584.  part editors for multiple platforms is far easier than doing so for 
  1585.  conventional applications. 
  1586.  
  1587.  OpenDoc is an object-oriented system, but a part editor can be written in 
  1588.  procedural code and still fit into the OpenDoc class structure. Existing 
  1589.  applications, object-oriented or not, can be retrofitted easily to work in the 
  1590.  OpenDoc environment. OpenDoc is extensible, and many of its components are 
  1591.  replaceable, allowing for innovation by developers at both the system and 
  1592.  application levels. 
  1593.  
  1594.  This chapter introduces the OpenDoc class library, and presents a high-level 
  1595.  summary of several approaches to developing an OpenDoc part editor. For 
  1596.  additional discussions of general development-related issues, see also OpenDoc 
  1597.  Run-Time Features. 
  1598.  
  1599.  
  1600. ΓòÉΓòÉΓòÉ 4.1. The OpenDoc Class Library ΓòÉΓòÉΓòÉ
  1601.  
  1602. OpenDoc is a set of DLLs with a largely platform-independent, object-oriented 
  1603. programming interface. This section introduces the classes implemented in the 
  1604. OpenDoc libraries and the design goals behind them. 
  1605.  
  1606. The interfaces to all of OpenDoc's classes are specified in the Interface 
  1607. Definition Language (IDL), a programming-language-neutral syntax for creating 
  1608. interfaces. The interfaces are compiled separately from implementation code 
  1609. using the compiler for the System Object Model (SOM), a specification for 
  1610. object binding at runtime. See Developing with SOM and IDL for more 
  1611. information. 
  1612.  
  1613. Because OpenDoc uses IDL and SOM, part editors and other OpenDoc objects that 
  1614. have been created with different compilers or in completely different 
  1615. programming languages can nevertheless communicate properly with each other. 
  1616. Furthermore, they can be independently revised and extended and still work 
  1617. together. 
  1618.  
  1619. For more complete information on the OpenDoc class library, including detailed 
  1620. descriptions of all public OpenDoc classes and methods, see the OpenDoc for 
  1621. OS/2 Programming Reference. 
  1622.  
  1623.  
  1624. ΓòÉΓòÉΓòÉ 4.1.1. A Set of Classes, Not a Framework ΓòÉΓòÉΓòÉ
  1625.  
  1626. OpenDoc is a set of classes whose objects cooperate in the creation and 
  1627. manipulation of compound documents. It is designed to be as platform-neutral as 
  1628. possible. The object-oriented library structure, in which object fields are 
  1629. private, facilitates the replacement of existing code in a modular manner. 
  1630. Also, by using abstract classes and pure virtual methods, it defines a 
  1631. structure for part editors while specifying as little as possible about their 
  1632. internal functioning. 
  1633.  
  1634. The OpenDoc class library is not an object-oriented application framework in 
  1635. the full sense of the word. That is, even though the design of OpenDoc allows 
  1636. you to create a part editor, it does so at a lower level, and without forcing 
  1637. as much adherence to interface and implementation as is typical for an 
  1638. application framework. 
  1639.  
  1640. You can create a part editor just as effectively in either way: directly to the 
  1641. OpenDoc library interfaces or indirectly through the interfaces of a framework. 
  1642. The main difference is that if you use a part-editor framework, you have less 
  1643. code to actually implement yourself, and it is easier to ensure consistency in 
  1644. the final product. 
  1645.  
  1646. The principal classes in the OpenDoc class hierarchy are shown in the following 
  1647. figure. All classes are derived from the superclass ODObject, itself a subclass 
  1648. of somObject, the fundamental SOM superclass (not shown). Classes whose names 
  1649. are in bold are abstract superclasses that your part editor is likely to 
  1650. subclass. The other principal classes implement the basic capabilities of 
  1651. OpenDoc; classes typically instantiated by your part (if it uses them) are in 
  1652. italics, and classes instantiated only by OpenDoc are in plain text. 
  1653.  
  1654. Runtime relationships 
  1655. For an illustrated discussion of the relationships of the principal OpenDoc 
  1656. objects in terms of runtime references among them, see Run-Time Object 
  1657. Relationships. 
  1658.  
  1659. Classes shown in the following figure are support classes, consisting mostly of 
  1660. iterators and simple sets. They are all direct subclasses of ODObject. (A 
  1661. separate set of specialized OpenDoc support classes, used solely for scripting, 
  1662. is shown in the figure in Scripting-Related Objects). 
  1663.  
  1664. Compared to some application frameworks, there is little inheritance in the 
  1665. hierarchy represented in the preceding figures; OpenDoc instead makes extensive 
  1666. use of object delegation, in which objects unrelated by inheritance cooperate 
  1667. to perform a task. This inheritance structure preserves the language-neutral 
  1668. flavor of OpenDoc and improves ease of maintenance and replaceability. 
  1669.  
  1670. The OpenDoc classes can be divided into these three groups, based on how a part 
  1671. editor might make use of them: 
  1672.  
  1673.      The class (ODPart) that you must subclass and implement to create your 
  1674.       part editor 
  1675.      The bulk of the implemented OpenDoc classes, instantiated either by your 
  1676.       part editor or by OpenDoc, that your part editor calls to perform its 
  1677.       tasks 
  1678.      The classes you can subclass and implement to extend OpenDoc 
  1679.  
  1680.  The following sections summarize these groups of classes. 
  1681.  
  1682.  
  1683. ΓòÉΓòÉΓòÉ 4.1.2. Classes you Must Subclass ΓòÉΓòÉΓòÉ
  1684.  
  1685. The OpenDoc classes listed in this section are abstract superclasses that you 
  1686. are intended to subclass if you wish to implement their capabilities. 
  1687.  
  1688.  
  1689. ΓòÉΓòÉΓòÉ 4.1.2.1. The Class ODPart ΓòÉΓòÉΓòÉ
  1690.  
  1691. The class ODPart is central to OpenDoc; it is the one class that you must 
  1692. subclass to create a part editor. ODPart represents the programming interface 
  1693. that your part editor presents to OpenDoc and to other parts. 
  1694.  
  1695. ODPart is an abstract superclass with approximately 65 defined methods. When 
  1696. you subclass ODPart, you must override all methods, but you need to provide 
  1697. meaningful implementations only for those methods that represent capabilities 
  1698. actually supported by your part editor. The rest can be stub implementations. 
  1699.  
  1700. There is one additional class that you must subclass and implement if your part 
  1701. is a container part. You must provide an iterator class (a subclass of the 
  1702. abstract superclass ODEmbeddedFramesIterator) to allow callers to access all of 
  1703. the frames directly embedded in your part. 
  1704.  
  1705.  
  1706. ΓòÉΓòÉΓòÉ 4.1.3. Classes for Extending OpenDoc ΓòÉΓòÉΓòÉ
  1707.  
  1708. OpenDoc provides these classes specifically for enhancing its features: 
  1709.  
  1710.      The class ODExtension is the abstract superclass from which extensions to 
  1711.       OpenDoc are defined; OpenDoc allows you to add new methods to existing 
  1712.       classes by associating objects of class ODExtension with the specific 
  1713.       class that they extend. The classes ODSemanticInterface and 
  1714.       ODSettingsExtension are examples of currently existing subclasses of 
  1715.       ODExtension. 
  1716.  
  1717.      The class ODSemanticInterface, when subclassed, represents the interface 
  1718.       through which a part receives semantic events, thus allowing it to be 
  1719.       scriptable. 
  1720.  
  1721.      The class ODSettingsExtension, when subclassed, represents an object with 
  1722.       which your part editor can create and display a Settings dialog box for 
  1723.       your part editor. 
  1724.  
  1725.      The class ODViewExtension, when subclassed, represents the interface 
  1726.       through which a part can add columns to a details view. 
  1727.  
  1728.      The class ODDispatchModule is used to dispatch certain types of events 
  1729.       (such as keystroke events) to part editors. You can provide for 
  1730.       dispatching of new types of events or messages to your part editor by 
  1731.       subclassing ODDispatchModule. 
  1732.  
  1733.      The class ODFocusModule is used to describe a particular type of focus 
  1734.       (such as the selection focus). You can provide new types of focus for 
  1735.       your part editor by subclassing ODFocusModule. 
  1736.  
  1737.      The class ODTransform represents a graphical transformation matrix used 
  1738.       for drawing. It is somewhat different from the other classes in this 
  1739.       category, in that it can be used as-is (which is why it also appears in 
  1740.       the next section) and it can also be subclassed to extend the kinds of 
  1741.       transformations it is capable of. 
  1742.  
  1743.  
  1744. ΓòÉΓòÉΓòÉ 4.1.4. Classes you Can Use ΓòÉΓòÉΓòÉ
  1745.  
  1746. The OpenDoc classes listed in this section implement most of the OpenDoc 
  1747. features that your part editor uses. By using or instantiating objects of these 
  1748. classes, your part can function within an OpenDoc document and can embed other 
  1749. parts. 
  1750.  
  1751.  
  1752. ΓòÉΓòÉΓòÉ 4.1.4.1. Abstract Superclasses ΓòÉΓòÉΓòÉ
  1753.  
  1754. These classes are never directly instantiated. The classes ODPart and 
  1755. ODEmbeddedFramesIterator, mentioned in the previous section, are abstract 
  1756. superclasses. Other abstract superclasses are mentioned in Classes for 
  1757. Extending OpenDoc. 
  1758.  
  1759. The abstract superclasses in the following list are special; they define the 
  1760. basic inheritance architecture of OpenDoc. Not only would you not instantiate 
  1761. these classes, but you would probably never directly subclass them; in 
  1762. developing a part editor, you would use (or further subclass) one of their 
  1763. existing subclasses. 
  1764.  
  1765.      ODObject. This is the abstract superclass for most of the principal 
  1766.       OpenDoc classes. All subclasses of ODObject define objects that are 
  1767.       extensible. 
  1768.  
  1769.      ODRefCntObject. This is the abstract superclass for reference-counted 
  1770.       objects-objects that maintain a count of how many other objects refer to 
  1771.       them so that OpenDoc can manage memory use efficiently. 
  1772.  
  1773.      ODPersistentObject. This is the abstract superclass for persistent 
  1774.       objects-objects whose state can be stored persistently. 
  1775.  
  1776.  
  1777. ΓòÉΓòÉΓòÉ 4.1.4.2. Implemented Classes ΓòÉΓòÉΓòÉ
  1778.  
  1779. These classes are implemented in ways unique to each platform that supports 
  1780. OpenDoc. Some are instantiated only by OpenDoc, whereas others may also be 
  1781. instantiated by your part editor. 
  1782.  
  1783.      The session object. The class ODSession represents the user opening and 
  1784.       accessing a single OpenDoc document. 
  1785.  
  1786.       There is only one ODSession object. Part editors and other OpenDoc 
  1787.       objects cache a reference to the single ODSession object for performance 
  1788.       reasons. The OpenDoc run time calls ODSession to instantiate all of the 
  1789.       OpenDoc library objects (such as ODDispatcher, ODWindowState, and 
  1790.       ODArbitrator) and initialize them. ODSession also keeps internal 
  1791.       references to these OpenDoc objects, so it is a handy thing to use to 
  1792.       access other objects. 
  1793.  
  1794.      The binding object. The class ODBinding represents the object that 
  1795.       performs the binding of part editors to the parts in a document. 
  1796.  
  1797.      Storage classes. The primary classes of objects associated with document 
  1798.       storage are the class ODStorageSystem and the set of classes 
  1799.       (ODContainer, ODDocument, ODDraft, and ODStorageUnit) that constitute a 
  1800.       container suite. The container-suite objects all work closely together 
  1801.       and are implemented differently for each platform or file system. 
  1802.  
  1803.      Data-interchange classes. The classes ODLink, ODLinkSource, ODLinkSpec, 
  1804.       ODDragAndDrop, and ODClipboard all relate to transfer of data from one 
  1805.       location to another. These objects do not represent documents, but they 
  1806.       nevertheless use storage units to hold the data they transfer. 
  1807.  
  1808.      Drawing-related classes. The classes ODCanvas, ODShape, and ODTransform 
  1809.       represent imaging structures in a given graphics system. The classes 
  1810.       ODWindowState and ODWindow represent windows on a given platform. The 
  1811.       classes ODFrame and ODFacet represent the frame and facet structures that 
  1812.       define the layout of embedded parts. 
  1813.  
  1814.      Event-handling classes. The classes ODArbitrator and ODDispatcher control 
  1815.       what kinds of user events are sent to which part editors during 
  1816.       execution. The classes ODMenuBar, ODPopupMenu, ODHelp, ODStatusLine, and 
  1817.       ODUndo give part editors access to the user interface. 
  1818.  
  1819.      Semantic-event classes. Besides the abstract class ODSemanticInterface, 
  1820.       the classes ODNameResolver and ODMessageInterface are associated with 
  1821.       sending or receiving semantic events (scripting messages), and connecting 
  1822.       to a scripting system. The first figure in A Set of Classes, Not a 
  1823.       Framework does not show the entire object hierarchy involved with 
  1824.       semantic events and scripting; see the first figure in A Set of Classes, 
  1825.       Not a Framework for a more complete picture. 
  1826.  
  1827.  
  1828. ΓòÉΓòÉΓòÉ 4.1.4.3. Service Classes ΓòÉΓòÉΓòÉ
  1829.  
  1830. These classes exist mainly as services for other classes to use: 
  1831.  
  1832.      The ODStorageUnitCursor and ODStorageUnitView classes facilitate access 
  1833.       to specific values in specific storage units. 
  1834.  
  1835.      The ODFocusSet class provides convenient grouping of foci (access to 
  1836.       shared resources such as the keyboard or menu bar) for activation and 
  1837.       event handling. 
  1838.  
  1839.      The ODNameSpaceManager and ODNameSpace classes provide convenient storage 
  1840.       for attribute/value pairs. The classes ODObjectNameSpace and 
  1841.       ODValueNameSpace, subclasses of ODNameSpace, provide, respectively, name 
  1842.       spaces for OpenDoc objects and for data. 
  1843.  
  1844.      The ODTranslation class provides platform-specific translation between 
  1845.       data formats. 
  1846.  
  1847.      The object descriptor classes (shown in the figure in Scripting-Related 
  1848.       Objects) provide scripting support in the form of an object-oriented 
  1849.       encapsulation of OSA event descriptor structures. 
  1850.  
  1851.      Many classes have associated iterator classes and list classes that are 
  1852.       used for counting through all related instances of the class. 
  1853.  
  1854.  
  1855. ΓòÉΓòÉΓòÉ 4.2. Writing OpenDoc Software ΓòÉΓòÉΓòÉ
  1856.  
  1857. This section briefly summarizes some high-level aspects of the design and 
  1858. implementation of a part editor. It discusses: 
  1859.  
  1860.      Issues related to developing with the System Object Model that underlies 
  1861.       all OpenDoc classes 
  1862.  
  1863.      Protocols that your part can participate in to accomplish its tasks 
  1864.  
  1865.      Several development scenarios for creating OpenDoc software 
  1866.  
  1867.  
  1868. ΓòÉΓòÉΓòÉ 4.2.1. Developing with SOM and IDL ΓòÉΓòÉΓòÉ
  1869.  
  1870. OpenDoc is implemented as a shared library consisting of a set of SOM classes. 
  1871. The interfaces to SOM classes must be written in the SOM Interface Description 
  1872. Language (IDL) and compiled by the SOM compiler, separately from the 
  1873. implementations of the classes. 
  1874.  
  1875. The implementation of OpenDoc objects as SOM objects has several advantages to 
  1876. its use as a shared library: 
  1877.  
  1878.      SOM objects are dynamically bound. Dynamic binding is essential to the 
  1879.       nature of OpenDoc, in which new parts can be added to existing documents 
  1880.       at any time. 
  1881.  
  1882.      All SOM objects, whether their implementations were compiled under 
  1883.       different compilers in the same programming language or in different 
  1884.       languages, communicate consistently and pass parameters consistently. 
  1885.  
  1886.      Unlike with other object-oriented architectures, the modification and 
  1887.       recompilation of a SOM class do not necessarily require the subsequent 
  1888.       recompilation of all of its subclasses and clients. 
  1889.  
  1890.  Because OpenDoc consists of SOM classes, the class ODPart is naturally a SOM 
  1891.  class. If you want your part editor, which is a subclass of ODPart plus any 
  1892.  other classes that you define, to also consist of SOM classes, then you must 
  1893.  write your interfaces in IDL, separate from your implementations, and you must 
  1894.  compile them with the SOM compiler. The result of the compilation is a set of 
  1895.  header and stub implementation source files, in one of the procedural or 
  1896.  object-oriented programming languages supported by the SOM compiler. You 
  1897.  complete your development by writing your implementations into the stub 
  1898.  implementation files and compiling them, along with the headers, using a 
  1899.  standard compiler for your programming language. 
  1900.  
  1901.  If you write your part-editor interfaces in IDL, you will notice that the IDL 
  1902.  syntax is very similar to that of C and C++. It includes essentially the same 
  1903.  character set, white space rules, comment styles, preprocessing capabilities, 
  1904.  identifier-naming rules, and rules for literals. But there are a few notable 
  1905.  differences in source-code appearance when declaring or calling methods of 
  1906.  SOM-based objects: 
  1907.  
  1908.      In IDL method declarations (function definitions), each parameter 
  1909.       declaration is preceded by a directional attribute ("in", "out", or 
  1910.       "inout") that notes whether the parameter is used as an input, or as a 
  1911.       result, or as both. (For example, void FacetAdded (in ODFacet facet);) 
  1912.  
  1913.      The C++ interface to any method of a SOM object includes an extra initial 
  1914.       parameter, the environment parameter (ev), used by all SOM methods to 
  1915.       pass exceptions. See SOM Exception Handling for more information. 
  1916.  
  1917.      The C interface to any SOM method includes another extra parameter, 
  1918.       before the environment parameter, specifying the object to which the 
  1919.       method call is directed. 
  1920.  
  1921.  Advantages of making all your classes SOM classes include a greater ability to 
  1922.  develop portions of your part editor (or set of editors) using different 
  1923.  programming languages and compilers, and a lesser need for recompilation of 
  1924.  all of your code when you change portions of it. These advantages may not be 
  1925.  compelling, however, unless your libraries are very large, especially since 
  1926.  the advantages must be balanced against the disadvantages of working in both 
  1927.  IDL and a separate programming language. 
  1928.  
  1929.  You are not required to make your part-editor classes SOM classes. If you are 
  1930.  developing in C++, for example, you can use C++ classes instead. The generally 
  1931.  preferred procedure is to create only one SOM class, a subclass of ODPart 
  1932.  whose interface contains nothing but your public methods (overrides of the 
  1933.  methods of ODPart and its superclasses). That SOM class delegates all of its 
  1934.  method calls to a C++ wrapper class, which contains the functionality for the 
  1935.  public methods as well as any private fields and methods. Additional classes 
  1936.  can be subclasses of your C++ wrapper class. 
  1937.  
  1938.  Advantages of developing in C++ with a single wrapper object include a lesser 
  1939.  need to work with interfaces in two languages (IDL and C++), a smaller memory 
  1940.  and calling overhead for your objects, and the availability of C++ features 
  1941.  (such as templates) that are not supported by SOM. 
  1942.  
  1943.  
  1944. ΓòÉΓòÉΓòÉ 4.2.1.1. SOM Class ID and Editor ID ΓòÉΓòÉΓòÉ
  1945.  
  1946. A SOM class ID is an ISO string whose format is "module::className". A part 
  1947. editor's editor ID is a SOM class ID that uniquely defines the editor; you need 
  1948. to specify your editor ID in your editor's IDL interfaces. For example, the 
  1949. editor ID for AcmeGraph 1.0 might be "Acme::AcmeGraph". Editor IDs are used for 
  1950. binding; see Information Used for Binding for more information. 
  1951.  
  1952. For a more detailed description of the Interface Definition Language and 
  1953. instructions on programming with SOM, see, for example, the SOMObjects 
  1954. Developer Toolkit Users Guide and SOMObjects Developer Toolkit Programmers 
  1955. Reference Manual. 
  1956.  
  1957.  
  1958. ΓòÉΓòÉΓòÉ 4.2.1.2. Direct-To-Som (DTS) ΓòÉΓòÉΓòÉ
  1959.  
  1960. SOM defines bindings for C and C++ languages. These bindings consist of a 
  1961. number of macros plus structure or class definitions in header files with the 
  1962. extensions .h and .ih (for C) and .xh and .xih (for C++). They are generated 
  1963. for a particular SOM class by running the SOM compiler on the .idl file for 
  1964. that class interface. The bindings can be used with a wide range of C and C++ 
  1965. compilers and do not require special compiler support. 
  1966.  
  1967. Direct-To-SOM (DTS) is a new and much more flexible way of using SOM in a C++ 
  1968. program. DTS class definitions resemble regular C++ classes, and you can either 
  1969. write them directly or use the SOM compiler to generate them into .hh files 
  1970. from existing IDL. DTS C++ class definitions can only be used with C++ 
  1971. compilers, such as VisualAge C++, that support DTS. 
  1972.  
  1973. DTS provides the same access to SOM functionality that the C++ bindings do but, 
  1974. in addition, DTS supports far more of the C++ language. DTS supports: 
  1975.  
  1976.      Member operators 
  1977.      Conversion functions 
  1978.      User-defined new and delete operators 
  1979.      Function overloading 
  1980.      Stack local SOM objects 
  1981.      First-class source debugging support for SOM classes 
  1982.  
  1983.  You can write and subclass your DTS classes directly and may never need to 
  1984.  write any IDL. 
  1985.  
  1986.  For more information about DTS, refer to your compiler programming guide. 
  1987.  
  1988.  
  1989. ΓòÉΓòÉΓòÉ 4.2.2. OpenDoc Protocols ΓòÉΓòÉΓòÉ
  1990.  
  1991. OpenDoc imposes very few restrictions on how your part editor does its job. The 
  1992. inner workings of your editor's core data engine are of little concern to 
  1993. OpenDoc. The engine should be able to free storage when requested, it should 
  1994. adequately handle cases where the part can be only partially read into memory, 
  1995. and it should handle any multiprocessing or multithreading issues that arise. 
  1996. Other than that, it simply needs to provide an interface to OpenDoc and use the 
  1997. OpenDoc interface to accomplish OpenDoc-related tasks. 
  1998.  
  1999. The programming interfaces that your part editor uses (and provides) to perform 
  2000. specific tasks are called protocols. The methods of ODPart, for example, 
  2001. participate in approximately 12 protocols, such as part activation and undo. 
  2002. This section briefly describes the protocols; and the next table lists the 
  2003. methods of ODPart that you will have to override to participate in each 
  2004. protocol. 
  2005.  
  2006.  
  2007. ΓòÉΓòÉΓòÉ 4.2.2.1. Which Protocols To Participate In ΓòÉΓòÉΓòÉ
  2008.  
  2009. To implement the simplest possible part, you need to participate in only some 
  2010. OpenDoc protocols, and you need to override only some methods of ODPart. As a 
  2011. minimum, your part editor must be able to: 
  2012.  
  2013.      Draw its part 
  2014.      Retrieve its part's data 
  2015.      Handle events sent to its part 
  2016.  
  2017.  Unless it creates extremely simple parts, your part editor must also provide 
  2018.  some sort of command interface to the user. It must then be able to 
  2019.  
  2020.      Activate its part 
  2021.      Handle menus, pop-ups, status lines, and help 
  2022.      Handle windows, dialog boxes, and palettes 
  2023.  
  2024.  If you wish your parts to be able to contain other parts, your part editor 
  2025.  must be able to 
  2026.  
  2027.      Embed frames and manipulate them 
  2028.      Create facets for visible frames 
  2029.      Store frames 
  2030.  
  2031.  Beyond these capabilities, you may want your parts to have additional 
  2032.  capabilities, such as drawing themselves asynchronously, supporting data 
  2033.  transfer such as drag and drop, supporting scripting, or others. You can add 
  2034.  those capabilities by overriding other methods of ODPart. 
  2035.  
  2036.  
  2037. ΓòÉΓòÉΓòÉ 4.2.2.2. Overriding the Methods of ODPart ΓòÉΓòÉΓòÉ
  2038.  
  2039. Your fundamental programming task in creating an OpenDoc part editor is to 
  2040. subclass the class ODPart and override its methods. The following list 
  2041. summarizes the OpenDoc protocols that your part editor can use, and lists the 
  2042. sections in this book that describe each protocol more fully. To create 
  2043. full-featured container parts, your editor must support all of these protocols. 
  2044.  
  2045. The methods of ODPart involved in each protocol are shown in the table that 
  2046. follows this list. 
  2047.  
  2048.      Layout. The layout and imaging protocols together make up the drawing 
  2049.       process. Your part uses the layout protocol for frame manipulation and 
  2050.       for facet manipulation. 
  2051.  
  2052.         -  Frame manipulation includes adding and removing display frames, 
  2053.            setting frame characteristics and order, opening frames into 
  2054.            windows, and performing frame negotiation (modifying embedded-frame 
  2055.            shapes on request). Your part interacts with its containing part and 
  2056.            with its draft object to modify your display frames. 
  2057.  
  2058.         -  Facet manipulation is the adding, altering, or removing of facets of 
  2059.            frames that are modified or scrolled into or out of view. You 
  2060.            interact with existing facet objects to add or manipulate embedded 
  2061.            facets. OpenDoc uses the facet hierarchy constructed by the layout 
  2062.            protocol for passing geometric events like mouse clicks to the 
  2063.            appropriate part editor. 
  2064.  
  2065.       All parts that are visible must participate in this protocol. The layout 
  2066.       protocol is described, along with the embedding protocol, in Frame and 
  2067.       Facet Hierarchies. 
  2068.  
  2069.      Imaging. Your part uses the imaging protocol after the layout protocol, 
  2070.       to draw itself appropriately in each of its display frames. Drawing may 
  2071.       occur asynchronously, or in response to update events, or when activation 
  2072.       or deactivation affects highlighting. Drawing can be to a video display 
  2073.       or to a printer. You interact with frames, facets, canvases, transforms, 
  2074.       and shapes during the imaging process. 
  2075.  
  2076.       All parts that are visible must participate in this protocol. The imaging 
  2077.       protocol is described in Canvases, Transforms and Shapes, Drawing, and 
  2078.       Printing. 
  2079.  
  2080.      Activation. Through this protocol your part activates and deactivates 
  2081.       itself (and its frames and facets). Your part interacts with the 
  2082.       arbitrator to change the menu and keystroke focus, and to notify the 
  2083.       parts and frames involved of the changes. 
  2084.  
  2085.       Your part must participate in this protocol if it ever needs to be active 
  2086.       or if it needs any of the other focus types. The activation protocol is 
  2087.       described in Focus Transfer. 
  2088.  
  2089.      User events. OpenDoc uses this protocol to distribute events such as 
  2090.       keystrokes and mouse clicks to the appropriate part editors. The document 
  2091.       shell, the arbitrator, and the dispatcher cooperate to deliver these 
  2092.       events to your part. 
  2093.  
  2094.       Your part must participate in this protocol if it handles events. The 
  2095.       user-events protocol is introduced in About Event Handling in OpenDoc and 
  2096.       is described in more detail in other parts of User Events. 
  2097.  
  2098.      Storage. Your part uses the storage protocol to write its content and its 
  2099.       state information persistently in its document, and subsequently to 
  2100.       retrieve it from the document. You interact with your draft object and 
  2101.       your part's storage unit when reading and writing your part, and you may 
  2102.       also interact with other drafts and storage units when using the 
  2103.       clipboard, drag-and-drop, and linking protocols. 
  2104.  
  2105.       All parts must participate in this protocol. The part-storage protocol is 
  2106.       described in Storage Units, Properties, and Values and Documents, Drafts, 
  2107.       and Parts. 
  2108.  
  2109.      Binding. The OpenDoc document shell controls the runtime binding of your 
  2110.       part editor to the parts in a document that it can edit. Your part's 
  2111.       methods are not called during binding. The binding protocol is discussed 
  2112.       in Binding. 
  2113.  
  2114.      Embedding. Your part uses this protocol to embed other parts within 
  2115.       itself and to interact with those parts. 
  2116.  
  2117.       Your part participates in this protocol if it is a container part-that 
  2118.       is, if it is capable of embedding parts within itself. The embedding 
  2119.       protocol is described in Frame and Facet Hierarchies. 
  2120.  
  2121.      Clipboard. The clipboard protocol allows the user to use menu commands to 
  2122.       move content elements and embedded parts into or out of your part, from 
  2123.       or to a system-maintained buffer. Your part interacts with the clipboard 
  2124.       object both when copying to the clipboard and when pasting from it. 
  2125.  
  2126.       Your part must participate in this protocol if it supports clipboard 
  2127.       transfer. The clipboard protocol is described in Clipboard Transfer. 
  2128.  
  2129.      Drag and drop. The drag-and-drop protocol allows the use of direct 
  2130.       manipulation to move content elements and embedded parts into or out of 
  2131.       your part or within your part. Your part interacts with the drag-and-drop 
  2132.       object. 
  2133.  
  2134.       Your part must participate in this protocol if it supports drag and drop. 
  2135.       The drag-and-drop protocol is described in Drag and Drop. 
  2136.  
  2137.      Linking. Your part can use the linking protocol to export updatable data 
  2138.       to another part or to incorporate or embed an updatable copy of another 
  2139.       part's data into your part. If your part is the source of a link, you 
  2140.       interact with a link-source object; if your part is the destination of a 
  2141.       link, you interact with a link object. 
  2142.  
  2143.       Your part must participate in this protocol if it supports linking. The 
  2144.       linking protocol is described in Linking. 
  2145.  
  2146.      Undo. Your part uses this protocol to give the user the capability of 
  2147.       reversing the effects of recently executed commands. Your part interacts 
  2148.       with the undo object to accomplish this. 
  2149.  
  2150.       Your part must participate in this protocol if it has an undo capability. 
  2151.       The undo protocol is described in Undo. 
  2152.  
  2153.      Extensions. The extension protocol is a very general mechanism for 
  2154.       extending your part's capabilities; it consists of an interface in the 
  2155.       form of a specialized extension object that other part editors can 
  2156.       access. 
  2157.  
  2158.       Your part participates in this protocol if it provides OpenDoc 
  2159.       extensions. The extensions protocol is described in OpenDoc Extension 
  2160.       Interface. 
  2161.  
  2162.      Semantic events. Your part uses the semantic events protocol to make 
  2163.       itself scriptable. It interacts with the semantic interface object when 
  2164.       receiving scripting messages (semantic events); it interacts with the 
  2165.       message interface object when sending scripting messages. 
  2166.  
  2167.       Your part must participate in this protocol if it is scriptable. The 
  2168.       semantic events protocol is described in Scripting and OpenDoc. 
  2169.  
  2170.      Memory management. The OpenDoc document shell manages the memory needed 
  2171.       for the document containing your part. 
  2172.  
  2173.       In general, your part editor does not need to be concerned with memory 
  2174.       management except to make sure that it deletes or releases objects that 
  2175.       it has created or obtained. The memory-management protocol and the use of 
  2176.       reference counting is further discussed in Creating and Releasing 
  2177.       Objects. 
  2178.  
  2179.  the table in OpenDoc Protocols lists the methods of ODPart that you must 
  2180.  override to have a functioning part editor, as well as those that you can 
  2181.  optionally override to participate in specific protocols. Note that some 
  2182.  protocols, such as layout, imaging, and activation, are required of all part 
  2183.  editors, and you therefore must override some or all of the methods associated 
  2184.  with them. Other protocols, such as embedding or undo, are not required, and 
  2185.  you therefore need not override any of their methods if your parts do not 
  2186.  participate. It is, of course, strongly recommended that your parts 
  2187.  participate in all protocols. 
  2188.  
  2189.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2190.   ΓöéProtocol       ΓöéRequired overrides                 ΓöéOptional overrides                 Γöé
  2191.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2192.   ΓöéLayout         ΓöéAttachSourceFrame                  ΓöéAcquireContainingPartProperties*   Γöé
  2193.   Γöé               ΓöéContainingPartPropertiesUpdated    ΓöéRevealFrame*                       Γöé
  2194.   Γöé               ΓöéDisplayFrameAdded                  Γöé                                   Γöé
  2195.   Γöé               ΓöéDisplayFrameClosed                 Γöé                                   Γöé
  2196.   Γöé               ΓöéDisplayFrameConnected              Γöé                                   Γöé
  2197.   Γöé               ΓöéDisplayFrameRemoved FacetAdded     Γöé                                   Γöé
  2198.   Γöé               ΓöéFacetRemoved FrameShapeChanged     Γöé                                   Γöé
  2199.   Γöé               ΓöéGeometryChanged Open               Γöé                                   Γöé
  2200.   Γöé               ΓöéSequenceChanged                    Γöé                                   Γöé
  2201.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2202.   ΓöéImaging        ΓöéCanvasChanged Draw                 ΓöéAdjustBorderShape* CanvasUpdated*  Γöé
  2203.   Γöé               ΓöéGetPrintResolution HighlightChangedΓöé                                   Γöé
  2204.   Γöé               ΓöéPresentationChanged ViewTypeChangedΓöé                                   Γöé
  2205.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2206.   ΓöéActivation     ΓöéAbortRelinquishFocus               Γöé                                   Γöé
  2207.   Γöé               ΓöéBeginRelinquishFocus               Γöé                                   Γöé
  2208.   Γöé               ΓöéCommitRelinquishFocus FocusAcquiredΓöé                                   Γöé
  2209.   Γöé               ΓöéFocusLost                          Γöé                                   Γöé
  2210.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2211.   ΓöéUser events    ΓöéAdjustMenus HandleEvent            ΓöéCreateRootMenuBar                  Γöé
  2212.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2213.   ΓöéStorage        ΓöéCloneInto** ClonePartInfo          ΓöésomInit** somUninit**              Γöé
  2214.   Γöé               ΓöéExternalize** ExternalizeKinds     Γöé                                   Γöé
  2215.   Γöé               ΓöéInitPart InitPartFromStorage       Γöé                                   Γöé
  2216.   Γöé               ΓöéReadPartInfo WritePartInfo         Γöé                                   Γöé
  2217.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2218.   ΓöéBinding        ΓöéCangeKind                          Γöé                                   Γöé
  2219.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2220.   ΓöéMemory         ΓöéReleaseAll**                       ΓöéAcquire** Purge** Release**        Γöé
  2221.   ΓöéManagement     Γöé                                   Γöé                                   Γöé
  2222.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2223.   ΓöéLinking        ΓöéLinkStatusChanged                  ΓöéBreakLink BreakLinkSource          Γöé
  2224.   Γöé               Γöé                                   ΓöéCreateLink EditInLinkAttempted*    Γöé
  2225.   Γöé               Γöé                                   ΓöéFulfillPromise LinkBroken          Γöé
  2226.   Γöé               Γöé                                   ΓöéLinkUpdated RevealLink ShowLink    Γöé
  2227.   Γöé               Γöé                                   ΓöéUpdateFromLinkSource               Γöé
  2228.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2229.   ΓöéEmbedding      Γöé                                   ΓöéCreateEmbeddedFramesIterator*      Γöé
  2230.   Γöé               Γöé                                   ΓöéEmbeddedFrameUpdated*              Γöé
  2231.   Γöé               Γöé                                   ΓöéRemoveEmbeddedFrame*               Γöé
  2232.   Γöé               Γöé                                   ΓöéRequestEmbeddedFrame*              Γöé
  2233.   Γöé               Γöé                                   ΓöéRequestFrameShape*                 Γöé
  2234.   Γöé               Γöé                                   ΓöéUsedShapeChanged*                  Γöé
  2235.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2236.   ΓöéClipboard      Γöé                                   ΓöéFulfillPromise                     Γöé
  2237.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2238.   ΓöéDrag and Drop  Γöé                                   ΓöéDragEnter DragLeave DragWithin DropΓöé
  2239.   Γöé               Γöé                                   ΓöéDropCompleted FulfillPromise       Γöé
  2240.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2241.   ΓöéUndo           Γöé                                   ΓöéDisposeActionState ReadActionState Γöé
  2242.   Γöé               Γöé                                   ΓöéRedoAction UndoAction              Γöé
  2243.   Γöé               Γöé                                   ΓöéWriteActionState                   Γöé
  2244.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2245.   ΓöéExtensions     Γöé                                   ΓöéAcquireExtension** HasExtension**  Γöé
  2246.   Γöé               Γöé                                   ΓöéReleaseExtension**                 Γöé
  2247.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2248.   ΓöéSemantic EventsΓöé                                   ΓöéEmbeddedFrameSpec*                 Γöé
  2249.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2250.  
  2251.       *  Required of all parts that support embedding 
  2252.       ** Defined in a superclass of ODPart 
  2253.  
  2254.  
  2255. ΓòÉΓòÉΓòÉ 4.2.3. Development Scenarios ΓòÉΓòÉΓòÉ
  2256.  
  2257. This section provides a high-level discussion of several possible OpenDoc 
  2258. development scenarios. Reading the scenarios may help you to decide what kinds 
  2259. of OpenDoc component software you are most interested in developing. 
  2260. Specifically, it discusses 
  2261.  
  2262.      Creating a noncontainer part editor 
  2263.      Creating a container part editor 
  2264.      Converting a conventional application into a part editor 
  2265.      Developing OpenDoc components that are not part editors 
  2266.  
  2267.  
  2268. ΓòÉΓòÉΓòÉ 4.2.3.1. Writing an Editor for NonContainer Parts ΓòÉΓòÉΓòÉ
  2269.  
  2270. Writing a part editor that does not support embedding is somewhat simpler than 
  2271. writing an editor that does. Furthermore, if you are starting from scratch (not 
  2272. modifying an existing application), you are free to consider all aspects of the 
  2273. design of your part editor before you implement anything. 
  2274.  
  2275.      Content model. If your parts are to be scriptable (see the Scripting 
  2276.       step), you must create a content model and construct semantic events that 
  2277.       allow a full range of user operations to be performed on the parts' 
  2278.       content objects. 
  2279.  
  2280.      Core engine. Design and implement your core data engine, the set of data 
  2281.       structures and behaviors that manifest the basic purpose of your editor. 
  2282.  
  2283.      Storage. Implement persistent storage in these situations: 
  2284.  
  2285.         -  Use the OpenDoc storage system to store your part editor's data. 
  2286.            Your part editor must implement code to initialize a part and to 
  2287.            write it back to storage. 
  2288.  
  2289.         -  Implement clipboard and drag-and-drop capabilities to transfer 
  2290.            information between parts, using the same OpenDoc storage concepts 
  2291.            for data transfer as for persistent storage. 
  2292.  
  2293.         -  Implement linking support, using a combination of event-handling 
  2294.            code and storage code (similar to support for document storage, 
  2295.            clipboard, and drag and drop). 
  2296.  
  2297.      Drawing. Give your part the capability of drawing its content, properly 
  2298.       transformed and clipped, in whatever combination of facets and frames the 
  2299.       content appears, onscreen or offscreen, and for screen display or for 
  2300.       printing. 
  2301.  
  2302.      Event handling. Give your part editor the capability of responding to 
  2303.       user events such as mouse clicks and keystrokes. It must also respond 
  2304.       properly to activation and deactivation events and must use the OpenDoc 
  2305.       user interface objects such as members, pop-ups, help, and status line. 
  2306.  
  2307.      Scripting. To support scripting, you must first define the content model 
  2308.       of your parts, as noted earlier (in the Content Model step). Then you 
  2309.       must implement accessory functions to resolve object specifiers (external 
  2310.       references to a part's content objects) as well as semantic-event 
  2311.       handlers to perform your part's content operations. 
  2312.  
  2313.      Extensions. If you plan to extend the capabilities of your parts to 
  2314.       communicate with other parts or process information fast, create and 
  2315.       attach an extension interface to your part editor. To obtain existing 
  2316.       public extension interface designs or to propose a new public interface, 
  2317.       contact CI Labs. 
  2318.  
  2319.      Packaging and shipping. Once your part editor is complete, provide 
  2320.       information for the OpenDoc binding process to use, indicating what part 
  2321.       kinds are handled and what semantic events are handled. 
  2322.  
  2323.  You ship your product as one or more part editors, plus an install program and 
  2324.  accompanying documentation. Users install your part editor into their systems 
  2325.  and then, using the templates that get control at part registration time, 
  2326.  create new documents of your part kind or insert new parts with your part kind 
  2327.  into their documents. Rules and conventions for installing part editors and 
  2328.  storing documents vary among platforms. For OS/2 platform rules, see the 
  2329.  recipe Installation of OpenDoc Software. 
  2330.  
  2331.  Users themselves can create additional, customized template documents. Users 
  2332.  should be able to exchange documents, including templates, freely. 
  2333.  
  2334.  
  2335. ΓòÉΓòÉΓòÉ 4.2.3.2. Writing an Editor for Container Parts ΓòÉΓòÉΓòÉ
  2336.  
  2337. If your part editor is to support embedding-that is, if its parts are to be 
  2338. container parts-you need to include the following additional steps: 
  2339.  
  2340.      Embedding. You need to add embedding support to your content model and to 
  2341.       storage. 
  2342.  
  2343.         -  Your content model needs to include a type of content element that 
  2344.            represents an embedded part. If your part editor supports semantic 
  2345.            events, embedded parts must be content objects to which you can pass 
  2346.            events. 
  2347.  
  2348.         -  Make sure your parts can store embedded parts, both in their 
  2349.            documents and during data transfer. This is relatively simple to 
  2350.            implement; OpenDoc takes care of most of it. 
  2351.  
  2352.      Layout management. You need to add support for layout management during 
  2353.       event handling and during frame negotiation. 
  2354.  
  2355.         -  Your part editor must be able to maintain updated information on 
  2356.            embedded frames and facets and notify embedded parts of such 
  2357.            changes. It must add facets when embedded frames become visible. It 
  2358.            must modify or delete facets when embedded frames move or become no 
  2359.            longer visible. 
  2360.  
  2361.         -  Your part editor must include support for layout negotiation, 
  2362.            including updating the shapes and transforms associated with each 
  2363.            visible embedded frame and facet. 
  2364.  For a summary of the issues to consider in creating a part editor for 
  2365.  container parts, see Embedding Checklist. 
  2366.  
  2367.  
  2368. ΓòÉΓòÉΓòÉ 4.2.3.3. Converting a Conventional Application to a Part Editor ΓòÉΓòÉΓòÉ
  2369.  
  2370. Creating a part editor from an existing conventional application involves 
  2371. maintaining its core features but repackaging them for the OpenDoc environment. 
  2372.  
  2373.      Content model and core data engine. You should have your content model 
  2374.       and core data engine already in place. You may need to separate your core 
  2375.       data engine from other facilities, such as user interface and storage, if 
  2376.       it is not already sufficiently separated. 
  2377.  
  2378.      Storage. You must refit all file I/O and clipboard data transfers into 
  2379.       OpenDoc terms, as described for part editors in the Storage step in 
  2380.       Writing an Editor for NonContainer Parts. 
  2381.  
  2382.      Event handling. Because your part editor will receive its event 
  2383.       information from the document shell, you need to remove your event loop 
  2384.       and event-handling code. 
  2385.  
  2386.      Scripting. You can add scripting support, as described for part editors 
  2387.       in the Scripting step in Writing an Editor for NonContainer Parts. 
  2388.  
  2389.      Extensions. You can extend the capabilities of your parts, as described 
  2390.       for part editors in the Extensions step in Writing an Editor for 
  2391.       NonContainer Parts. 
  2392.  
  2393.      Packaging and shipping. Package and ship your part editor, as described 
  2394.       for part editors in the Packaging and Shipping step in Writing an Editor 
  2395.       for NonContainer Parts. 
  2396.  
  2397.  If your converted application is to be a container part, you need to follow 
  2398.  these additional steps: 
  2399.  
  2400.      Embedding. Add embedding support, as described for part editors in the 
  2401.       Embedding step in Writing an Editor for Container Parts. 
  2402.  
  2403.      Layout management. Add layout-management code, as described for part 
  2404.       editors in the Layout Management step in Writing an Editor for Container 
  2405.       Parts. 
  2406.  
  2407.  
  2408. ΓòÉΓòÉΓòÉ 4.2.3.4. Writing Other Types of Component Software ΓòÉΓòÉΓòÉ
  2409.  
  2410. This book primarily describes how to create a part editor. However, you are not 
  2411. limited to that alone. Development of container applications is discussed 
  2412. briefly in the previous section. Using the OpenDoc class libraries, you can 
  2413. also create other kinds of OpenDoc component software: 
  2414.  
  2415.      Part viewers are simply part editors with their editing and saving 
  2416.       capabilities removed. A part editor should be able to read, display, and 
  2417.       print its parts. 
  2418.  
  2419.       Development issues for part viewers are a subset of those for fully 
  2420.       functional part editors. A part viewer is usually much smaller than its 
  2421.       corresponding editor, and it can be developed from the same code base. 
  2422.  
  2423.       To encourage data interchange, you should always create a part viewer for 
  2424.       every part editor you develop, and you should distribute the viewer 
  2425.       widely and without cost or obligation to the user. 
  2426.  
  2427.      Part extensions are objects with which you can extend the programming 
  2428.       interface of your part editor. Extensions work in conjunction with part 
  2429.       editors, allowing their parts to communicate with and directly manipulate 
  2430.       other parts. Extensions are described in Extending OpenDoc. 
  2431.  
  2432.      Document-shell plug-ins are extensions to the capabilities of the shell. 
  2433.       They are DLLs that you can write and install. Shell plug-ins are 
  2434.       described in Shell Plug-Ins. 
  2435.  
  2436.      Part or document services are OpenDoc components that, instead of editing 
  2437.       and saving parts in a document, provide specialized services to those 
  2438.       parts and documents. Spelling checkers, database-retrieval engines, and 
  2439.       network connection services are all examples. 
  2440.  
  2441.       You develop an OpenDoc service much as you develop a part editor. Like 
  2442.       part editors, services are subclasses of ODPart. However, services 
  2443.       commonly use less of the embedding, layout, and imaging protocols of 
  2444.       OpenDoc, and they usually communicate with the parts they serve through 
  2445.       an extension interface (a subclass of ODExtension). The extension 
  2446.       interface is described in Extending OpenDoc. 
  2447.  
  2448.  
  2449. ΓòÉΓòÉΓòÉ 5. Layout and Embedding ΓòÉΓòÉΓòÉ
  2450.  
  2451. This is the first of eight chapters that discuss the OpenDoc programming 
  2452. interface in detail. This chapter focuses on the key concepts of how parts are 
  2453. embedded in documents and how embedded parts communicate with their containing 
  2454. parts to lay themselves out for display. 
  2455.  
  2456. Before reading this chapter, you should be familiar with the concepts presented 
  2457. in Introduction and Development Overview. For additional concepts related to 
  2458. your part editor's runtime environment see OpenDoc Run-Time Features. 
  2459.  
  2460. This chapter starts with a general discussion of frames and facets, and then 
  2461. describes: 
  2462.  
  2463.      How your part can function as an embedded part in an OpenDoc document 
  2464.  
  2465.      How your part can negotiate with its containing part for modifications to 
  2466.       its display frames 
  2467.  
  2468.  If your part is a noncontainer part, these are the only sections of this 
  2469.  chapter you need to read. If, however, you are developing a container part, 
  2470.  you need also to read the remainder of this chapter. It summarizes how to 
  2471.  embed a part and describes how to interact with the frames and facets of your 
  2472.  embedded parts. 
  2473.  
  2474.  For a summary of embedding issues for container parts, see also Embedding 
  2475.  Checklist. 
  2476.  
  2477.  
  2478. ΓòÉΓòÉΓòÉ 5.1. Frame and Facet Hierarchies ΓòÉΓòÉΓòÉ
  2479.  
  2480. The object hierarchy of embedding controls how information is passed among the 
  2481. parts that make up a compound document. Parts and embedded frames make up one 
  2482. hierarchy; facets make up a separate but essentially parallel hierarchy. 
  2483.  
  2484. The following figure shows a simple example of these hierarchies for a document 
  2485. that consists of a graphics root part ("draw part"), in which is embedded a 
  2486. clock ("clock part") and a text-processing part ("text part"). The text part 
  2487. has a movie-viewing part ("movie part") embedded within it. 
  2488.  
  2489. This figure uses the same conventions as the more detailed run-time diagrams 
  2490. presented in the figure in Run-Time Object Relationships. Individual OpenDoc 
  2491. objects are represented by labeled boxes, with the references (pointers in C++) 
  2492. between them drawn as arrows. (Different arrows have different appearances in 
  2493. the following figure for clarity only; all represent the same kinds of object 
  2494. references). The embedding structure extends downward, with more deeply 
  2495. embedded objects shown lower in the diagram. 
  2496.  
  2497. The window object is at the top of the previous figure, uniting the two 
  2498. hierarchies. The window object itself is referenced by the window state object, 
  2499. as shown in the figure in section Window State and Windows. (Some inter-object 
  2500. references have been omitted from this diagram, as noted in the next section). 
  2501.  
  2502.  
  2503. ΓòÉΓòÉΓòÉ 5.1.1. Frames and Parts ΓòÉΓòÉΓòÉ
  2504.  
  2505. The fundamental structure of embedding in the compound document is represented 
  2506. by the hierarchy on the left. The draw part is the root part of the document; 
  2507. it directly references its two embedded frames. Those frames, in turn, 
  2508. reference their parts: the text part and the clock part. The text part 
  2509. references its one embedded frame, which in turn references its part, the movie 
  2510. part. Each part thus references only indirectly its own embedded parts. (In 
  2511. this case, there is one frame per part, but there could be more than one). 
  2512.  
  2513. Note also that each part also has a reference back up the hierarchy to its 
  2514. display frame, and each frame has a direct reference up to its containing 
  2515. frame. See the figure in Embedding for a more complete picture of the object 
  2516. structure of embedding. 
  2517.  
  2518. The embedding relation of parts and frames does not have to be the strict 
  2519. hierarchy shown in the figure in Frame and Facet Hierarchies. For example, a 
  2520. single part can have frames embedded at different levels, as in the figure in 
  2521. section Providing Split-Frame Views. 
  2522.  
  2523. Parts and frames are stored together in their document. When the document is 
  2524. closed, the states of all the parts and frames are saved. When the document is 
  2525. reopened, all the parts and frames are restored by reading in the saved data. 
  2526.  
  2527.  
  2528. ΓòÉΓòÉΓòÉ 5.1.2. Facets ΓòÉΓòÉΓòÉ
  2529.  
  2530. The hierarchy on the right side of the figure in section Frame and Facet 
  2531. Hierarchies is analogous to the one on the left, but it is simpler and more 
  2532. direct. The facet hierarchy is designed for fast drawing and event-dispatching. 
  2533. Each facet corresponds to its equivalent frame, but it directly references its 
  2534. embedded facets. (In this case, there is one facet per visible frame, but there 
  2535. could be more than one). 
  2536.  
  2537. Whereas frames must exist (at least in storage, if not always in memory) for 
  2538. all embedded parts in a document, facets are needed for only those frames that 
  2539. are visible at any one moment. Because the facet hierarchy is for drawing and 
  2540. event dispatching, there is no need to have facets that cannot be drawn and 
  2541. cannot accept events. 
  2542.  
  2543. Facets are not stored when a document is saved. Facets are created and deleted 
  2544. by their frames' containing parts, as the facets' frames become visible or 
  2545. invisible because of scrolling, resizing of frames or windows, or opening and 
  2546. closing of windows. 
  2547.  
  2548. Note from the figure in section Frame and Facet Hierarchies that each frame has 
  2549. a direct reference to (and from) its equivalent facet. That frame-to-facet 
  2550. reference is the connection between the two hierarchies. It also means that 
  2551. each part object references its own facets only indirectly, through its display 
  2552. frames. (Your part can, of course, keep its own private list of its facets). 
  2553.  
  2554.  
  2555. ΓòÉΓòÉΓòÉ 5.2. Working with your Display Frames and Facets ΓòÉΓòÉΓòÉ
  2556.  
  2557. Your part's display frames are the frames in which you draw your part's 
  2558. contents. This section discusses how to request or respond to changes and 
  2559. additions to those frames. 
  2560.  
  2561. You do not directly create your own part's display frames; your part's 
  2562. containing part does that. When your part is first created or first read into 
  2563. memory from storage, the containing part of your part will in most cases have 
  2564. already provided at least one frame for your part to display itself in. 
  2565. However, it is possible that your part can be instantiated without already 
  2566. having a display frame. (see Adding an Embedded Part). Your part should allow 
  2567. for that possibility. 
  2568.  
  2569. Your part should also allow for the possibility of multiple display frames. 
  2570. Your part must keep a list of its display frames, with enough information so 
  2571. that your part knows how to display itself in each and synchronize their 
  2572. displays when necessary. OpenDoc does not specify the format of that list. It 
  2573. is your responsibility to keep the list and to update each display frame that 
  2574. has been affected by any change to your part. 
  2575.  
  2576.  
  2577. ΓòÉΓòÉΓòÉ 5.2.1. Responding to Reconnected and Closed Display Frames ΓòÉΓòÉΓòÉ
  2578.  
  2579. When the document containing your part opens and your previously stored display 
  2580. frames are read in and instantiated, OpenDoc calls your part's 
  2581. DisplayFrameConnected method. Here is its interface (note that this and all 
  2582. other method prototypes in this book are written in IDL): 
  2583.  
  2584. void DisplayFrameConnected(in ODFrame frame);
  2585.  
  2586. Your DisplayFrameConnected method should update your part's internal list of 
  2587. display frames and other related structures to reflect the addition of the 
  2588. frame. It should assign the frame's used shape, if different from the frame 
  2589. shape itself. It should also check the frame's content extent and update it if 
  2590. necessary, as described in Content Extent. It might also call the frame's 
  2591. SetDroppable method to add the frame's ability to accept drops. 
  2592.  
  2593. Unlike for DisplayFrameAdded (see Responding to an Added Display Frame), your 
  2594. DisplayFrameConnected method does not normally have to create new part info 
  2595. data or a new set of embedded frames for the display frame, because they will 
  2596. have been created earlier. 
  2597.  
  2598. When your part's document is closed, OpenDoc calls your part's 
  2599. DisplayFrameClosed method when it closes your display frame: 
  2600.  
  2601. void DisplayFrameClosed(in ODFrame frame);
  2602.  
  2603. Your DisplayFrameClosed method should 
  2604.  
  2605.      Update your part's internal list of display frames and other related 
  2606.       structures to reflect the closing of the frame 
  2607.  
  2608.      Relinquish any foci owned by the frame; see Relinquishing Foci 
  2609.  
  2610.      Call the Close method of all your embedded frames 
  2611.  
  2612.  If this frame is the root frame of your window and you have previously 
  2613.  instructed OpenDoc not to dispose of the platform-specific window structure, 
  2614.  you must dispose of the platform window yourself at this time. 
  2615.  
  2616.  Closing and reconnecting can happen at other times as well. For efficient 
  2617.  memory use, a containing part may not always keep frame objects in memory for 
  2618.  all of its embedded frames. Instead, as described in Reconnecting and 
  2619.  Releasing Embedded Frames, it might release frames as they become invisible 
  2620.  through scrolling, and reinstantiate them as they become visible. Released 
  2621.  frames can then be closed by OpenDoc. 
  2622.  
  2623.  Do not update your persistently stored display frames when your 
  2624.  DisplayFrameConnected or DisplayFrameClosed methods are called; these methods 
  2625.  should have no effect on stored data. In general, you should write your part 
  2626.  content and frames to storage only when your Externalize or ExternalizeKinds 
  2627.  methods are called. 
  2628.  
  2629.  
  2630. ΓòÉΓòÉΓòÉ 5.2.2. Responding to Added or Removed Facets ΓòÉΓòÉΓòÉ
  2631.  
  2632. When your part's containing part has added a facet to one of your part's 
  2633. display frames, the display frame notifies your part of the addition by calling 
  2634. your part's FacetAdded method. Here is its interface: 
  2635.  
  2636. void FacetAdded(in ODFacet facet);
  2637.  
  2638. Your FacetAdded method must perform certain actions to handle the addition of 
  2639. the new facet to one of your frames. Some actions depend on the nature and 
  2640. implementation of your part itself, but others are standard: 
  2641.  
  2642.      The method should store any private information that it needs as part 
  2643.       info data in the facet that is being added. Although a facet's part info 
  2644.       is not persistent, it can hold information that the facet needs for 
  2645.       display. 
  2646.  
  2647.      The method should assign an active shape to the facet, if needed. If you 
  2648.       do not explicitly assign an active shape, OpenDoc uses the frame shape of 
  2649.       the facet's associated frame for the active shape. 
  2650.  
  2651.      The method should create facets for all embedded frames that are visible 
  2652.       within the area of the added facet.  See Adding a Facet. 
  2653.  
  2654.  When a containing part removes a facet from one of your part's display frames, 
  2655.  the frame notifies your part by calling your part's FacetRemoved method: 
  2656.  
  2657.   void FacetRemoved(in ODFacet facet);
  2658.  
  2659.  Your FacetRemoved method must perform certain actions to handle the removal of 
  2660.  the facet. In general, this method reverses the actions performed by 
  2661.  FacetAdded. Typically, the method should at least: 
  2662.  
  2663.      Remove the facets for all embedded frames that were visible in the area 
  2664.       of the removed facet 
  2665.  
  2666.      Delete any part info data that was referenced in the facet 
  2667.  
  2668.  Facets are intended to be ephemeral objects; don't hold references to them 
  2669.  when they are no longer needed. Your FacetRemoved method should delete all 
  2670.  references to the facets that it removes. 
  2671.  
  2672.  Note:  If your part is the root part in a window, it receives a FacetAdded 
  2673.         call from the root frame when the window is opened and a FacetRemoved 
  2674.         call from the root frame when the window is closed. 
  2675.  
  2676.  
  2677. ΓòÉΓòÉΓòÉ 5.2.3. Resizing a Display Frame ΓòÉΓòÉΓòÉ
  2678.  
  2679. Because of editing operations in your part, or because of an undesirable frame 
  2680. size imposed by your part's containing part, you may wish to change the size or 
  2681. shape of your display frame. You must negotiate this change with the containing 
  2682. part. (For an example of frame negotiation, showing the point of view of both 
  2683. the containing part and the embedded part, see Frame Negotiation). 
  2684.  
  2685. You start by requesting a new frame size from your part's containing part. 
  2686. Depending on its current contents and other constraints such as gridding, the 
  2687. containing part may grant the requested size, return a different size, or 
  2688. refuse the request by returning a size identical to your current frame size. 
  2689.  
  2690. To request a new frame size, take these steps: 
  2691.  
  2692.      Call the RequestFrameShape method of your display frame. The frame, in 
  2693.       turn, calls the containing part's RequestFrameShape method to forward the 
  2694.       request. 
  2695.  
  2696.      The containing part may honor the request, or it may decide on a 
  2697.       different (usually smaller) shape. It returns the shape it will let your 
  2698.       display frame have. The frame stores it as its frame shape and returns it 
  2699.       to you. 
  2700.  
  2701.      Use the returned frame shape to update the used shape for that frame. You 
  2702.       can also, at this time, update the active shape for your frame's facet. 
  2703.  
  2704.      If your part does not wish to accept the new shape, it can call the 
  2705.       frame's RequestFrameShape method again, but with a different shape to 
  2706.       avoid endless repetition of these steps. Alternatively, it can request an 
  2707.       additional frame, as described in Requesting an Additional Display Frame 
  2708.       (next). 
  2709.  
  2710.  
  2711. ΓòÉΓòÉΓòÉ 5.2.4. Requesting an Additional Display Frame ΓòÉΓòÉΓòÉ
  2712.  
  2713. Your part may need a display frame in addition to the frame or frames already 
  2714. created by your part's containing part. For example, you may need an extra 
  2715. frame to flow content into (as when adding another column or page of text), or 
  2716. you may need it to display your part with a new presentation. 
  2717.  
  2718. To request another frame, you can call the RequestEmbeddedFrame method of the 
  2719. containing part. You must specify one of your current display frames as a base 
  2720. frame; the new frame will be a sibling of the base frame, meaning that it is 
  2721. embedded at the same level as the base frame. Also, the new frame will be in 
  2722. the same group as the base frame. (By convention, the containing part adds the 
  2723. new frame to the end of the sequence in that group.) You also pass additional 
  2724. information, such as the view type and presentation for the new frame, and 
  2725. whether it should overlay, or float over, the content of the containing part. 
  2726.  
  2727. The shape you request for the new frame is understood to be expressed in the 
  2728. frame coordinates of the base frame (see Frame Coordinate Space). Thus you can 
  2729. request a position for the new frame that is relative to the base frame (such 
  2730. as above, below, to the side, or overlapping), by specifying an origin that is 
  2731. offset from the base frame's origin. The containing part has ultimate control 
  2732. over frame positioning, however, and is not required to size or place the new 
  2733. frame exactly as you request. Furthermore, the frame shape returned by the 
  2734. containing part is by convention normalized, meaning that the 
  2735. relative-positioning information has been stripped from it and its origin is at 
  2736. (0, 0). 
  2737.  
  2738. The containing part responds to this call as described in Adding an Embedded 
  2739. Frame on Request. Your part then responds as described in Responding to an 
  2740. Added Display Frame (next). 
  2741.  
  2742.  
  2743. ΓòÉΓòÉΓòÉ 5.2.5. Responding to an Added Display Frame ΓòÉΓòÉΓòÉ
  2744.  
  2745. When an additional display frame is created, OpenDoc automatically connects it 
  2746. to the part it displays. This automatic connection ensures that frames are 
  2747. always valid and usable; the object that creates the new frame need do nothing 
  2748. beyond creating the frame itself. 
  2749.  
  2750. To achieve that automatic connection, the part displayed in the frame must 
  2751. respond to this method call, which informs the part that it has a new frame: 
  2752.  
  2753. void DisplayFrameAdded(in ODFrame frame);
  2754.  
  2755. Your part receives this call when it is first created and has no previously 
  2756. stored display frame, and also when additional display frames are created for 
  2757. it. In response to this call, your part's DisplayFrameAdded method performs the 
  2758. appropriate tasks. Most of them depend on the nature and implementation of your 
  2759. part itself; however, here are some general actions it should take: 
  2760.  
  2761.      The method should add the new display frame to your part's list of 
  2762.       display frames. This list, like other internal structures, is completely 
  2763.       hidden from OpenDoc. You can represent the list any way you choose. 
  2764.  
  2765.      The method should validate the view type and presentation of the new 
  2766.       frame. Your part should accept any view types that are in the required 
  2767.       set of view types, plus any other view types or presentations that you 
  2768.       support. The DisplayFrameAdded method should correct these values, if 
  2769.       necessary, as described in Defining General Display Characteristics. 
  2770.  
  2771.      The method should assign your part's current content extent to the frame 
  2772.       using the frame's ChangeContentExtent method; see Content Extent. 
  2773.  
  2774.      The method should assign a used shape for the frame. If you do not 
  2775.       specifically assign a used shape, the frame shape is used; a containing 
  2776.       part that calls the frame's AcquireUsedShape method receives the frame 
  2777.       shape in that case. 
  2778.  
  2779.      The method should add any needed part info to the frame, by calling the 
  2780.       frame's SetPartInfo method. See Part Info for more information. 
  2781.  
  2782.      If the frame being added is the root frame of its window, your part may 
  2783.       want to activate itself. Part activation is described in How Part 
  2784.       Activation Happens. (This situation can occur only when your part is 
  2785.       first created and has no previous display frame; it cannot happen when 
  2786.       creating an additional display frame). 
  2787.  
  2788.      If the frame being added can accept dropped data, the method should call 
  2789.       the frame's SetDroppable method, passing it a value of kODTrue. 
  2790.       Otherwise, the frame will not be able to receive data through drag and 
  2791.       drop. See Drag and Drop for more information. 
  2792.  
  2793.  Your part should not perform any layout or imaging tasks as a result of a 
  2794.  display frame being added; specifically, it should not at this point negotiate 
  2795.  with its containing part for a different frame shape. It should wait until its 
  2796.  FacetAdded method is called, by which time the containing part has stored the 
  2797.  frame shape and the frame has become visible. 
  2798.  
  2799.  Note:  OpenDoc calls DisplayFrameAdded only when a frame is newly created. 
  2800.         When your part opens and its stored display frame is recreated, OpenDoc 
  2801.         calls your part's DisplayFrameConnected method; see Responding to 
  2802.         Reconnected and Closed Display Frames. 
  2803.  
  2804.  
  2805. ΓòÉΓòÉΓòÉ 5.2.6. Removing a Display Frame ΓòÉΓòÉΓòÉ
  2806.  
  2807. To remove a frame in which your part is displayed, you call the 
  2808. RemoveEmbeddedFrame method of your part's containing part. You can only remove 
  2809. frames that you have previously requested through calls to your containing 
  2810. part's RequestEmbeddedFrame method. Your other display frames can be removed 
  2811. only by your containing part. 
  2812.  
  2813. When it receives the RemoveEmbeddedFrame call, the containing part calls the 
  2814. frame's Remove method to permanently remove all connection between your part 
  2815. and the frame. This also decrements the reference count of the frame object, 
  2816. and the draft deletes the frame from storage if the reference count is 0. Just 
  2817. before removing the frame, OpenDoc calls your part's DisplayFrameRemoved 
  2818. method: 
  2819.  
  2820. void DisplayFrameRemoved(in ODFrame frame);
  2821.  
  2822. Your part's containing part can also initiate removal of one of your display 
  2823. frames, as described in Removing an Embedded Frame. OpenDoc calls your 
  2824. DisplayFrameRemoved method regardless of whether your part or the containing 
  2825. part initiates the removal. 
  2826.  
  2827. Your DisplayFrameRemoved method should 
  2828.  
  2829.      Relinquish any foci owned by the frame (see Relinquishing Foci ) 
  2830.  
  2831.      Delete any part info that your part had associated with the frame 
  2832.  
  2833.      Update your part's internal list of display frames and other related 
  2834.       structures to reflect the removal of the frame. 
  2835.  
  2836.      Remove in turn any embedded frames that your part had been displaying in 
  2837.       that frame, by calling their Remove method 
  2838.  
  2839.  If this frame is the root frame of your window and you have previously 
  2840.  instructed OpenDoc not to dispose of the platform-specific window structure, 
  2841.  you must dispose of the platform window yourself at this time. 
  2842.  
  2843.  Note:  OpenDoc calls DisplayFrameRemoved only when a frame is permanently 
  2844.         removed from your part. When your part closes and OpenDoc stores its 
  2845.         display frame, OpenDoc calls your part's DisplayFrameClosed method; see 
  2846.         Responding to Reconnected and Closed Display Frames. 
  2847.  
  2848.  
  2849. ΓòÉΓòÉΓòÉ 5.2.7. Grouping Display Frames ΓòÉΓòÉΓòÉ
  2850.  
  2851. As an embedded part, your part does not directly control the frames in which it 
  2852. is displayed. However, if you need to flow text or other content in order 
  2853. through a sequence of separate display frames of your part (as for page-layout 
  2854. purposes), you can request that the containing part create and assign you the 
  2855. needed frames as a sequence in a single frame group. See Creating Frame Groups. 
  2856.  
  2857.  
  2858. ΓòÉΓòÉΓòÉ 5.2.8. Synchronizing Display Frames ΓòÉΓòÉΓòÉ
  2859.  
  2860. Sometimes, views of your part in two or more separate frames must be 
  2861. synchronized, meaning that any editing or other changes to the contents of one 
  2862. (the source frame) must force updating of the other. In some cases, as when 
  2863. opening one of your display frames into a window, you can determine these 
  2864. dependencies internally. In other cases, you cannot. For example, if your part 
  2865. is an embedded part and your containing part creates multiple views of your 
  2866. part, your containing part asks you to synchronize those views by calling your 
  2867. part's AttachSourceFrame method. This is its interface: 
  2868.  
  2869. void AttachSourceFrame(in ODFrame frame,
  2870.                        in ODFrame sourceFrame);
  2871.  
  2872. Your AttachSourceFrame method should take whatever action is necessary to 
  2873. synchronize the frames; make sure that the result of any editing in one frame 
  2874. appears in the other. At a minimum, if the two frames have the same 
  2875. presentation, the method should duplicate all embedded frames in one frame into 
  2876. the other (and attach them to their source frames as well). It is the 
  2877. containing frame that determines when embedded frames must be synchronized. See 
  2878. Synchronizing Embedded Frames. 
  2879.  
  2880.  
  2881. ΓòÉΓòÉΓòÉ 5.2.9. Using Subframes to Suppress the Active Frame Border ΓòÉΓòÉΓòÉ
  2882.  
  2883. The active frame border (see, for example, The figure in Activation and 
  2884. Selection) is drawn by OpenDoc around the frame of the currently active part. 
  2885. (It actually follows the active shape of the frame's facet, as described in 
  2886. Active Shape. When your part is the active part, OpenDoc automatically draws 
  2887. the active frame border around your part's display frame (the frame that has 
  2888. the selection focus). 
  2889.  
  2890. There may be situations in which you do not want the active frame border around 
  2891. your part's display frame, even when it is active. For example, your part's 
  2892. frame may represent a single pane in a split window (see Using Multiple 
  2893. Facets), in which case the entire window should be considered active, not just 
  2894. the one pane. 
  2895.  
  2896. In such a case you can force OpenDoc to draw the active frame border around 
  2897. your display frame's containing frame instead of your display frame itself. You 
  2898. can call your display frame's SetSubframe method to assign it as a subframe of 
  2899. its containing frame. (You can test whether a frame is a subframe of its 
  2900. containing frame by calling its IsSubframe method). 
  2901.  
  2902.  
  2903. ΓòÉΓòÉΓòÉ 5.2.10. Adopting Container Properties ΓòÉΓòÉΓòÉ
  2904.  
  2905. As described in Transmitting your Container Properties to Embedded Parts, a 
  2906. containing part can notify its embedded parts of the container properties, the 
  2907. characteristics of its content that it expects the embedded parts to adopt. For 
  2908. example, if your part is a text part and the user embeds it into another text 
  2909. part, the containing part may expect your part to adopt the general text 
  2910. appearance (font, size, stylistic variation, and so on) of the containing part. 
  2911.  
  2912. Your part can, of course, adopt only those container properties whose format 
  2913. and meaning it understands. You obtain the set of container properties that 
  2914. your containing part makes available for adoption by calling the 
  2915. AcquireContainingPartProperties method of your containing part. 
  2916.  
  2917. A containing part calls your part's ContainingPartPropertiesUpdated method when 
  2918. it changes any of the container properties available for your part to adopt. 
  2919. This is its interface: 
  2920.  
  2921. void ContainingPartPropertiesUpdated(in ODFrame frame,
  2922.                                      in ODStorageUnit propertyUnit);
  2923.  
  2924. Your ContainingPartPropertiesUpdated method should read and adopt any container 
  2925. properties that it understands from the provided storage unit. Then, it should 
  2926. in turn call the ContainingPartPropertiesUpdated method of any of your part's 
  2927. own embedded frames (other than bundled frames) that are displayed within the 
  2928. frame passed to ContainingPartPropertiesUpdated. 
  2929.  
  2930.  
  2931. ΓòÉΓòÉΓòÉ 5.3. Frame Negotiation ΓòÉΓòÉΓòÉ
  2932.  
  2933. Each part in an OpenDoc document controls the positions, sizes, and shapes of 
  2934. its embedded frames. At the same time, embedded parts may need to change the 
  2935. sizes, shapes, or numbers of the frames in which they are displayed. Read this 
  2936. section if your part expects to negotiate its display frame sizes with its 
  2937. containing part, or if it is a container part and expects to negotiate with its 
  2938. embedded parts over the sizes of its embedded frames. 
  2939.  
  2940. Either party can initiate the negotiation, although the containing part has 
  2941. unilateral control over the outcome. The following figure shows an example of 
  2942. frame negotiation, in which an embedded part with a single display frame 
  2943. requests a larger frame size from its containing part, which has two display 
  2944. frames. 
  2945.  
  2946. In this case, the embedded part initiates the frame negotiation. Its frame is 
  2947. wholly contained within frame 1 (the upper frame) of the containing part: 
  2948.  
  2949.    1. The embedded part asks the containing part for a significantly larger 
  2950.       frame, perhaps to fit material pasted in from the clipboard. The embedded 
  2951.       frame is not concerned with, and does not even know, where or how the 
  2952.       larger frame will fit into the containing part's content. 
  2953.  
  2954.    2. The containing part decides, on the basis of its own content model, that 
  2955.       the requested frame is too large to fit within frame 1. The containing 
  2956.       part instead increases the size of the embedded frame as much as it can, 
  2957.       assigns it a place in its content area, and returns the resulting frame 
  2958.       to the embedded part. 
  2959.  
  2960.    3. The embedded part accepts the frame given to it. If it were to repeat the 
  2961.       first step and ask for the original larger frame again, the containing 
  2962.       part would simply repeat the second step and return the same frame. 
  2963.  
  2964.       But the embedded part still wants more area for its display, so it tries 
  2965.       a different approach; it requests another display frame, this time to be 
  2966.       embedded in frame 2 of the embedded part. 
  2967.  
  2968.    4. The containing part decides that the requested frame will fit in frame 2. 
  2969.       It assigns the frame a place within frame 2 and returns the frame to the 
  2970.       embedded part. 
  2971.  
  2972.  Frame negotiation, from the point of view of the embedded part, is discussed 
  2973.  in Resizing a Display Frame and Requesting an Additional Display Frame. Frame 
  2974.  negotiation, from the point of view of the containing part, is discussed in 
  2975.  Resizing an Embedded Frame and Adding an Embedded Frame on Request. 
  2976.  
  2977.  
  2978. ΓòÉΓòÉΓòÉ 5.4. Working with Embedded Frames and Facets ΓòÉΓòÉΓòÉ
  2979.  
  2980. Read the information in this section if your part can contain embedded parts. 
  2981. It discusses what information your part needs to maintain for embedded frames 
  2982. and how it creates those embedded frames and facets. 
  2983.  
  2984. As a containing part, your part needs to maintain current information on the 
  2985. shapes and transforms for all its visible embedded frames and facets. If it 
  2986. makes changes to them, it should not only update its own information but in 
  2987. some cases also notify the embedded parts of the changes, so that they can 
  2988. update their own information. Your part must also support frame negotiation 
  2989. (see Frame Negotiation), to permit embedded parts to request additional frames 
  2990. or changes to the sizes of their existing frames. 
  2991.  
  2992. If your part is a container part, the user can embed other parts into your part 
  2993. in several ways, such as by pasting from the clipboard, using drag and drop, or 
  2994. even selecting a tool from a palette. 
  2995.  
  2996. The overall process of embedding a part is summarized in the section Adding an 
  2997. Embedded Part. The overall process of removing a part is summarized in Removing 
  2998. an Embedded Part. Both processes make use of the specific tasks described in 
  2999. this section. 
  3000.  
  3001.  
  3002. ΓòÉΓòÉΓòÉ 5.4.1. Creating a New Embedded Frame ΓòÉΓòÉΓòÉ
  3003.  
  3004. If your part embeds a part that does not already have its own display frame, 
  3005. you need to create a new embedded frame that will be the embedded part's 
  3006. display frame. Also, if you create an additional view of an existing embedded 
  3007. part you need to create and embed a frame to hold the new view. 
  3008.  
  3009. In these situations, your part-the containing part-initiates the embedding 
  3010. creation. Your method to create an embedded frame calls the CreateFrame method 
  3011. of the draft, which returns an initialized frame that has already been assigned 
  3012. to the embedded part (CreateFrame calls the DisplayFrameAdded method of the 
  3013. embedded part to do that). This calling sequence ensures that the new frame can 
  3014. be used as soon as the draft returns it. 
  3015.  
  3016. When you call CreateFrame, you specify several features of the new frame, 
  3017. including the following: 
  3018.  
  3019.      Containing frame:  the frame (your display frame) that is to contain the 
  3020.       embedded frame. 
  3021.  
  3022.      Frame shape:  the shape of the frame to be created. Your part can use a 
  3023.       default shape or it can use information supplied with the data you are 
  3024.       embedding; see Frame Shape or Frame Annotation for more information. 
  3025.  
  3026.      Part:  the part (your part) in which the frame is to be embedded. 
  3027.  
  3028.      View type and presentation:  the initial view type and presentation the 
  3029.       part displayed in the embedded frame is to have. 
  3030.  
  3031.      Subframe:  whether or not the embedded frame is to be a subframe of its 
  3032.       containing frame (your display frame). See Using Subframes to Suppress 
  3033.       the Active Frame Border, and Using Multiple Facets for examples. 
  3034.  
  3035.      Overlay status:  whether or not the frame should overlay, or float over, 
  3036.       the containing frame. 
  3037.  
  3038.  Once the reference to the new frame is returned, you store it somewhere in 
  3039.  your content and add it to your part's list of embedded frames. It's up to you 
  3040.  to decide how your part internally stores its content, including its embedded 
  3041.  frames. If the embedded frame is visible within the containing frame, you must 
  3042.  create a facet for it. See Adding a Facet. 
  3043.  
  3044.  For more information on the DisplayFrameAdded method, see Requesting an 
  3045.  Additional Display Frame. 
  3046.  
  3047.  
  3048. ΓòÉΓòÉΓòÉ 5.4.2. Adding an Embedded Frame on Request ΓòÉΓòÉΓòÉ
  3049.  
  3050. As a container part, your part may also need to support creation of an embedded 
  3051. frame when requested to do so by another part. As described in Requesting an 
  3052. Additional Display Frame, an embedded part can call your part's 
  3053. RequestEmbeddedFrame method in order to get an additional frame for its 
  3054. content. The embedded part passes the necessary information about the requested 
  3055. frame, as shown in this interface: 
  3056.  
  3057. ODFrame RequestEmbeddedFrame(in ODFrame containingFrame,
  3058.                              in ODFrame baseFrame,
  3059.                              in ODShape frameShape,
  3060.                              in ODPart embedPart,
  3061.                              in ODTypeToken viewType,
  3062.                              in ODTypeToken presentation,
  3063.                              in ODBoolean isOverlaid);
  3064.  
  3065. Your RequestEmbeddedFrame method passes most of this information along to your 
  3066. draft's CreateFrame method. The base-frame parameter specifies which of the 
  3067. embedded part's existing display frames is to be the base frame for the new 
  3068. frame; the new frame will be a sibling of the base frame and will be in the 
  3069. same frame group (if any) as the base frame. 
  3070.  
  3071. The frameShape parameter passed to this method expresses the requested frame 
  3072. shape in the coordinate system of the base frame. By this method, the embedded 
  3073. part can request, by specifying the origin of the frame shape, a relative 
  3074. location for the new frame compared to its base frame. Your 
  3075. RequestEmbeddedFrame method should take this information into account when 
  3076. granting the frame shape and assigning an external transform to its facet. 
  3077. Specifically, you should incorporate the positioning information into the 
  3078. external transform (if appropriate, given the nature and state of your 
  3079. intrinsic content) and then return a frame shape that has been normalized-that 
  3080. is, one in which the origin of the frame shape is at (0, 0). 
  3081.  
  3082. Based on information in the existing frame, your RequestEmbeddedFrame method 
  3083. should also assign the new frame's group ID and sequence number, by calling its 
  3084. SetFrameGroup and ChangeSequenceNumber methods. Your part can assign the new 
  3085. frame any sequence number in the frame group, although by convention you should 
  3086. add the new frame to the end of the current sequence. Then the 
  3087. RequestEmbeddedFrame method should add the new frame to your part's list of 
  3088. embedded frames. The method should also create a facet for the new frame if it 
  3089. is visible. 
  3090.  
  3091. You might implement your RequestEmbeddedFrame method in such a way that it 
  3092. calls a private method to actually create the frame. You could then use that 
  3093. same private method when creating embedded frames other than by request (as 
  3094. described in the previous section, Creating a New Embedded Frame). 
  3095.  
  3096.  
  3097. ΓòÉΓòÉΓòÉ 5.4.3. Resizing an Embedded Frame ΓòÉΓòÉΓòÉ
  3098.  
  3099. To change a frame's size, the user typically selects the frame and manipulates 
  3100. the frame border's resize handles. The containing part is responsible for 
  3101. drawing the selected frame border, determining what resize handles are 
  3102. appropriate, and interpreting drag actions on them. For more information on 
  3103. event-handling related to resizing frames, see Resizing Selected Frames. 
  3104.  
  3105. If your part is the containing part of a frame that is resized by the user, or 
  3106. if your part has other reasons to change the size of an embedded frame (for 
  3107. example, to enforce gridding or in response to editing of your own intrinsic 
  3108. content surrounding the frame), you need to notify the embedded part that its 
  3109. frame has changed. 
  3110.  
  3111. After you change the embedded frame's shape, call the frame's ChangeFrameShape 
  3112. method and pass it the new shape. (For efficiency, you can first acquire the 
  3113. embedded frame's existing frame shape, then resize it, then call 
  3114. ChangeFrameShape, and finally release your reference to the frame). The frame 
  3115. in turn notifies its part by calling its FrameShapeChanged method. In response, 
  3116. the embedded part may request a different frame size, as discussed in Resizing 
  3117. a Display Frame. 
  3118.  
  3119. Note that resizing may result in your part having to adjust the layout of its 
  3120. own intrinsic content, such as wrapped text. 
  3121.  
  3122.  
  3123. ΓòÉΓòÉΓòÉ 5.4.4. Removing an Embedded Frame ΓòÉΓòÉΓòÉ
  3124.  
  3125. To remove a frame embedded in your part, the basic procedure is to delete all 
  3126. its facets, delete it from your private content structures and call its frame's 
  3127. Remove method. This releases the frame object, which decrements its reference 
  3128. count and possibly causes the draft to delete it from storage. OpenDoc then 
  3129. notifies the embedded part of the removal by calling its DisplayFrameRemoved 
  3130. method, as described in Removing a Display Frame. 
  3131.  
  3132. Removing an embedded frame should be an undoable action, however. Therefore, 
  3133. you should add a few steps to the procedure to retain enough information to 
  3134. reconstruct the frame (and all its embedded frames) if the user chooses to undo 
  3135. the deletion. You can follow steps such as these: 
  3136.  
  3137.    1. Remove all of the embedded facets from the frame; see Removing a Facet. 
  3138.  
  3139.    2. Set the frame's containing frame to kODNULL, to indicate that the frame 
  3140.       is no longer embedded in any part. 
  3141.  
  3142.    3. Place a reference to the frame in an undo action that you add to the undo 
  3143.       history; see Adding an Action to the Undo History. 
  3144.  
  3145.    4. Remove the frame from your embedded-frames list (with which you allow 
  3146.       callers to iterate through your embedded frames; see Providing an 
  3147.       Embedded-Frames Iterator). 
  3148.  
  3149.    5. Remove the frame from your other private content structures. 
  3150.  
  3151.  If the user subsequently chooses to undo the action that led to the removal of 
  3152.  the frame, you can then 
  3153.  
  3154.    1. Retrieve the reference to the frame from the undo action 
  3155.  
  3156.    2. Reestablish your display frame as the frame's containing frame 
  3157.  
  3158.    3. Recreate any needed facets for the frame 
  3159.  
  3160.  If the undo action history is cleared, your part's DisposeActionState method 
  3161.  is called and at that point you can remove the frame object referenced in your 
  3162.  undo action, by calling its Remove method. 
  3163.  
  3164.  
  3165. ΓòÉΓòÉΓòÉ 5.4.5. Reconnecting and Releasing Embedded Frames ΓòÉΓòÉΓòÉ
  3166.  
  3167. Your part connects and closes its embedded frames when the document containing 
  3168. your part opens and closes. On opening, when your part calls the draft's 
  3169. AcquireFrame method for each embedded frame that you want to display the frame 
  3170. in turn calls the DisplayFrameConnected method of its part. After your part and 
  3171. its embedded frames have been saved, and before the document closes, you call 
  3172. the Close method of each of your embedded frames; the frames in turn call the 
  3173. DisplayFrameClosed methods of their parts. 
  3174.  
  3175. The DisplayFrameClosed and DisplayFrameConnected methods are described in 
  3176. Responding to Reconnected and Closed Display Frames. 
  3177.  
  3178. For efficient memory usage, your part can retrieve and connect only the 
  3179. embedded frames that are visible when its document opens, and it can also 
  3180. release and reconnect embedded frames during execution, as the frames become 
  3181. invisible or visible through scrolling or removal of obscuring content. This 
  3182. process is described in Lazy Instantiation. 
  3183.  
  3184.  
  3185. ΓòÉΓòÉΓòÉ 5.4.6. Adding a Facet ΓòÉΓòÉΓòÉ
  3186.  
  3187. OpenDoc needs to know what parts are visible in a window and where, so that it 
  3188. can dispatch events to them properly and make sure they display themselves. But 
  3189. OpenDoc does not need to know the embedding structure of a document; that is, 
  3190. OpenDoc is not directly concerned with where embedded frames are located and 
  3191. what their sizes and shapes are. Because embedded frames are considered to be 
  3192. content elements of their containing part, each containing part maintains 
  3193. embedded-frame positions, sizes, and shapes in its own internal data 
  3194. structures. Therefore, containing parts need to give OpenDoc information about 
  3195. embedded frames only when they are visible. They do this is by creating a facet 
  3196. for each location where one of their embedded frames is visible. 
  3197.  
  3198. An embedded frame in your part may become visible immediately after it is 
  3199. created, or when your part has scrolled or moved it into view, or when an 
  3200. obscuring piece of content has been removed. However the frame becomes visible, 
  3201. your part must ensure that there is a facet to display the frame's contents. 
  3202. Follow these general steps: 
  3203.  
  3204.      If your own display frame has multiple facets, create an embedded facet 
  3205.       for each of the facets in which the newly visible embedded frame appears. 
  3206.       To do that, iterate through all the facets of your display frame, 
  3207.       creating embedded facets where needed. 
  3208.  
  3209.      For each needed facet, if it does not already exist, make one by asking 
  3210.       the containing facet (your display frame's facet) to create one. Call the 
  3211.       containing facet's CreateEmbeddedFacet method. 
  3212.  
  3213.         -  In your call to CreateEmbeddedFacet, assign the embedded facet a 
  3214.            clip shape equal to the embedded frame's frame shape, if the new 
  3215.            facet is to be positioned in front of all sibling facets and other 
  3216.            content in your part. Otherwise, adjust the clip shape as described 
  3217.            in Managing Facet Clip Shapes. 
  3218.  
  3219.         -  Assign the embedded facet an external transform, based on your 
  3220.            part's internal data on the location of the embedded frame. 
  3221.  
  3222.         -  If you are to be drawing offscreen through this facet, assign the 
  3223.            facet a canvas. See Canvases for an explanation. 
  3224.  
  3225.      If you want to receive events sent to, but not handled by, the part 
  3226.       displayed in this facet, set the event-propagating flag of the facet's 
  3227.       frame. See Propagating Events for an explanation. 
  3228.  
  3229.  After you create the facet, OpenDoc calls the embedded part's FacetAdded 
  3230.  method to notify it that it has a new facet. 
  3231.  
  3232.  
  3233. ΓòÉΓòÉΓòÉ 5.4.7. Removing a Facet ΓòÉΓòÉΓòÉ
  3234.  
  3235. An embedded frame may become invisible when the containing part has deleted it, 
  3236. scrolled or moved it out of view, or placed an obscuring piece of content over 
  3237. it. In any of these instances, the containing part can then delete the facet, 
  3238. because it is no longer needed. 
  3239.  
  3240. Your part deletes the facet of an embedded frame by calling the containing 
  3241. facet's RemoveFacet method. (If the frame that is no longer visible has more 
  3242. than one facet, you need to iterate through all facets, removing each one that 
  3243. is not visible). OpenDoc in turn calls the embedded part's FacetRemoved method 
  3244. to notify it that one of its facets has been removed. 
  3245.  
  3246. You do not have to actually delete the facet from memory the moment it is no 
  3247. longer needed; you can instead mark it privately as unused and wait for a call 
  3248. to your Purge method to actually remove it. 
  3249.  
  3250.  
  3251. ΓòÉΓòÉΓòÉ 5.4.8. Creating Frame Groups ΓòÉΓòÉΓòÉ
  3252.  
  3253. A frame group is a set of display frames used in sequence. For example, a 
  3254. page-layout part uses a frame group to display text that flows from one frame 
  3255. to another. Each frame in the frame group has a sequence number; the sequence 
  3256. numbers establish the order of content flow from one frame into the next. 
  3257.  
  3258. Sequence information is important for a frame group because the embedded part 
  3259. needs to know the order in which to fill the frames. Also your part (the 
  3260. containing part) needs to provide sequence information to the user, and it 
  3261. probably also needs to allow the user to set up or modify the sequence. 
  3262.  
  3263. Your part creates and maintains the frame groups used by all its embedded 
  3264. parts. To create a frame group, you call the SetFrameGroup method of each frame 
  3265. that is to be in the group, passing it a group ID that is meaningful to you. 
  3266. You also assign each frame a unique sequence number within its group, by 
  3267. calling its SetSequenceNumber method. You should assign sequence numbers that 
  3268. increase uniformly from 1, so that the embedded part can recognize the position 
  3269. of each frame in the group. You can, of course, add and remove frames from the 
  3270. group and alter their sequence with additional calls to SetFrameGroup and 
  3271. SetSequenceNumber. The embedded part displayed in the frame group can find out 
  3272. the group ID or sequence number of any of its frames by calling the frame's 
  3273. GetFrameGroup and GetSequenceNumber methods. 
  3274.  
  3275.  
  3276. ΓòÉΓòÉΓòÉ 5.4.9. Synchronizing Embedded Frames ΓòÉΓòÉΓòÉ
  3277.  
  3278. If your part wants to create multiple similar views of an embedded part, you 
  3279. must ask the embedded part to synchronize those views. Then, if the content of 
  3280. one of the frames is edited, the embedded part will know to invalidate and 
  3281. redraw the equivalent areas in the other frames. 
  3282.  
  3283. Frame synchronization is necessary because each display frame of a containing 
  3284. part represents a separate display hierarchy. For invalidating and redrawing, 
  3285. OpenDoc itself maintains no direct connection between embedded frames in those 
  3286. separate hierarchies, even if they are exact duplicates that show the same 
  3287. embedded-part content. the figure in Synchronizing Embedded Frames shows an 
  3288. example. Part A (in frame view type) is opened into a part window. Embedded 
  3289. frame B2, as displayed in the part window, is a duplicate of embedded frame B1 
  3290. in the original frame. However, unless you synchronize the frames, Part B will 
  3291. not know to update the display of B1 if the user edits the content of B2. 
  3292.  
  3293. Your part (the containing part) makes the request to synchronize frames by 
  3294. calling the embedded part's AttachSourceFrame method. You should call 
  3295. AttachSourceFrame as soon as you create the frame that needs to be synchronized 
  3296. with the source frame-that is, before you add any facets to the frame. How an 
  3297. embedded part responds to AttachSourceFrame is described in Grouping Display 
  3298. Frames. See Synchronizing Display Frames for a description of how an embedded 
  3299. part responds to AttachSourceFrame. 
  3300.  
  3301.  
  3302. ΓòÉΓòÉΓòÉ 5.4.10. Transmitting your Container Properties to Embedded Parts ΓòÉΓòÉΓòÉ
  3303.  
  3304. When one part is embedded in another part of the same or similar part category, 
  3305. the user may prefer that, by default, they share certain visual or behavioral 
  3306. characteristics. For example, if the user embeds a text part into another text 
  3307. part, it might be more convenient for the embedded part to adopt the text 
  3308. appearance (font, size, stylistic variation) of the containing part. 
  3309.  
  3310. OpenDoc supports the communication necessary for this process by defining the 
  3311. concept of container properties. The containing part defines whatever 
  3312. characteristics it wishes to transmit to its embedded parts; embedded parts 
  3313. that understand those container properties can choose to adopt them. Container 
  3314. properties are passed from the containing part to its embedded part in a 
  3315. storage unit; the embedded part reads whatever container properties it 
  3316. understands from the storage unit, and adopts them for its own display if 
  3317. appropriate. 
  3318.  
  3319. Note:  Container properties are completely part-defined and may apply to only a 
  3320.        portion of a part's content, and thus are in general unrelated to the 
  3321.        properties of the part's storage unit, as described in Storage-Unit 
  3322.        Organization. 
  3323.  
  3324.  As the containing part, your part can define whatever container properties it 
  3325.  wishes to provide for adoption by embedded parts. Only parts that understand 
  3326.  the formats of your container properties, of course, can adopt them. 
  3327.  
  3328.  An embedded part learns what container properties it might adopt from your 
  3329.  part by calling your part's AcquireContainingPartProperties method. This is 
  3330.  its interface: 
  3331.  
  3332.   ODStorageUnit AcquireContainingPartProperties(in ODFrame frame);
  3333.  
  3334.  You should return your container properties to the caller in a storage unit. 
  3335.  
  3336.  Whenever your part changes any of the container properties that it expects 
  3337.  embedded parts to adopt, it should notify each embedded part (other than 
  3338.  bundled parts) of the change by calling the embedded part's 
  3339.  ContainingPartPropertiesUpdated method. 
  3340.  
  3341.  
  3342. ΓòÉΓòÉΓòÉ 5.4.11. Providing an Embedded-Frames Iterator ΓòÉΓòÉΓòÉ
  3343.  
  3344. Your part must keep a list of all its embedded frames. OpenDoc does not specify 
  3345. the format of this list. However, your part must implement an iterator class 
  3346. (type ODEmbeddedFramesIterator) that gives a caller access to each of the 
  3347. frames in your list of embedded frames. The caller creates an iterator to 
  3348. access your embedded frames by calling your part's CreateEmbeddedFramesIterator 
  3349. method, which has this interface: 
  3350.  
  3351. ODEmbeddedFramesIterator CreateEmbeddedFramesIterator(in ODFrame frame);
  3352.  
  3353. Your implementation of CreateEmbeddedFramesIterator must provide First, Next, 
  3354. and IsNotComplete methods, as do other OpenDoc iterators. See Accessing Objects 
  3355. through Iterators for additional discussion. 
  3356.  
  3357.  
  3358. ΓòÉΓòÉΓòÉ 6. Drawing ΓòÉΓòÉΓòÉ
  3359.  
  3360. This is the second of eight chapters that discuss the OpenDoc programming 
  3361. interface in detail. This chapter describes how your part draws itself. 
  3362.  
  3363. Before reading this chapter, you should be familiar with the concepts presented 
  3364. in Introduction and Development Overview. You should also be familiar with the 
  3365. discussion of frames and facets presented in the previous chapter. For 
  3366. additional concepts related to your part editor's runtime environment, see 
  3367. OpenDoc Run-Time Features. The discussion in this chapter also assumes that you 
  3368. are familiar with the platform-specific graphics system and drawing commands 
  3369. you need to draw your parts' content. For OS/2, this means the OS/2 Graphic 
  3370. Programming Interface (GPI). 
  3371.  
  3372. This chapter shows how your part: 
  3373.  
  3374.      Uses canvases as drawing destinations 
  3375.      Use transforms and shapes to lay out its contents 
  3376.      Draws itself to the screen 
  3377.      Prints itself 
  3378.  
  3379.  For a discussion of windows, the display structures within which all your 
  3380.  drawing typically takes place, see Windows and Menus. 
  3381.  
  3382.  
  3383. ΓòÉΓòÉΓòÉ 6.1. Canvases ΓòÉΓòÉΓòÉ
  3384.  
  3385. Canvases are inherently platform-specific. OpenDoc canvas objects are basically 
  3386. wrappers for structures that differ across platforms. This section discusses 
  3387. how to use canvas objects regardless of which platform you are developing for, 
  3388. with some OS/2-specific information provided where appropriate. 
  3389.  
  3390.  
  3391. ΓòÉΓòÉΓòÉ 6.1.1. Using Canvases ΓòÉΓòÉΓòÉ
  3392.  
  3393. The class ODCanvas is OpenDoc's wrapper for a platform-specific (or 
  3394. graphics-system-specific) object that represents a drawing environment. A 
  3395. drawing canvas can refer to anything from a bit map or a structured display 
  3396. list to a stream of PostScript code. It represents the destination for drawing 
  3397. commands, the environment for constructing a rendered image; it has a 
  3398. coordinate system and may retain state information (such as pen color) that 
  3399. influences how drawing commands are interpreted. 
  3400.  
  3401. A canvas object holds a reference to a system-specific object called a platform 
  3402. canvas, and that object is not deleted when the canvas is released. If you 
  3403. create a canvas, you must create the platform canvas separately, and you are 
  3404. responsible for deleting it when the canvas is deleted. 
  3405.  
  3406. On some platforms, the platform canvas is a system-defined type or structure. 
  3407. On OS/2, it is a SOM class, which you create using the ODFacet method 
  3408. CreatePlatformCanvas. 
  3409.  
  3410.  
  3411. ΓòÉΓòÉΓòÉ 6.1.1.1. Canvas Features ΓòÉΓòÉΓòÉ
  3412.  
  3413. Canvases can be dynamic or static, meaning that they are used for video display 
  3414. or printing display, respectively. Your part editor can determine whether it is 
  3415. drawing to a static or dynamic canvas and can adjust its procedures 
  3416. accordingly. 
  3417.  
  3418. Canvases can be onscreen or offscreen. Your part editor can create special 
  3419. effects or improve performance by drawing a complex image to an offscreen cache 
  3420. and then quickly transferring the completed image to the screen. For added 
  3421. convenience, offscreen canvases maintain clipping and updating information that 
  3422. mirrors their onscreen equivalents. 
  3423.  
  3424. Canvases are attached to individual facets. In the following figure, for 
  3425. example, which shows the same document with the same facet hierarchy as in the 
  3426. figure in Frame and Facet Hierarchies, the document has two attached canvases: 
  3427.  
  3428.      An offscreen canvas is attached to the movie part's facet. 
  3429.  
  3430.      An onscreen canvas is attached to the root part's facet. (A canvas 
  3431.       attached to the root facet of a window is also called a window canvas; 
  3432.       every window has a window canvas, which is assigned to its root facet by 
  3433.       OpenDoc when you first register the window). 
  3434.  
  3435.  If a particular facet in a window's facet hierarchy has an attached canvas, 
  3436.  all of its embedded facets (and their embedded facets, and so on) draw to that 
  3437.  canvas. Thus, for most drawing, only a window's root facet needs a canvas. In 
  3438.  the previous figure, for example, any drawing done to the text facet, draw 
  3439.  facet, or clock facet is rendered on the window canvas. 
  3440.  
  3441.  However, if a particular part needs an offscreen canvas, for itself or for an 
  3442.  embedded part, it can attach a canvas to a facet anywhere within the 
  3443.  hierarchy. Any drawing done to the movie facet in the previous figure, for 
  3444.  example, is rendered on the offscreen canvas. 
  3445.  
  3446.  On OS/2, a window canvas consists of a Presentation Manager (PM) window 
  3447.  hierarchy that parallels the facet hierarchy. There is one PM window for each 
  3448.  facet in the window canvas. 
  3449.  
  3450.  Every canvas has an owner, a part that is responsible for transferring images 
  3451.  drawn on its canvas to the parent of that canvas. In the previous figure, for 
  3452.  example, the movie images drawn to the offscreen canvas must be transferred to 
  3453.  the window canvas in order to be viewed onscreen. The owner decides when and 
  3454.  how to transfer images from a canvas to its parent. The owner of the offscreen 
  3455.  canvas in the previous figure might be the movie part or the text part that 
  3456.  contains the movie part. 
  3457.  
  3458.  
  3459. ΓòÉΓòÉΓòÉ 6.1.1.2. Adding and Removing Canvases ΓòÉΓòÉΓòÉ
  3460.  
  3461. This section describes how to create and delete canvases for your parts. For 
  3462. specific information on using canvases for offscreen drawing, see Offscreen 
  3463. Drawing. If you want to create a canvas and attach it to a facet, take these 
  3464. steps: 
  3465.  
  3466.    1. Create and initialize a GPI presentation space and associate it with a 
  3467.       memory DC. 
  3468.  
  3469.    2. Create an ODPlatformCanvas object using the CreatePlatformCanvas method 
  3470.       of ODFacet. 
  3471.  
  3472.    3. Create a canvas object, using the CreateCanvas method of ODFacet or 
  3473.       ODWindowState. In calling the method, you assign the platform canvas to 
  3474.       the new canvas, and you also define the canvas as static or dynamic and 
  3475.       onscreen or offscreen. (These values cannot change for the lifetime of 
  3476.       the canvas). 
  3477.  
  3478.    4. Designate your part as owner of the canvas by calling the SetOwner method 
  3479.       of the canvas. 
  3480.  
  3481.    5. Assign the canvas to a facet. Because only the owner of a canvas can 
  3482.       remove it from a facet, the timing of assigning the canvas is important: 
  3483.  
  3484.           If your part is a containing part assigning an offscreen canvas to 
  3485.            one of its embedded parts, you should assign the canvas when you 
  3486.            first create the embedded facet that is, when you first call the 
  3487.            CreateEmbeddedFacet method of the embedded part's containing facet. 
  3488.            Otherwise, the embedded part may assign a canvas to the facet, 
  3489.            precluding you from doing so. 
  3490.  
  3491.           If your part is a containing part and one of its embedded parts has 
  3492.            an existing facet with no assigned canvas, you can add one by 
  3493.            calling the ChangeCanvas method of the embedded facet. When you do 
  3494.            so, OpenDoc communicates the change to all embedded parts that use 
  3495.            that facet, by calling their CanvasChanged methods. 
  3496.  
  3497.           Your part can add a canvas to any of its own display frames' facets 
  3498.            at any time, as long as the facet does not already have an assigned 
  3499.            canvas. It is probably best to attach the canvas as soon as the 
  3500.            facet is created, by calling ChangeCanvas from within your part's 
  3501.            FacetAdded method. If the containing part of your part has already 
  3502.            attached a canvas to your new facet, you cannot assign a different 
  3503.            canvas to it. 
  3504.  
  3505.           If your part absolutely needs to attach its own canvas to a facet 
  3506.            that already has an assigned canvas, you can get around this 
  3507.            restriction by creating a subframe of the facet's frame, creating a 
  3508.            facet for that frame, and assigning the canvas to that facet. 
  3509.  
  3510.  To remove a canvas from a facet, take these steps: 
  3511.  
  3512.    1. Call the facet's ChangeCanvas method, passing it a null value for the 
  3513.       canvas reference. 
  3514.  
  3515.    2. Delete the PS and memory DC that the platform canvas had referenced. 
  3516.  
  3517.    3. Delete the canvas object, by calling delete (in C++). 
  3518.  
  3519.    4. Delete the platform canvas object, by calling delete in C++. 
  3520.  
  3521.  
  3522. ΓòÉΓòÉΓòÉ 6.2. Transforms and Shapes ΓòÉΓòÉΓòÉ
  3523.  
  3524. Unlike windows and canvases, transforms and shapes are not platform-specific. 
  3525. The OpenDoc objects that represent them may encapsulate platform-specific 
  3526. structures, but they also often give added capabilities. This section discusses 
  3527. how you use transforms and shapes to position and clip embedded parts for 
  3528. drawing. 
  3529.  
  3530.  
  3531. ΓòÉΓòÉΓòÉ 6.2.1. Transforms and Coordinate Spaces ΓòÉΓòÉΓòÉ
  3532.  
  3533. Both frames and facets employ transforms. It is useful to discuss them in terms 
  3534. of the coordinate spaces they define. 
  3535.  
  3536. In OpenDoc, an object of the class ODTransform is a 3x3 matrix that is used to 
  3537. modify the locations of points in a systematic manner. OpenDoc transforms 
  3538. support the full range of two-dimensional transformations shown in the 
  3539. following figure. 
  3540.  
  3541. Not all graphics systems support all the features of OpenDoc transforms. Some 
  3542. graphics systems support only offset, or translation, of points; others support 
  3543. offset plus scaling; still others support all transformations. Depending on the 
  3544. graphics system your part editor uses, it may have to do extra work on its own 
  3545. to support features such as scaling or rotation. In such a case, you can create 
  3546. a subclass of ODTransform, if desired, that adds those features or even other, 
  3547. more sophisticated transformational capabilities. 
  3548.  
  3549. A transform can be thought of as defining a coordinate space for the items that 
  3550. it is applied to. OpenDoc uses transforms to convert among two kinds of 
  3551. coordinate space: frame coordinate space and content coordinate space. 
  3552.  
  3553.  
  3554. ΓòÉΓòÉΓòÉ 6.2.1.1. Frame Coordinate Space ΓòÉΓòÉΓòÉ
  3555.  
  3556. The frame coordinate space is the coordinate system defined by the 
  3557. specification of the frame shape. The frame shape is the basis for the layout 
  3558. and drawing of embedded parts. Suppose, for example, that a frame shape is 
  3559. defined as a rectangle with coordinates of (0, 0) and (100, 100). In a 
  3560. coordinate system with the origin at the lower left as in OS/2, the shape would 
  3561. appear as shown in the figure below. 
  3562.  
  3563. All shapes and geometric information passed back and forth between embedded 
  3564. parts and their containing parts are expressed in terms of the frame coordinate 
  3565. space. 
  3566.  
  3567. Note that the shapes describing the facet associated with a frame are described 
  3568. in the same coordinate space as the frame; that is, they are in frame 
  3569. coordinates. Thus, in this example, if the facet corresponded exactly to the 
  3570. frame (which is common), it would have coordinates of (0, 0) and (100, 100). 
  3571.  
  3572.  
  3573. ΓòÉΓòÉΓòÉ 6.2.1.2. Content Coordinate Space ΓòÉΓòÉΓòÉ
  3574.  
  3575. The content coordinate space of a part is the coordinate system that defines 
  3576. locations in the part's content area. It is the local coordinate space of the 
  3577. part itself and typically has its origin in the lower-left corner of the part's 
  3578. content. 
  3579.  
  3580. The internal transform of a part's display frame defines the scrolled position 
  3581. (as well as the scaling, rotational, and skew properties) of the part's 
  3582. contents within the frame. Applying the display frame's internal transform to a 
  3583. point in content coordinate space converts it to frame coordinate space. 
  3584. Conversely, applying the inverse of the internal transform to a point in frame 
  3585. coordinate space converts it to content coordinate space. 
  3586.  
  3587. For example, suppose that the following figure shows the entire contents of a 
  3588. part, and that a portion of it is to be displayed in a frame. If the part's 
  3589. display frame has the dimensions shown previously (the figure in Frame 
  3590. Coordinate Space), and if the frame's internal transform specifies an offset 
  3591. value of (50, 50), the frame would appear in relation to its part's content as 
  3592. shown in the following figure. Only the portion of the part within the area of 
  3593. frame shape will be displayed when the part is drawn. 
  3594.  
  3595. Application of the internal transform, in this case, means that a point at (50, 
  3596. 50) in content coordinates-the lower-left corner of the display frame-is at (0, 
  3597. 0) in frame coordinates. Conversely, a point at (50, 50) in frame coordinates 
  3598. is at (0, 0) in content coordinates. 
  3599.  
  3600. Transformations other than offsets are applied in the same manner; you can 
  3601. scale, rotate, or otherwise transform the contents of the part within its frame 
  3602. by applying the frame's internal transform. 
  3603.  
  3604.  
  3605. ΓòÉΓòÉΓòÉ 6.2.1.3. Converting to the Coordinates of a Containing Part ΓòÉΓòÉΓòÉ
  3606.  
  3607. Just as the internal transform of a frame defines the scrolled position of the 
  3608. content it displays, the external transform of that frame's facet defines the 
  3609. position of the frame within its containing part. 
  3610.  
  3611. Applying the external transform of a frame's facet to a point in frame 
  3612. coordinate space converts it to the content coordinate space of the containing 
  3613. part. For example, suppose that the facet and frame of the embedded part in the 
  3614. previous figure have the same shape, and suppose further that the facet's 
  3615. external transform specifies an offset of (150, 10). In relation to the 
  3616. containing part's content area, the embedded part would appear as shown in the 
  3617. following figure. 
  3618.  
  3619. In this case, applying the external transform causes a point at (0, 0) in 
  3620. embedded-frame coordinates-the lower-left corner of the embedded part's 
  3621. frame-to be at (150, 10) in containing-part content coordinates. 
  3622.  
  3623. (Conversely, applying the inverse of the embedded facet's external transform to 
  3624. a point in content coordinate space converts it to the embedded frame's 
  3625. coordinate space. Thus, in the previous figure, a point at (150, 10) in 
  3626. embedded-frame coordinates is at (0,0) in the content coordinates of the 
  3627. containing part). 
  3628.  
  3629. Transformations other than offsets are applied in the same manner; the embedded 
  3630. part and its frame can be scaled, rotated, or otherwise transformed within the 
  3631. containing part by applying the facet's external transform. 
  3632.  
  3633. To convert from the content coordinates of an embedded part to the content 
  3634. coordinates of its containing part therefore, you need to apply two transforms: 
  3635. the internal transform of the embedded part's display frame, followed by the 
  3636. external transform of that frame's facet. For the example shown in this 
  3637. section, you can see by inspection that the point (50, 50) in the content 
  3638. coordinates of the embedded part (the origin of its display frame) becomes the 
  3639. point (150, 10) in the content coordinates of the containing part. You could 
  3640. also calculate that the point (0, 0) in the contents of the embedded part (its 
  3641. lower-left corner) converts, by application of both transforms, to the point 
  3642. (100, 10) in the contents of the containing part (outside of the embedded frame 
  3643. and, therefore, not drawn). 
  3644.  
  3645. You are not usually concerned with your embedded part's location within the 
  3646. content area of its containing part. You are, however, always interested in 
  3647. your content's location-and your frame's location-on the canvas or in the 
  3648. window in which you are drawn, as described next. 
  3649.  
  3650.  
  3651. ΓòÉΓòÉΓòÉ 6.2.1.4. Canvas Coordinates and Window Coordinates ΓòÉΓòÉΓòÉ
  3652.  
  3653. When your part draws its contents, or when it draws adornments to its frame 
  3654. such as scroll bars, it is your part's responsibility to properly position what 
  3655. it draws on its canvas. In setting up the canvas' platform-specific drawing 
  3656. environment, you need to provide information that tells the canvas where, in 
  3657. terms of its own coordinate space, your drawing will take place. OpenDoc does 
  3658. not do that for you automatically. It does, however, provide methods that make 
  3659. it fairly simple. 
  3660.  
  3661. If you start from your part's content coordinate space and traverse the 
  3662. embedding hierarchy upward, applying, in turn, your part's internal transform 
  3663. and external transform, followed by each internal transform and external 
  3664. transform of all containing frames and facets, up to a facet with an attached 
  3665. canvas, you arrive at the canvas coordinate space or the window coordinate 
  3666. space in which your part is drawn. 
  3667.  
  3668.      If there are no offscreen canvases in the facet hierarchy, the canvas 
  3669.       coordinate space is the same as the window coordinate space, and 
  3670.       calculating it involves applying all transforms up through the internal 
  3671.       transform of the root facet. This coordinate space corresponds to the 
  3672.       device coordinates of the window canvas. 
  3673.  
  3674.      If there are one or more offscreen canvases in the facet hierarchy, the 
  3675.       canvas coordinate space corresponds to the frame coordinates of the first 
  3676.       part above yours in the hierarchy whose facet has an attached canvas. 
  3677.       Calculating it involves applying all transforms up through the internal 
  3678.       transform of the frame whose facet has the canvas. The window coordinate 
  3679.       space, in this case, is unaffected by the presence of an offscreen 
  3680.       canvas; it is still defined by the device coordinates of the window 
  3681.       canvas. 
  3682.  
  3683.  The following figure shows a simple example of converting to canvas 
  3684.  coordinates and window coordinates. The containing part and the embedded part 
  3685.  are the same ones as shown in the figure in Converting to the Coordinates of a 
  3686.  Containing Part, and the containing part is, in this case, the root part of 
  3687.  the window. The internal transform of the root frame (the containing part's 
  3688.  display frame) specifies an offset of (50, 50), and the external transform of 
  3689.  the root facet is identity. 
  3690.  
  3691.  Converting content coordinates to window coordinates means concatenating all 
  3692.  the transforms up through the root frame's external transform. If there is no 
  3693.  offscreen canvas in the previous figure, the point (50,50) in content 
  3694.  coordinates (the origin of the embedded part's frame, as shown in the figure 
  3695.  in Content Coordinate Space) becomes the point (100, 10) in window or canvas 
  3696.  coordinates. If there were an offscreen canvas attached to the embedded facet 
  3697.  in the previous figure, the canvas coordinates for the origin of the embedded 
  3698.  part's frame would be (0,0). 
  3699.  
  3700.  Normally, you do all your drawing in canvas coordinate space. That way, 
  3701.  whether or not you are drawing to an offscreen canvas (which you might not 
  3702.  control or even be aware of), your positioning will be correct. However, when 
  3703.  you need to draw directly to the window to provide specific user feedback, as 
  3704.  described in Drawing Directly to the Window, you need to work in window 
  3705.  coordinates. 
  3706.  
  3707.  By concatenating the appropriate internal and external transforms, OpenDoc 
  3708.  calculates four different composite transforms that you can use for 
  3709.  positioning before drawing: 
  3710.  
  3711.      The composite transform from your content coordinates to canvas 
  3712.       coordinates is called your content transform, and you apply it when 
  3713.       drawing your part's contents on any canvas. You obtain it by calling your 
  3714.       facet's AcquireContentTransform method. 
  3715.  
  3716.      The composite transform from your frame coordinates to canvas coordinates 
  3717.       is called your frame transform, and you apply it when drawing any frame 
  3718.       adornment on the canvas. You obtain it by calling your facet's 
  3719.       AcquireFrameTransform method. 
  3720.  
  3721.      The composite transform from your content coordinates to window 
  3722.       coordinates is called your window-content transform, and you apply it 
  3723.       when drawing your part's contents directly to the window. You obtain it 
  3724.       by calling your facet's AcquireWindowContentTransform method. 
  3725.  
  3726.      The composite transform from your frame coordinates to window coordinates 
  3727.       is called your window-frame transform, and you apply it when drawing any 
  3728.       frame adornment directly to the window. You obtain it by calling your 
  3729.       facet's AcquireWindowFrameTransform method. 
  3730.  
  3731.  For a description of how to use these transforms when setting up for drawing, 
  3732.  see Draw Method of your Part Editor. 
  3733.  
  3734.  
  3735. ΓòÉΓòÉΓòÉ 6.2.1.4.1. Transforms and Hit-Testing ΓòÉΓòÉΓòÉ
  3736.  
  3737.  
  3738. Hit-testing is, in a sense, the inverse of drawing; it involves a conversion 
  3739. from window coordinates to your part's content coordinates. In most 
  3740. circumstances, OpenDoc takes care of this for you. See Hit-Testing for more 
  3741. information. 
  3742.  
  3743.  
  3744. ΓòÉΓòÉΓòÉ 6.2.1.5. Coordinate Bias and Platform-Normal Coordinates ΓòÉΓòÉΓòÉ
  3745.  
  3746. On each platform, OpenDoc uses the platform's native coordinate system, called 
  3747. platform-normal coordinates, for stored information and for internal 
  3748. calculations. For example, on OS/2, coordinates are measured with the origin at 
  3749. the lower-left (of the screen, of a shape, or of a page, and so on), with 
  3750. increasing values to the right and upward. Some other platforms use coordinates 
  3751. with an origin at the upper-left, with values increasing to the right and 
  3752. downward. The following figure shows how these two coordinate systems would 
  3753. apply to measurements on a text part's page. 
  3754.  
  3755. OpenDoc functions consistently on any platform, regardless of the platform's 
  3756. coordinate system, without need for coordinate conversion. However, a part 
  3757. editor that assumes a particular coordinate system will not function correctly 
  3758. with OpenDoc on a platform with a different coordinate system, unless it first 
  3759. accounts for the coordinate bias, or difference between its coordinate system 
  3760. and platform-normal coordinates. 
  3761.  
  3762.  
  3763. ΓòÉΓòÉΓòÉ 6.2.1.5.1. Bias Transforms ΓòÉΓòÉΓòÉ
  3764.  
  3765.  
  3766. Coordinate bias usually takes the form of an offset in the origin, a change in 
  3767. the polarity of one or more axes, and possibly a change in scale. A 
  3768. transformation matrix, called a bias transform, is applied to measurements in a 
  3769. part's coordinate system to change them into platform-normal values. 
  3770.  
  3771. When your part editor's assumed coordinate system is different from that of 
  3772. OpenDoc or other parts on the current platform, your part can still communicate 
  3773. properly with them if you install an offscreen canvas on your part's facets and 
  3774. assign the proper bias transform to it. You draw to that canvas using your own 
  3775. coordinates and then transfer the (automatically transformed) results to the 
  3776. onscreen, platform-normal, parent canvas. 
  3777.  
  3778.  
  3779. ΓòÉΓòÉΓòÉ 6.2.1.5.2. Content Extent ΓòÉΓòÉΓòÉ
  3780.  
  3781.  
  3782. To convert locations in your part's content between coordinate systems whose 
  3783. origins are offset, the vertical extent of your content (in essence, the height 
  3784. of your part's page) represents the offset between the two coordinate origins. 
  3785. See the figure in Coordinate Bias and Platform-Normal Coordinates for an 
  3786. example. This content extent is the offset needed in the bias transform that 
  3787. performs the conversion. 
  3788.  
  3789. Because your part may be drawn at any time on a canvas that has a bias 
  3790. transform attached, you should always make the value of your content extent 
  3791. available. When a frame is added to your part, and whenever your part's content 
  3792. extent changes (such as when you add a new page), you should call your display 
  3793. frame's ChangeContentExtent method so that the frame always stores the proper 
  3794. value. A caller constructing a bias transform can obtain the current content 
  3795. extent of your part by calling the GetContentExtent method of your part's 
  3796. frame. 
  3797.  
  3798.  
  3799. ΓòÉΓòÉΓòÉ 6.2.1.5.3. The biasCanvas Parameter ΓòÉΓòÉΓòÉ
  3800.  
  3801.  
  3802. The classes ODFrame and ODFacet include several methods, such as 
  3803. ChangeInternalTransform and ContainsPoint, that specify shapes or calculate 
  3804. positions on a canvas. Because these calculations necessarily assume a 
  3805. coordinate system, the methods include a parameter, biasCanvas, that allows you 
  3806. to specify a canvas whose attached bias transform is to be used to convert 
  3807. between your part editor's coordinates and platform-normal coordinates. Thus, 
  3808. after you set up your offscreen canvas for drawing in your own coordinate 
  3809. system, you can also use it to make sure that all point, frame, and facet 
  3810. geometry is properly converted for you. 
  3811.  
  3812.  
  3813. ΓòÉΓòÉΓòÉ 6.2.2. Using Transforms ΓòÉΓòÉΓòÉ
  3814.  
  3815. The sections that follow cover some of the basic ways you can use transforms to 
  3816. position and modify the content of your part and embedded parts. 
  3817.  
  3818.  
  3819. ΓòÉΓòÉΓòÉ 6.2.2.1. Scrolling your Part in a Frame ΓòÉΓòÉΓòÉ
  3820.  
  3821. If your part's content area is greater than its frame area, only a portion of 
  3822. the content can be displayed in the frame. The user needs to be able to choose 
  3823. which portion of a part shows through its frame by moving the part's 
  3824. contents-as a unit-in relation to the frame position. 
  3825.  
  3826. The standard OpenDoc method for supporting this ability involves the Show Frame 
  3827. Outline menu command, available in the View menu when the user opens your 
  3828. part's frame into its own part window. In this mode, the user can drag an 
  3829. outline of the frame, positioning it as desired in your part's content area. 
  3830. Another standard method employs a mode that uses a hand-shaped cursor to drag 
  3831. the part within its frame. It is also possible to use arrow keys or other 
  3832. keyboard input to cause scrolling. 
  3833.  
  3834. Providing scroll bars is another way to support scrolling. If your part is the 
  3835. root part of a document window or part window, scroll bars are the standard 
  3836. method. If your part is an embedded part displayed in a frame, scroll bars may 
  3837. or may not be appropriate, depending on the size of your frame and the nature 
  3838. of its contents. 
  3839.  
  3840. Programmatically, changing the portion of a part displayed in a frame involves 
  3841. modifying the offset (translational setting) of the internal transform of the 
  3842. part's frame and then redrawing. If you do not have scroll bars within your 
  3843. frame, these are the basic steps: 
  3844.  
  3845.    1. Obtain a copy of your frame's internal transform, by calling the frame's 
  3846.       AcquireInternalTransform method. 
  3847.  
  3848.    2. Call the MoveBy method of the transform, passing it the negative of the 
  3849.       amount by which you want the frame to scroll. 
  3850.  
  3851.    3. Reassign the changed transform to your frame, by calling your frame's 
  3852.       ChangeInternalTransform method. 
  3853.  
  3854.    4. Redraw the scrolled frame, as shown in the following figure and discussed 
  3855.       in Drawing when a Part Is Scrolled. 
  3856.  
  3857.  For more information on redrawing frames that include scroll bars or other 
  3858.  adornments, see Drawing with Scroll Bars. For more information on handling 
  3859.  scroll bars, interpreting events in them, and redrawing frames that include 
  3860.  scroll bars or other adornments, see Scrolling. 
  3861.  
  3862.  
  3863. ΓòÉΓòÉΓòÉ 6.2.2.2. Transforming the Image of your Part ΓòÉΓòÉΓòÉ
  3864.  
  3865. If the graphics system used by your part editor supports all transformations, 
  3866. you can simply modify the internal transform of your display frame to achieve 
  3867. the kinds of special effects shown in the figure in Transforms and Coordinate 
  3868. Spaces. By modifying the internal transform appropriately, you not only can 
  3869. position your part's content in its display frames, but you can also scale, 
  3870. rotate, skew, and apply perspective to it. The OS/2 GPI supports all types of 
  3871. transforms except perspective (see the figure in Transforms and Coordinate 
  3872. Spaces). 
  3873.  
  3874. For example, you could change the scale of your part's content-to support 
  3875. either higher precision in positioning or larger total content area than would 
  3876. otherwise be possible-by including a scale factor in your display frames' 
  3877. internal transforms. Then, to leave embedded parts' displays unaffected by the 
  3878. scaling, you could apply the inverse scaling factor to the external transforms 
  3879. of all embedded facets. 
  3880.  
  3881. Even if your graphics system does not support features such as rotation or 
  3882. skew, you can still "pre-transform" your images by first applying the internal 
  3883. transform to all drawing coordinates, before passing them to the drawing 
  3884. commands. 
  3885.  
  3886.  
  3887. ΓòÉΓòÉΓòÉ 6.2.2.3. Positioning an Embedded Frame ΓòÉΓòÉΓòÉ
  3888.  
  3889. In general, your containing part can store information on the shapes and 
  3890. positions of embedded frames in any format that is convenient for you. When 
  3891. frames become visible, however, OpenDoc needs that positioning information to 
  3892. allow it to dispatch events correctly and to correctly place the drawn images 
  3893. of each embedded part. 
  3894.  
  3895. Thus, when you create a facet for a visible frame embedded in your part, you 
  3896. assign it (when calling the CreateEmbeddedFacet method) an external transform 
  3897. whose offset reflects the position of the embedded frame in the coordinate 
  3898. system of your part content. If you later reposition that frame, you need to 
  3899. modify its facet's external transform, if the frame is visible. You can change 
  3900. a facet's external transform, as well as its clip shape, by calling its 
  3901. ChangeGeometry method. 
  3902.  
  3903.  
  3904. ΓòÉΓòÉΓòÉ 6.2.2.4. Transforming the Image of an Embedded Part ΓòÉΓòÉΓòÉ
  3905.  
  3906. You can use the external transform of a facet embedded in your part to achieve 
  3907. special display effects, regardless of the display intention of the embedded 
  3908. part. By modifying the external transform appropriately, you not only can 
  3909. position the frame within your part's displayed content but can also scale, 
  3910. rotate, skew, and apply perspective to it. 
  3911.  
  3912. For example, you could make separate embedded frames appear to be the faces of 
  3913. a cube, giving each the proper skew or perspective necessary to achieve the 
  3914. effect, regardless of what is being drawn in each frame by its own part editor. 
  3915.  
  3916.  
  3917. ΓòÉΓòÉΓòÉ 6.2.3. Using Drawing-Related Shapes ΓòÉΓòÉΓòÉ
  3918.  
  3919. A shape object is an OpenDoc object that is an instance of the class ODShape. 
  3920. It is the specification of a two-dimensional shape in a given coordinate space. 
  3921. Different platforms and different graphics systems define shapes differently. 
  3922. Objects of the class ODShape are partly wrappers for system-specific shape 
  3923. structures, but they also have the ability to convert among several common 
  3924. shape structures. 
  3925.  
  3926. OpenDoc uses shape objects for clipping purposes in drawing and hit-testing. 
  3927. There are four drawing-related shapes: the frame shape and used shape, attached 
  3928. to the frame object; and the clip shape and active shape, attached to the facet 
  3929. object. 
  3930.  
  3931.  
  3932. ΓòÉΓòÉΓòÉ 6.2.3.1. Frame Shape ΓòÉΓòÉΓòÉ
  3933.  
  3934. The frame shape is discussed in many places in this book, including earlier in 
  3935. this chapter, in Frame and Facet Hierarchies. The frame shape represents the 
  3936. fundamental contract between embedded part and containing part for display 
  3937. space. The other drawing-related shapes are variations on the frame shape, and 
  3938. all are defined in the same coordinate system as the frame shape. 
  3939.  
  3940. A frame shape is commonly rectangular, as shown in the following figure, but it 
  3941. can have any kind of outline, even irregular. An embedded part can request a 
  3942. nonrectangular frame shape if it has a special need for one; for example, a 
  3943. part that displays a clock face might request a round frame shape. It is the 
  3944. containing part's right to comply with or deny that request, and it is also the 
  3945. containing part's responsibility to draw that frame's selected appearance, 
  3946. including resize handles, if appropriate. 
  3947.  
  3948. The frame shape is defined by the containing part and is stored in the frame 
  3949. object. Your part (the containing part) can set an embedded frame's frame shape 
  3950. by calling the frame's ChangeFrameShape method. Any caller may access the frame 
  3951. shape by calling the frame's AcquireFrameShape method. 
  3952.  
  3953. By convention, your part should use the frame shape when drawing the selected 
  3954. frame border of an embedded part. 
  3955.  
  3956. Cross-platform representation 
  3957.  
  3958. The frame shape is stored persistently, and your part may subsequently be 
  3959. displayed under a different graphics system. Therefore, it is important that a 
  3960. frame shape have a platform-neutral (that is, polygonal) representation when it 
  3961. is stored. 
  3962.  
  3963.  
  3964. ΓòÉΓòÉΓòÉ 6.2.3.2. Used Shape ΓòÉΓòÉΓòÉ
  3965.  
  3966. An embedded part may need a nonrectangular shape to draw in, may need to change 
  3967. frame shape often, or may want to allow the containing part to be able to draw 
  3968. within portions of its frame. In these cases, the embedded part need not 
  3969. negotiate for an unusual frame shape or continually renegotiate its frame size. 
  3970. Instead it can define a used shape to tell its containing part which portions 
  3971. of its frame shape it is currently using. In the following figure, for example, 
  3972. the embedded part retains a rectangular frame shape but defines a used shape 
  3973. that covers only the content elements it draws. The containing part can then 
  3974. use that information to, perhaps, wrap its content to the used portions of the 
  3975. embedded part. For example, the third figure in Event Handling shows a 
  3976. containing part (a text part) that wraps its text closely to the used shape of 
  3977. an embedded part (a pie-chart part whose frame shape is actually rectangular). 
  3978.  
  3979. The used shape is defined by the embedded part, specified in frame coordinates, 
  3980. and stored in the frame object. Any caller may access the used shape by calling 
  3981. the frame's AcquireUsedShape method. If the embedded part has not stored a used 
  3982. shape in its frame, AcquireUsedShape returns the frame shape as a default. 
  3983.  
  3984. Note that it does not make sense for the used shape to extend beyond the edges 
  3985. of the frame shape, because the clip shape (described on Clip Shape) is based 
  3986. on the frame shape and no drawing occurs outside of the clip shape. 
  3987.  
  3988. Your part can set its display frame's used shape by calling the frame's 
  3989. ChangeUsedShape method. (You can pass a null shape to ChangeUsedShape to make 
  3990. your used shape identical to your frame shape). When you do, OpenDoc then calls 
  3991. the UsedShapeChanged method of your containing part: 
  3992.  
  3993. void UsedShapeChanged(in ODFrame embeddedFrame);
  3994.  
  3995. If your part is the containing part in this situation and has wrapped its 
  3996. content to the embedded part's used shape, you can use this method to adjust 
  3997. your content to the new used shape. 
  3998.  
  3999.  
  4000. ΓòÉΓòÉΓòÉ 6.2.3.3. Active Shape ΓòÉΓòÉΓòÉ
  4001.  
  4002. A facet's active shape is the area within a frame in which the embedded part is 
  4003. willing to receive geometry-based (mouse) events. The active shape of a facet 
  4004. is often identical to either the frame shape or the used shape of its frame, as 
  4005. shown in the following figure. The active area of a part is likely to coincide 
  4006. with the area it draws in; events within the frame shape but outside of the 
  4007. used shape are better sent to the containing part, which may have drawn in that 
  4008. area. 
  4009.  
  4010. The active shape is defined by the embedded part, is specified in frame 
  4011. coordinates, and is stored in the facet object. Your embedded part can set the 
  4012. active shape of its display frame's facet by calling the facet's 
  4013. ChangeActiveShape method. Any caller may access the active shape by calling the 
  4014. facet's AcquireActiveShape method. If the embedded part has not stored an 
  4015. active shape in its facet, AcquireActiveShape returns the frame's shape. 
  4016.  
  4017. Note that the effective active shape-the active shape as the user perceives 
  4018. it-is the intersection of the active shape and the clip shape (described next). 
  4019. Events within the area of obscuring content or other frames that block the 
  4020. active shape are not passed to the embedded part. 
  4021.  
  4022. OpenDoc uses the active shape when drawing the active frame border of an 
  4023. embedded part. 
  4024.  
  4025.  
  4026. ΓòÉΓòÉΓòÉ 6.2.3.4. Clip Shape ΓòÉΓòÉΓòÉ
  4027.  
  4028. A facet's clip shape defines the portion of a frame that is actually to be 
  4029. drawn. The clip shape of a facet is commonly identical to the frame shape of 
  4030. its frame, except that it may be modified to account for obscuring content 
  4031. elements or overlapping frames in the containing part, as shown in the 
  4032. following figure. 
  4033.  
  4034. The clip shape is defined by the containing part, it is specified in frame 
  4035. coordinates, and it is stored in the facet object. Your part (the containing 
  4036. part) can set the clip shape of an embedded frame's facet by calling the 
  4037. facet's ChangeGeometry method. Any caller may access the clip shape by calling 
  4038. the facet's AcquireClipShape method. 
  4039.  
  4040.  
  4041. ΓòÉΓòÉΓòÉ 6.2.4. Managing Facet Clip Shapes ΓòÉΓòÉΓòÉ
  4042.  
  4043. This section describes how your part adjusts the clip shapes of its embedded 
  4044. frames' facets before drawing, to account for overlapping relationships and for 
  4045. the active frame border that OpenDoc draws. 
  4046.  
  4047.  
  4048. ΓòÉΓòÉΓòÉ 6.2.4.1. Clipping Embedded Facets and Intrinsic Content ΓòÉΓòÉΓòÉ
  4049.  
  4050. Sibling frames are frames embedded at the same level within a containing frame. 
  4051. They may be frames in a frame group (described in Creating Frame Groups), or 
  4052. they may be unrelated frames belonging to different embedded parts. Because 
  4053. sibling frames can overlap each other and can overlap (or be overlapped by) 
  4054. intrinsic content of the containing part, it is the responsibility of the 
  4055. containing part to ensure that clipping occurs properly. The following figure 
  4056. shows examples of the overlapping relationships that can occur. 
  4057.  
  4058.  
  4059. ΓòÉΓòÉΓòÉ 6.2.4.2. List of Embedded Facets ΓòÉΓòÉΓòÉ
  4060.  
  4061. If your part contains embedded frames, it must maintain a z-ordered 
  4062. (front-to-back) list of the embedded frames and content elements, so that you 
  4063. can reconstruct the overlapping relationships among them. You use that list to 
  4064. update the clip shapes of the facets of your embedded frames. 
  4065.  
  4066. You control the z-ordering among sibling frames embedded in your part, and you 
  4067. can communicate that information to OpenDoc through the MoveBehind and 
  4068. MoveBefore methods of the containing facet of the sibling frames' facets. The 
  4069. facet positioning you achieve with MoveBehind and MoveBefore is reflected in 
  4070. the order in which you or OpenDoc (or any caller) encounters facets when you 
  4071. use a facet iterator (class ODFacetIterator) to access each of the sibling 
  4072. facets in turn (as, for example, when calculating a resulting clip shape). 
  4073.  
  4074.  
  4075. ΓòÉΓòÉΓòÉ 6.2.4.3. Calculating the Clip Shapes ΓòÉΓòÉΓòÉ
  4076.  
  4077. If your part contains embedded frames, it performs two related tasks when 
  4078. managing its embedded facets' clip shapes. 
  4079.  
  4080.      It must clip all of its embedded facets so that sibling embedded parts 
  4081.       don't improperly overwrite each other, the containing part's intrinsic 
  4082.       content, or the active frame border. (Adjusting the Active Frame Border 
  4083.       describes how to account for the active frame border). 
  4084.  
  4085.      It must clip its own intrinsic content so that it doesn't improperly 
  4086.       overwrite embedded parts or the active frame border. This also means 
  4087.       taking drawing responsibility in the area of an embedded frame that is 
  4088.       outside the embedded frame's used shape; because the embedded part does 
  4089.       not draw outside of its used shape, it is the containing part's 
  4090.       responsibility to do so. 
  4091.  
  4092.  In calculating the clip shapes for your embedded parts' facets, remember these 
  4093.  points: 
  4094.  
  4095.      A facet's clip shape is affected only by sibling elements, whether they 
  4096.       be items of intrinsic content or facets of other embedded frames. Your 
  4097.       own display facet's clip shape, and the clip shapes of facets embedded 
  4098.       within your embedded parts, have no effect. 
  4099.  
  4100.      When one embedded facet obscures another, use the used shape of the 
  4101.       obscuring facet's frame to clip the obscured facet. 
  4102.  
  4103.      When intrinsic content obscures an embedded facet, make sure to account 
  4104.       for all of it-including selection handles, the active frame border, and 
  4105.       other adornments. 
  4106.  
  4107.      You need to recalculate your embedded parts' clip shapes whenever a 
  4108.       content element or an embedded frame is added, deleted, moved, adorned 
  4109.       with resize handles, or modified in any way that affects how it is drawn. 
  4110.       However, when a given item changes, you need only to recalculate the 
  4111.       clips of it and the elements behind it; the clipping of elements lower in 
  4112.       z-order is unaffected. 
  4113.  
  4114.  Your routine to recalculate embedded-facet clip shapes could take steps 
  4115.  similar to these: 
  4116.  
  4117.    1. Create a "working clip," a clip shape that at each point in the 
  4118.       calculations represents the total area that is not obscured of your 
  4119.       display facet. Start it as a copy of your own display frame's used shape; 
  4120.       only content elements within that area need to have their clip shapes 
  4121.       recalculated. 
  4122.  
  4123.    2. If the currently active frame is embedded in your part, subtract the 
  4124.       active frame border from your working clip. (See Adjusting the Active 
  4125.       Frame Border). 
  4126.  
  4127.    3. Iterate through all your z-ordered content elements, front to back. For 
  4128.       each element that is an item of intrinsic content, do this: 
  4129.  
  4130.           Calculate a new clip shape, representing the visible portion of the 
  4131.            item, by intersecting the item's shape with the current working 
  4132.            clip. Store the new clip shape according to your own content model. 
  4133.  
  4134.           Calculate a new mask shape that includes both the (clipped) content 
  4135.            item shape and any adornments (such as selection handles) it may 
  4136.            have. Modify the working clip by subtracting that mask shape from 
  4137.            it, so that elements behind this content item will be obscured. 
  4138.  
  4139.       Likewise, for each element that is an embedded facet, do this: 
  4140.  
  4141.           Get the frame shape for the facet's frame and convert it to your own 
  4142.            content coordinates. Intersect it with the current working clip (to 
  4143.            account for obscuring content in front), convert it back to 
  4144.            embedded-frame coordinates, and assign it as the facet's new clip 
  4145.            shape. 
  4146.  
  4147.           Calculate a new mask shape by getting the used shape for the facet's 
  4148.            frame and converting it to your own content coordinates. Modify the 
  4149.            working clip by subtracting that mask shape from it, so that 
  4150.            elements behind this embedded frame will be obscured. 
  4151.  
  4152.  
  4153. ΓòÉΓòÉΓòÉ 6.2.4.4. Embedded-Part Responsibilities ΓòÉΓòÉΓòÉ
  4154.  
  4155. The containing part is responsible for its embedded facets' clip shapes, but 
  4156. the embedded part has some responsibilities, to ensure that drawing occurs 
  4157. properly: 
  4158.  
  4159.      The embedded part must always clip its own drawing operations correctly, 
  4160.       using its aggregate clip shape; see Draw Method of your Part Editor. 
  4161.  
  4162.      The embedded part must never draw outside of its used shape. Only a root 
  4163.       part can draw outside of its used shape. 
  4164.  
  4165.      When a containing part changes the clip shape of one of its embedded 
  4166.       frame's facets, OpenDoc notifies the embedded part of the change by 
  4167.       calling the embedded part's GeometryChanged method. If the embedded part 
  4168.       is drawing asynchronously (see Asynchronous Drawing), its next 
  4169.       asynchronous draw must use the new clip shape. 
  4170.  
  4171.  
  4172. ΓòÉΓòÉΓòÉ 6.2.4.5. Adjusting the Active Frame Border ΓòÉΓòÉΓòÉ
  4173.  
  4174. When a partcsq.s frame is active, OpenDoc draws the active frame border (shown 
  4175. in the following figure) around the frame. Neither the active part itself nor 
  4176. its containing part need to draw the border. 
  4177.  
  4178. However, the active frame border occupies an area a few pixels wide in the 
  4179. content area of the active partcsq.s containing part, and it may overlap or be 
  4180. overlapped by other content elements (embedded frames or intrinsic content) of 
  4181. the containing part (see the following figure). Therefore, it is up to the 
  4182. containing part to make sure that the active frame border is appropriately 
  4183. clipped by elements in front of the active frame, and that elements behind the 
  4184. active frame are appropriately clipped so that they do not draw themselves 
  4185. within the border area. 
  4186.  
  4187. When a new frame acquires the selection focus, or when the active frame changes 
  4188. its frame shape, OpenDoc calculates a new active border shape. It then passes 
  4189. that shape to the active part's containing part, by calling the containing 
  4190. part's AdjustBorderShape method: 
  4191.  
  4192. ODShape AdjustBorderShape(in ODFacet embeddedFacet,
  4193.                           in ODShape shape) ;
  4194.  
  4195. Your AdjustBorderShape method has two tasks:  clip the active border shape to 
  4196. account for obscuring content, and clip any of your own content that is 
  4197. obscured by the border. 
  4198.  
  4199. When the active frame embedded in your part becomes inactive and thus no longer 
  4200. has the active border around it, OpenDoc notifies your part of the change by 
  4201. calling your part's AdjustBorderShape method once more, this time passing a 
  4202. null value for the shape parameter. You can then remove the clipping you had 
  4203. previously applied to your obscured content. 
  4204.  
  4205. Note:  If your part receives several consecutive calls to its AdjustBorderShape 
  4206.        method, it means that your embedded (active) frame has several facets. 
  4207.        Consider the active border shape to be the union of all the provided 
  4208.        shapes. 
  4209.  
  4210.  In your AdjustBorderShape method, you can take steps such as the following. 
  4211.  These steps assume that you maintain a field in your part that is a copy of 
  4212.  the clipped active frame border, and that your embedded-frame clipping method 
  4213.  (see Managing Facet Clip Shapes) uses that active-border field to clip your 
  4214.  content elements. 
  4215.  
  4216.    1. If the shape parameter is null, you no longer need to maintain an active 
  4217.       frame border. Release the border shape you had maintained, set your 
  4218.       active-border field to null, call your embedded-frame clipping method to 
  4219.       remove the clipping that had been caused by the presence of the active 
  4220.       frame border, and exit. 
  4221.  
  4222.    2. If the shape parameter is non-null, copy the shape, convert it to your 
  4223.       own content coordinates, and intersect it with your own used shape, so 
  4224.       that the active border will not be drawn outside of your used shape. 
  4225.  
  4226.    3. To calculate the resultant clipped border shape, iterate through all your 
  4227.       z-ordered content elements, starting from the facet of the active frame 
  4228.       and working toward the front. (Only items in front of the facet can clip 
  4229.       it). 
  4230.  
  4231.           For each element that is an item of intrinsic content, calculate a 
  4232.            mask shape that includes both the item's shape and any adornments 
  4233.            (such as selection handles) it may have. Subtract that mask shape 
  4234.            from your active-border shape. 
  4235.  
  4236.           For each element that is an embedded facet, calculate a mask shape 
  4237.            by getting the used shape for the facet's frame, converting it to 
  4238.            your own content coordinates, and subtracting it from your 
  4239.            active-border shape. 
  4240.  
  4241.    4. If your active-border field is currently null, place the resulting 
  4242.       active-border shape in it. If it is currently non-null, you are 
  4243.       calculating a composite border shape from several facets of the active 
  4244.       frame; in that case, union the resulting active-border shape with the 
  4245.       shape already in the field. 
  4246.  
  4247.    5. Call your embedded-frame clipping method (see Managing Facet Clip 
  4248.       Shapes), so that it will recalculate the clip shapes of all items behind 
  4249.       the active frame, making sure that they don't overwrite it. 
  4250.  
  4251.  If your AdjustBorderShape method does nothing and simply passes back the shape 
  4252.  it receives, it must increment the shape's reference count before returning 
  4253.  it. 
  4254.  
  4255.  
  4256. ΓòÉΓòÉΓòÉ 6.3. Drawing ΓòÉΓòÉΓòÉ
  4257.  
  4258. Fundamental to OpenDoc is the responsibility of each part in a compound 
  4259. document to draw itself, within the limits of the frame provided by its 
  4260. containing part. Drawing typically occurs when your part editor is asked to 
  4261. draw a particular facet of a particular frame in which its part is displayed. 
  4262. Your part editor is responsible for examining that facet and frame and 
  4263. displaying the correct data, with the appropriate representation, properly 
  4264. transformed and clipped. 
  4265.  
  4266. Before drawing, your part editor should, if necessary, update the used shapes 
  4267. of its frames and the active shapes of its facets, so that the containing part 
  4268. can lay itself out correctly and so that only the proper events are dispatched 
  4269. to your part by the document shell. 
  4270.  
  4271. This section begins by discussing how your part defines the general 
  4272. characteristics of its display and outlining several aspects of the basic 
  4273. drawing process. The section then discusses: 
  4274.  
  4275.      Drawing with scroll bars 
  4276.      Drawing directly to the window 
  4277.      Asynchronous drawing 
  4278.      Offscreen drawing 
  4279.      Use of multiple frames and facets 
  4280.      Storing cached representation of your frames' content 
  4281.  
  4282.  
  4283. ΓòÉΓòÉΓòÉ 6.3.1. Defining General Display Characteristics ΓòÉΓòÉΓòÉ
  4284.  
  4285. OpenDoc parts can display themselves in different ways in different frames or 
  4286. in different ways in the same frame at different times. The part is in control 
  4287. of its display within the borders of its frames, but there are conventions for 
  4288. other parts to request that the part display itself in a particular way. 
  4289.  
  4290. There are two kinds of display categories. The view type of a frame indicates 
  4291. whether the part within it is shown as one of several kinds of icons (standard 
  4292. icon, small icon, or thumbnail) or whether the part content itself is drawn 
  4293. within a frame. Some view types are standard values defined by OpenDoc; any 
  4294. part should be able to draw itself in any of the standard view types. You can 
  4295. define your own view types also. 
  4296.  
  4297. The presentation of a frame describes, for parts whose view type is framed, how 
  4298. the content is to be represented within the frame. Presentations are 
  4299. part-defined. You define what types of presentations your part supports and you 
  4300. assign their values. Examples of presentations are top view, side view, 
  4301. wireframe, full rendering, table, bar chart, pie chart, and tool palette. 
  4302.  
  4303. View type and presentation are represented as tokenized ISO strings of type 
  4304. ODTypeToken. If you create a presentation type, you define it first as an ISO 
  4305. string and then use the session object's Tokenize method to convert it to a 
  4306. token. 
  4307.  
  4308.  
  4309. ΓòÉΓòÉΓòÉ 6.3.1.1. View Type ΓòÉΓòÉΓòÉ
  4310.  
  4311. You can get and set the view type of your own frames by calling the frame's 
  4312. GetViewType and SetViewType methods, respectively. 
  4313.  
  4314. In general, a part is expected to adopt the view type specified by its 
  4315. containing part. However, another part (such as your part's containing part) 
  4316. can change your frame's view type at any time, and you can change the view type 
  4317. of a frame of another part (such as one of your part's embedded parts) at any 
  4318. time, by calling the frame's ChangeViewType method. ChangeViewType sets the 
  4319. view type and then notifies the owning part, by calling the ViewTypeChanged 
  4320. method: 
  4321.  
  4322. void ViewTypeChanged(in ODFrame frame);
  4323.  
  4324. If your part receives this call, it should display itself in the specified 
  4325. frame according to the indicated view type. Parts must support all standard 
  4326. view types. If your part does not support the requested view type, call your 
  4327. display frame's SetViewType method to change it back to a view type that you 
  4328. support. (Calling SetViewType does not result in a call to your ViewTypeChanged 
  4329. method). 
  4330.  
  4331. Note that a change in view type can mean a change in the optimum size for your 
  4332. display frame. Your ViewTypeChanged method might therefore engage in frame 
  4333. negotiation with your part's containing part at this point. 
  4334.  
  4335.  
  4336. ΓòÉΓòÉΓòÉ 6.3.1.2. Presentation ΓòÉΓòÉΓòÉ
  4337.  
  4338. You can get and set the presentation of your own frames by calling the frame's 
  4339. GetPresentation and SetPresentation methods, respectively. 
  4340.  
  4341. Note that another part can change your frame's presentation, or you can change 
  4342. the presentation of another part's frame, by calling the frame's 
  4343. ChangePresentation method. In response, ChangePresentation sets the 
  4344. presentation and then notifies the owning part, by calling the part's 
  4345. PresentationChanged method: 
  4346.  
  4347. void PresentationChanged(in ODFrame frame);
  4348.  
  4349. If your part receives this call, and if it supports the indicated presentation, 
  4350. it should display itself in the specified frame accordingly. If it recognizes 
  4351. the indicated presentation but does not support it, or if it does not recognize 
  4352. it, your part should instead pick a close match or a standard default. It 
  4353. should then call the frame's SetPresentation method to give it the correct 
  4354. value. (Calling SetPresentation does not result in a call to your 
  4355. PresentationChanged method). 
  4356.  
  4357.  
  4358. ΓòÉΓòÉΓòÉ 6.3.1.3. Part Info ΓòÉΓòÉΓòÉ
  4359.  
  4360. The part info data of a frame is a convenient place for your part to store 
  4361. information about that particular view of itself. The information can be 
  4362. anything from a simple ID to a pointer to a complicated structure or a 
  4363. reference to a helper object. A frame's part info is stored with the frame, not 
  4364. the part. Thus, if the part has many frames and if only a few have been read 
  4365. into memory, only the part info of those frames will be taking up space in 
  4366. memory. 
  4367.  
  4368. To assign information to a frame's part info field, use its SetPartInfo method; 
  4369. to retrieve its part info, use its GetPartInfo method. Writing a frame's part 
  4370. info to its storage unit and reading it back in are described in Reading and 
  4371. Writing Part Info. 
  4372.  
  4373. The facet object also contains a part info field, which can hold any kind of 
  4374. display-related information that you wish, such as transforms, color 
  4375. information, pen characteristics, or any other imaging-related data. 
  4376.  
  4377. To assign information to a facet's part info field, use its SetPartInfo method; 
  4378. to retrieve its part info, use its GetPartInfo method. (A facet's part info is 
  4379. not persistently stored, so there are no methods for reading and writing it). 
  4380.  
  4381.  
  4382. ΓòÉΓòÉΓòÉ 6.3.2. Basic Drawing ΓòÉΓòÉΓòÉ
  4383.  
  4384. This section discusses how your part editor performs its drawing tasks in 
  4385. typical situations. 
  4386.  
  4387.  
  4388. ΓòÉΓòÉΓòÉ 6.3.2.1. Setting Up ΓòÉΓòÉΓòÉ
  4389.  
  4390. To set itself up properly for display, your part should have previously 
  4391. examined the following information in the given facet and its frame: 
  4392.  
  4393.      The view type of the frame tells your part whether it should display 
  4394.       itself as an icon or whether it should show its contents. Your part 
  4395.       should be ready to display itself in the specified frame according to the 
  4396.       frame's view type. 
  4397.  
  4398.      The presentation of the frame tells your part what kind of presentation 
  4399.       (as defined by your own part) its content is to have, if it has frame 
  4400.       view type. If your part does not support the frame's presentation, 
  4401.       substitute a default presentation and call the frame's SetPresentation 
  4402.       method to give it the correct value. 
  4403.  
  4404.      Your part may be within a selection in its containing part. If so, it may 
  4405.       need to be highlighted appropriately for the selection model of the 
  4406.       containing part; see Drawing Selections for more information. You can 
  4407.       call the GetHighlight method of your facet at any time to see whether you 
  4408.       should draw your content with full highlighting, dim (background) 
  4409.       highlighting, or no highlighting. 
  4410.  
  4411.       Alternatively, when your part's HighlightChanged method is called, it can 
  4412.       record the style of highlighting it has been assigned. It can then in 
  4413.       turn call the ChangeHighlight method of all facets embedded in the facet 
  4414.       whose highlight has changed, to make sure that they reflect the same 
  4415.       highlight style. 
  4416.  
  4417.      Check to see if you need to draw borders around any link sources and 
  4418.       destinations in your part's content, as described in Link Borders. 
  4419.  
  4420.      Both the frame and the facet may have information in their part info 
  4421.       fields, placed there by the part itself, that can provide additional 
  4422.       display-related information or objects. Use the GetPartInfo method to 
  4423.       obtain it. 
  4424.  
  4425.      Your part should also be aware of the kind of canvas on which it is being 
  4426.       drawn. You can call the GetCanvas method of the facet to get a reference 
  4427.       to the drawing canvas. 
  4428.  
  4429.         -  If the canvas is dynamic (that is, if the result of calling the 
  4430.            canvas's IsDynamic method is kODTrue), the part is being drawn onto 
  4431.            an interactive device like a video display. Otherwise, it is being 
  4432.            drawn to a static device like a printer (or perhaps a print-preview 
  4433.            image onscreen). Your part may display its content differently in 
  4434.            each case; for instance, it might display scroll bars only on 
  4435.            dynamic canvases, and it might engage in frame negotiation if it is 
  4436.            being drawn on a static canvas. For considerations about static 
  4437.            canvas, see Printing. 
  4438.  
  4439.            Your part can make these adjustments from within its FacetAdded and 
  4440.            CanvasChanged methods. When a facet is added, the static/dynamic 
  4441.            nature of its canvas is fixed and cannot be changed unless the 
  4442.            canvas itself is changed. 
  4443.  
  4444.         -  If the canvas is offscreen (that is, if the result of calling the 
  4445.            canvas's IsOffscreen method is kODTrue), your part might handle the 
  4446.            drawing slightly differently. See Offscreen Drawing. 
  4447.  
  4448.  
  4449. ΓòÉΓòÉΓòÉ 6.3.3. Draw Method of your Part Editor ΓòÉΓòÉΓòÉ
  4450.  
  4451. Your part must be able to display its content in response to a call to its Draw 
  4452. method: 
  4453.  
  4454. void Draw(in ODFacet facet, in ODShape invalidShape);
  4455.  
  4456. When it receives this call, your part editor draws the part content in the 
  4457. given facet. Only the portion within the update shape (defined by the 
  4458. invalidShape parameter) needs to be drawn. The update shape is based on 
  4459. previous Invalidate calls that were made involving this facet or containing 
  4460. facets, or on updating needed because of part activation or window activation. 
  4461. The shape is expressed in the coordinate system of the facet's frame. 
  4462.  
  4463. Your part should take steps such as these to draw itself: 
  4464.  
  4465.    1. Your part must make sure that any required platform-specific graphics 
  4466.       structures are prepared for drawing and that the drawing context for the 
  4467.       facet is set correctly. You must at least do the following: 
  4468.  
  4469.           Obtain a handle to the presentation space to be used for drawing. 
  4470.            You do this by calling the canvas' GetPlatformCanvas method to 
  4471.            obtain the platform canvas object for the canvas and then call the 
  4472.            GetPS method of the platform canvas. 
  4473.  
  4474.           Set the default viewing transform of the presentation space. Call 
  4475.            your facet's AcquireContentTransform method to get the proper 
  4476.            conversion from your part's content coordinates to canvas 
  4477.            coordinates, convert the transform to a MATRIXLF structure and pass 
  4478.            the MATRIXLF structure to the GpiSetDefaultViewingTransform 
  4479.            function. 
  4480.  
  4481.           Set the clip region for drawing your part. Call your facet's 
  4482.            AcquireAggregateClipShape method to transform and intersect your 
  4483.            facet's clip shape with all enclosing clip shapes, resulting in a 
  4484.            composite clip shape in canvas coordinates. Then, transform the 
  4485.            aggregate clip shape to canvas coordinates and call the shape 
  4486.            object's GetRegion method to obtain a GPI region handle. Use this 
  4487.            handle to set the clip region with the GpiSetClipRegion function. 
  4488.  
  4489.            OpenDoc provides a utility library (FocusLib) that facilitates this 
  4490.            step for the OS/2 platform. The source code for FocusLib is provided 
  4491.            with the OpenDoc Programmer's Toolkit. 
  4492.  
  4493.    2. If your part is drawing to an offscreen canvas and has embedded parts, 
  4494.       have the embedded parts draw themselves first; see Updating an Offscreen 
  4495.       Canvas. 
  4496.  
  4497.    3. Your part can then draw its contents, using platform-specific drawing 
  4498.       commands. 
  4499.  
  4500.       Your part can alter the normal order of drawing, perhaps in order to make 
  4501.       overlapping embedded parts and content elements combine to achieve a 
  4502.       specific visual effect. You can force the drawing of a given embedded 
  4503.       part at any point by calling the embedded facet's Draw method. Calling 
  4504.       the embedded facet's DrawChildren method in addition forces the embedded 
  4505.       part's own embedded parts to draw themselves immediately. From within 
  4506.       your parts draw method, you may also call the update method of your 
  4507.       embedded facets, specifying KODNULL for the invalid shape. This will 
  4508.       cause the embedded facet, and any of its embedded facets, and so on, to 
  4509.       be updated as needed based on the current invalid shape. 
  4510.  
  4511.  Note:  Never draw outside of the used shape of your display frame. Your part's 
  4512.         containing part may be wrapping its content to the edges of your used 
  4513.         shape. 
  4514.  
  4515.  
  4516. ΓòÉΓòÉΓòÉ 6.3.3.1. Invalidating and Validating your Content ΓòÉΓòÉΓòÉ
  4517.  
  4518. To mark areas of your part's content that need redrawing, you modify the update 
  4519. shape of the canvas on which your part is imaged. To do so, you call the 
  4520. Invalidate method of your display frames or their facets, passing a shape 
  4521. (invalidShape), expressed in your own frame coordinates, that represents the 
  4522. area that needs to be redrawn. OpenDoc adds that shape to the canvas's update 
  4523. shape, and when redrawing occurs again, that area is included in the 
  4524. invalidShape passed to your Draw method. 
  4525.  
  4526. Likewise, to remove previously invalid areas from the update shape of the 
  4527. canvas, you call the Validate method of your frame or facet, passing a shape 
  4528. (validShape) that represents the area that no longer needs to be redrawn. 
  4529.  
  4530. Validating is not a common task for a part editor to perform; OpenDoc 
  4531. automatically validates all areas that you draw into with your Draw method, and 
  4532. when you draw asynchronously, you automatically validate the areas that you 
  4533. have redrawn when you call the DrawIn method of the facet. 
  4534.  
  4535.  
  4536. ΓòÉΓòÉΓòÉ 6.3.3.2. Drawing on Opening a Window ΓòÉΓòÉΓòÉ
  4537.  
  4538. When a window opens, the facets for all the visible parts of the document are 
  4539. created when the window's Open method is called. The root part's FacetAdded 
  4540. method is called; it builds facets for its embedded frames and invalidates 
  4541. them. OpenDoc, in turn, calls the embedded parts' FacetAdded methods, so that 
  4542. they can build facets for their own embedded parts, and so on. 
  4543.  
  4544. Each part editor whose frame is visible in the window (that is, whose frame has 
  4545. an associated facet) thus receives a call to its Draw method. The method draws 
  4546. the contents of its frame into the facet, by either using privately cached 
  4547. presentations or making standard drawing calls, taking into account the frame's 
  4548. and facet's aggregate transforms and clip shapes. 
  4549.  
  4550.  
  4551. ΓòÉΓòÉΓòÉ 6.3.3.3. Drawing when a Window Is Scrolled ΓòÉΓòÉΓòÉ
  4552.  
  4553. When the entire contents of a window is scrolled, the scrolled position of the 
  4554. contents is determined by the value of the internal transform of the root 
  4555. part's frame. If any of its embedded frames are made newly visible or newly 
  4556. invisible by scrolling, the root part should create or destroy their facets by 
  4557. calling the root facet's CreateEmbeddedFacet or RemoveFacet method, as 
  4558. described in Adding a Facet and Removing a Facet. 
  4559.  
  4560. To force redrawing of those parts of the window that need to be redrawn after 
  4561. scrolling, the root part marks the area that needs to be redrawn as invalid, by 
  4562. calling the root facet's Invalidate method, so that it will be redrawn when an 
  4563. update event occurs. 
  4564.  
  4565.  
  4566. ΓòÉΓòÉΓòÉ 6.3.3.4. Redrawing a Frame when It Changes ΓòÉΓòÉΓòÉ
  4567.  
  4568. If your part changes an embedded frame's shape, you may need to refresh its 
  4569. presentation as follows: 
  4570.  
  4571.    1. Change the frame's shape, as appropriate, by calling ChangeFrameShape. 
  4572.       (OpenDoc then calls the embedded part's FrameShapeChanged method, passing 
  4573.       it the new frame shape). 
  4574.  
  4575.    2. Change the clip shape-and external transform, if necessary-of the frame's 
  4576.       facet to correspond to the new frame shape. 
  4577.  
  4578.    3. If there is an undrawn area outside of the new facet shape, invalidate 
  4579.       the portions of your own intrinsic content that correspond to the 
  4580.       difference between the old and new frame shapes. 
  4581.  
  4582.  When the next update event is generated, the Draw methods of the embedded part 
  4583.  and your part, as appropriate, are called to draw the invalidated areas. 
  4584.  
  4585.  
  4586. ΓòÉΓòÉΓòÉ 6.3.3.5. Drawing when a Part Is Scrolled ΓòÉΓòÉΓòÉ
  4587.  
  4588. When a user scrolls the contents of an embedded part, the containing part takes 
  4589. no role in the repositioning or redrawing. The embedded part sets its frame's 
  4590. internal transform to the appropriate value, as discussed in Scrolling your 
  4591. Part in a Frame, and calls the facet's Invalidate method to force the redraw. 
  4592.  
  4593. If you are the part whose contents are to be scrolled, take these steps: 
  4594.  
  4595.    1. Call your frame's SetInternalTransform method, to set the transform's 
  4596.       offset values appropriately. How you obtain the offset values you pass to 
  4597.       SetInternalTransform depends on what kinds of events you interpret as 
  4598.       scrolling commands and how you handle them. For example, handling events 
  4599.       in scroll bars within your display frames is discussed in Scrolling. 
  4600.  
  4601.    2. If any embedded frames become visible or invisible as a result of the 
  4602.       scrolling, create or delete facets for them as described in Adding a 
  4603.       Facet and Removing a Facet. 
  4604.  
  4605.    3. Call your facet's Invalidate method to force a redraw at the next update 
  4606.       event. You should be able to shift the bits of your frame's image by the 
  4607.       scrolled amount and invalidate only the portion of your facet that 
  4608.       represents part content scrolled into view. 
  4609.  
  4610.  Drawing the contents of frames that include scroll bars is more complicated, 
  4611.  for two reasons. First, the content must be clipped so that it won't draw over 
  4612.  the scroll bars. Second, although the content can be scrolled, the scroll bars 
  4613.  themselves should not move. See Drawing with Scroll Bars for more information. 
  4614.  
  4615.  
  4616. ΓòÉΓòÉΓòÉ 6.3.3.6. Drawing Selections ΓòÉΓòÉΓòÉ
  4617.  
  4618. You determine how selecting works and how selections are drawn inside your 
  4619. parts. 
  4620.  
  4621. When a part embedded within your part is selected, the appearance you give it 
  4622. should be appropriate for your own selection model but it should also reflect 
  4623. whether the part is selected by itself or is part of a larger selection that 
  4624. includes your own part's intrinsic content: 
  4625.  
  4626.      To select an embedded part alone when it is viewed in a frame, the user 
  4627.       can perform several actions, such as activating the part and then 
  4628.       clicking on its frame border or using a lasso tool or other selection 
  4629.       method supported by the containing part. (Your part should support all 
  4630.       selection methods that are appropriate for your content model. Note that 
  4631.       when a frame is selected, its part is not active; the menus displayed are 
  4632.       those of the containing part). 
  4633.  
  4634.       If the part alone is selected, your part (the containing part) should 
  4635.       draw the frame border with a standard appearance-typically a gray line, 
  4636.       corresponding to the frame shape, with resize handles (usually eight of 
  4637.       them) if you permit the user to resize the frame. If you allow 
  4638.       nonrectangular frames (such as irregular polygons or circles), you are 
  4639.       responsible for putting an appropriate number of resize handles on the 
  4640.       frame border. 
  4641.  
  4642.      To select an embedded part alone when it is viewed as an icon, the user 
  4643.       places the mouse pointer over a part's icon (that is, anywhere within the 
  4644.       active shape of the facet displaying the icon) and clicks the mouse 
  4645.       button. Because the view type of the facet is iconic rather than framed, 
  4646.       OpenDoc sends the mouse event to your part. 
  4647.  
  4648.       You should, in this case, not draw the frame border of the embedded part 
  4649.       at all. Instead you should notify the part that it is highlighted by 
  4650.       calling the ChangeHighlight method of the embedded part's facet, 
  4651.       specifying a highlight value of kODFullHighlight. It is then up to the 
  4652.       embedded part to draw its highlighted appearance, either by using a 
  4653.       highlight color or displaying the selected version of its icon. 
  4654.  
  4655.      When an embedded part is enclosed within a range of your selected 
  4656.       intrinsic content, its appearance should be analogous to that of the 
  4657.       intrinsic content itself. You should draw the frame border with a 
  4658.       selected appearance, if appropriate, and you should call the 
  4659.       ChangeHighlight method of the embedded part's facet, so the part will 
  4660.       know how it should highlight itself. 
  4661.  
  4662.         -  If your part highlights selections with a highlight color or inverse 
  4663.            video (as text processors typically do), you should not draw frame 
  4664.            borders around embedded parts within your selection, and you should 
  4665.            set their facets' highlight value to kODFullHighlight. 
  4666.  
  4667.         -  If your part highlights selections by drawing frame borders around 
  4668.            individual objects (as object-based drawing programs typically do), 
  4669.            you should draw frame borders with a selected appearance around any 
  4670.            embedded parts, and you should set their facets' highlight value to 
  4671.            kODNoHighlight. 
  4672.  
  4673.         -  If your part highlights selections by drawing a dynamic marquee or 
  4674.            lasso border around the exact area of the selection (as 
  4675.            bit-map-based drawing programs typically do), you should not draw 
  4676.            frame borders around embedded parts, and you should set their 
  4677.            facets' highlight value to kODNoHighlight. 
  4678.  
  4679.  
  4680.  Your part should allow for multiple selection, so the user can select more 
  4681.  than one frame at a time, and it should also support Select All on its own 
  4682.  contents. Furthermore, it should allow for selection of hot parts-parts such 
  4683.  as controls that normally perform an action (such as running a script) in 
  4684.  response to a single click-without executing the action. 
  4685.  
  4686.  
  4687. ΓòÉΓòÉΓòÉ 6.3.4. Drawing with Scroll Bars ΓòÉΓòÉΓòÉ
  4688.  
  4689. This section discusses two methods for providing scroll bars for your parts. 
  4690. Note that these approaches work not only for scroll bars, but also for any 
  4691. nonscrolling adornments associated with a frame. 
  4692.  
  4693.  
  4694. ΓòÉΓòÉΓòÉ 6.3.4.1. Placing Scroll Bars within your Frame ΓòÉΓòÉΓòÉ
  4695.  
  4696. If you create scroll bars for your content inside the margins of your frame, 
  4697. remember that your frame shape includes the areas of the scroll bars. To draw 
  4698. properly, you need to account for the fact that, although your content can 
  4699. scroll, the scroll bars themselves should remain stationary. 
  4700.  
  4701. Note:  The method discussed in this section does not apply to a root part where 
  4702.        the scroll bars are part of the document shell window frame control and 
  4703.        are not within the root parts display frame. 
  4704.  
  4705.  Clipping and scrolling your content 
  4706.  One approach is to create an extra, private "content shape," as shown in the 
  4707.  following figure. 
  4708.  
  4709.  You can define the content shape in terms of frame coordinates, and you can 
  4710.  store it anywhere, although placing it in your frame's part info data is 
  4711.  reasonable. 
  4712.  
  4713.  When drawing your part's contents-the portion within the area of the content 
  4714.  shape-you take the current scrolled position of your content into account. You 
  4715.  include the frame's internal transform by using the transform returned by 
  4716.  GetContentTransform to set the origin, and you use the content shape as the 
  4717.  facet's clip shape when drawing. If you will draw your own scroll bars, you 
  4718.  ignore the current scrolled position of your content when drawing them. You 
  4719.  use the transform returned by GetFrameTransform to set the default viewing 
  4720.  transform, and you use the frame shape as the facet's clip shape. If you are 
  4721.  using the PM scroll bar control window, you need to position the scroll bar 
  4722.  window using the frame's external transform and set the window clip region, as 
  4723.  described in the recipes Facet Windows and Using Embedded PM Controls within a 
  4724.  Facet. You should call WinUpdateWindow in your Draw method, specifying the 
  4725.  handle of the scroll bar window after drawing your content. 
  4726.  
  4727.  Clipping embedded frames 
  4728.  One complication of this method is that OpenDoc knows nothing of your content 
  4729.  shape and therefore cannot clip the facets of embedded frames accordingly. 
  4730.  OpenDoc clips all embedded facets to the area of your frame's facet, but that 
  4731.  area includes the scroll bars as well. Thus, embedded parts can draw over the 
  4732.  area of your scroll bars. 
  4733.  
  4734.  To avoid this problem, you must intersect the clip shapes of each embedded 
  4735.  facet with your content shape before the facet draws itself. 
  4736.  
  4737.  
  4738. ΓòÉΓòÉΓòÉ 6.3.4.2. Placing Scroll Bars in a Separate Frame ΓòÉΓòÉΓòÉ
  4739.  
  4740. To avoid having to define a separate, private "content shape," you can place 
  4741. scroll bars or adornments in completely separate frames from your content. This 
  4742. method, however, requires the overhead of defining more objects, uses more 
  4743. memory, and may possibly affect performance negatively. 
  4744.  
  4745. You can request one display frame for your part that encloses both the scroll 
  4746. bars and the content. This frame has an internal transform of identity; it does 
  4747. not scroll. If you are drawing your own scroll bars, draw the scroll bars 
  4748. directly in this frame. 
  4749.  
  4750. You then request a second display frame for your part, a frame that can scroll 
  4751. and in which you draw your content. Make the second frame a subframe of the 
  4752. first; that is, make the nonscrolling frame the containing frame of the 
  4753. scrolling frame. Because both frames are display frames of the same part 
  4754. (yours), you must either set the isSubframe parameter to true when you first 
  4755. call RequestEmbeddedFrame to create the new frame, or you must call the 
  4756. SetSubframe method of the new frame after creating it. Either method lets 
  4757. OpenDoc know that the frame is a subframe, so that OpenDoc draws the active 
  4758. frame border in the correct location-around the facet of the parent frame. 
  4759.  
  4760. Your part's containing part, as usual, must make separate facets for both 
  4761. frames. Then, when a mouse event occurs in the nonscrolling frame, your part 
  4762. can interpret it and set the internal transform of the scrolling frame 
  4763. accordingly. 
  4764.  
  4765. With this method, you do not need to take any special care to manage clip 
  4766. shapes of any embedded facets. 
  4767.  
  4768. A more common use of subframes may be in creating scrollable split windows. See 
  4769. Drawing with Multiple Frames or Facets form=normal. 
  4770.  
  4771.  
  4772. ΓòÉΓòÉΓòÉ 6.3.5. Drawing Directly to the Window ΓòÉΓòÉΓòÉ
  4773.  
  4774. If your part editor needs to draw interactively, such as for rubber-banding or 
  4775. for sweeping out a selection while the mouse button is held down to provide 
  4776. user feedback, it can draw directly on the window of the document shell. 
  4777.  
  4778. OpenDoc provides several ODFacet methods, analogous to those used for drawing 
  4779. to your own canvas, that you can use to draw directly to the window: 
  4780.  
  4781.      The AcquireWindowContentTransform method, analogous to 
  4782.       AcquireContentTransform, converts from your part's content coordinate 
  4783.       space to window-canvas coordinate space. 
  4784.  
  4785.      The AcquireWindowFrameTransform method, analogous to 
  4786.       AcquireFrameTransform, converts from your part's frame coordinate space 
  4787.       to window-canvas coordinate space. 
  4788.  
  4789.      The AcquireWindowAggregateClipShape method, analogous to 
  4790.       AcquireAggregateClipShape, transforms and intersects your part's facet 
  4791.       clip shape with all enclosing clip shapes, resulting in a composite clip 
  4792.       shape in window-canvas coordinate space. 
  4793.  
  4794.  Use the values returned by these methods to set up your drawing environment 
  4795.  when you must draw directly to the window canvas. Note that, in cases where 
  4796.  there is no canvas in the facet hierarchy other than the window canvas, the 
  4797.  results returned by each of these pairs of methods are the same. 
  4798.  
  4799.  
  4800. ΓòÉΓòÉΓòÉ 6.3.6. Asynchronous Drawing ΓòÉΓòÉΓòÉ
  4801.  
  4802. Your part editor may need to display its part asynchronously, rather than in 
  4803. response to a call to your Draw method. For example, a part that displays a 
  4804. clock may need to redraw the clock face exactly once every second, regardless 
  4805. of whether an update event has resulted in a call to redraw. Asynchronous 
  4806. drawing is very similar to synchronous drawing, except that you should make 
  4807. these minor modifications: 
  4808.  
  4809.    1. Determine which of your part's frames should be drawn. Your part can have 
  4810.       multiple display frames, and more than one may need updating. Because 
  4811.       your part stores its display frames privately, only you can determine 
  4812.       which frames need to be drawn in. 
  4813.  
  4814.    2. For each frame being displayed, you must draw all facets. The frame's 
  4815.       CreateFrameFacetIterator method returns an iterator with which you can 
  4816.       access all the facets of the frame. (Alternatively, you can keep your own 
  4817.       list of facets). Draw the part's contents in each of these facets, using 
  4818.       the steps listed for synchronous drawing. 
  4819.  
  4820.    3. After drawing in a facet, call its DrawnIn method to tell it that you 
  4821.       have drawn in it asynchronously. If the facet is on an offscreen canvas, 
  4822.       calling DrawnIn allows the drawing to be copied into the window, because 
  4823.       the owning part's CanvasUpdated method gets called. 
  4824.  
  4825.  If your asynchronous drawing needs to apply to embedded parts as well, you can 
  4826.  call your facet's DrawChildrenAlways method, which forces all embedded facets 
  4827.  to redraw themselves, regardless of whether they have been invalidated or not. 
  4828.  
  4829.  
  4830. ΓòÉΓòÉΓòÉ 6.3.7. Offscreen Drawing ΓòÉΓòÉΓòÉ
  4831.  
  4832. There are several situations in which you may want your part to create an 
  4833. offscreen canvas. For example, you may want to increase performance with 
  4834. double-buffering, drawing complex images offscreen before transferring them 
  4835. rapidly to the screen. Alternatively, you may want to perform sophisticated 
  4836. image manipulation, such as drawing with transparency, tinting, or using 
  4837. complex transfer modes. 
  4838.  
  4839. Parts are likely to create offscreen canvases for their own facets for 
  4840. double-buffering, in order to draw with more efficiency and quality. Parts are 
  4841. likely to create offscreen canvases for their embedded parts' facets for 
  4842. graphic manipulation, in order to modify the imaging output of the embedded 
  4843. part and perhaps combine it with their own output. 
  4844.  
  4845. Canvases are described in general in Using Canvases; 
  4846.  
  4847.  
  4848. ΓòÉΓòÉΓòÉ 6.3.7.1. Drawing to an Offscreen Canvas ΓòÉΓòÉΓòÉ
  4849.  
  4850. Drawing on an offscreen canvas is essentially the same as drawing on an 
  4851. onscreen canvas, in these ways: 
  4852.  
  4853.      You set up the environment as usual: you obtain the canvas and its 
  4854.       pointer to the ODPlatformCanvas object, from which you obtain the 
  4855.       presentation space. You use your facet's transform and clip information 
  4856.       as usual. 
  4857.  
  4858.      If you draw asynchronously on your facet's offscreen canvas, you must, as 
  4859.       usual, call the facet's DrawnIn method to ensure proper updating of the 
  4860.       offscreen canvas to the window canvas. If your part's facet is moved to 
  4861.       an offscreen canvas while it is running, OpenDoc calls your part's 
  4862.       CanvasChanged method, so that your part will know to call DrawnIn if it 
  4863.       is drawing asynchronously. 
  4864.  
  4865.      You perform invalidation the same way for onscreen and offscreen 
  4866.       canvases. 
  4867.  Call the Invalidate or Validate methods of your display frames and their 
  4868.  facets, to accumulate the invalid area in the update shape of the offscreen 
  4869.  canvas. 
  4870.  
  4871.  If you want to bypass the offscreen canvas and draw directly to the document 
  4872.  shell window, make sure you obtain the window canvas when setting up the 
  4873.  environment. Then use the appropriate facet calls (such as 
  4874.  AcquireWindowContentTransform instead of AcquireContentTransform) when setting 
  4875.  the default viewing transform and clip region. 
  4876.  
  4877.  
  4878. ΓòÉΓòÉΓòÉ 6.3.7.2. Updating an Offscreen Canvas ΓòÉΓòÉΓòÉ
  4879.  
  4880. The part that owns an offscreen canvas is responsible for transferring its 
  4881. contents to the parent canvas. Only the part that created the canvas can be 
  4882. assumed to know how and when to transfer its contents. The canvas may have a 
  4883. different format from its parent (one may be a bit map and the other a display 
  4884. list, for example); the owner may want to transform the contents of the canvas 
  4885. (such as by rotation or tinting) as it transfers, or the owner may want to 
  4886. accumulate multiple drawing actions before transferring. 
  4887.  
  4888. When a containing part has placed one of its embedded part's facets on an 
  4889. offscreen canvas, it should force the embedded part to draw before the 
  4890. containing part itself draws any of its own contents. This ensures that the 
  4891. contents of the offscreen canvas are up to date, and can be combined safely 
  4892. with the containing part's contents when drawn to the onscreen canvas. You can 
  4893. force your embedded part to draw itself by calling the embedded facet's Draw 
  4894. method; you can force your embedded part's own embedded parts to draw 
  4895. themselves by also calling your embedded facet's DrawChildren method. 
  4896.  
  4897. If an embedded part displays asynchronously and uses Invalidate or Validate 
  4898. calls to modify the update shape of its offscreen canvas, the offscreen canvas 
  4899. calls its owning part's CanvasUpdated method to notify it of the change. The 
  4900. owning part can then transfer the updated content immediately to the parent 
  4901. canvas, or it can defer the transfer until a later time, for efficiency or for 
  4902. other reasons. 
  4903.  
  4904.  
  4905. ΓòÉΓòÉΓòÉ 6.3.8. Drawing with Multiple Frames or Facets ΓòÉΓòÉΓòÉ
  4906.  
  4907. OpenDoc has built-in support for multiple display frames for every part and 
  4908. multiple facets for every frame. This arrangement gives you great flexibility 
  4909. in designing the presentation of your part and of parts embedded in it. This 
  4910. section summarizes a few common reasons for implementing multiple frames or 
  4911. multiple facets. 
  4912.  
  4913.  
  4914. ΓòÉΓòÉΓòÉ 6.3.8.1. Using Multiple Frames ΓòÉΓòÉΓòÉ
  4915.  
  4916. Several uses for multiple frames have already been noted in this book, most of 
  4917. which involve the need for simultaneous display of different aspects or 
  4918. portions of a part's content. 
  4919.  
  4920.      A part whose frame is opened into a part window requires a second frame 
  4921.       as the root frame of that part window. 
  4922.  
  4923.      A part that flows text from one frame to another naturally needs more 
  4924.       than one frame. 
  4925.  
  4926.      Parts that allow for multiple different presentations of their content 
  4927.       are likely to display each kind of presentation (top view versus side 
  4928.       view, wire-frame versus rendered, and so on) in a separate frame. 
  4929.  
  4930.      Parts that display scroll bars, adornments, or palettes in addition to 
  4931.       their own content might use separate frames for such items. 
  4932.  
  4933.  In general, the part that is displayed in a set of frames initiates the use of 
  4934.  multiple frames. The containing part does, however, have ultimate control over 
  4935.  the number and size of frames for its embedded parts. 
  4936.  
  4937.  
  4938. ΓòÉΓòÉΓòÉ 6.3.8.2. Using Multiple Facets ΓòÉΓòÉΓòÉ
  4939.  
  4940. The use of multiple facets allows a containing part to duplicate, distort, and 
  4941. reposition the content displayed in its embedded frames. Normally, even with 
  4942. multiple facets, all of the facets of a frame display their content within the 
  4943. area of the frame shape, because the frame represents the basic space agreement 
  4944. between the embedded part and the containing part. However, the containing part 
  4945. always controls the facets to be applied to its embedded frames, and so the 
  4946. containing part can display the facets in any locations it wishes. 
  4947.  
  4948.  
  4949. ΓòÉΓòÉΓòÉ 6.3.8.2.1. Drawing an Embedded Frame Across Two Display Frames ΓòÉΓòÉΓòÉ
  4950.  
  4951.  
  4952. Perhaps the most common reason to use multiple facets for a frame is to show an 
  4953. embedded frame spanning a visual boundary between separate drawing areas in a 
  4954. containing frame. 
  4955.  
  4956. In the following figure, for example, a word-processing part uses a single 
  4957. display frame and facet for each of its pages. An embedded part's display frame 
  4958. spans the boundary between page 1 and page 2. The word-processing part then 
  4959. defines two facets for its embedded frame: one facet in the display for page 1, 
  4960. and the other in the display for page 2. 
  4961.  
  4962.  
  4963. ΓòÉΓòÉΓòÉ 6.3.8.2.2. Multiple Views of an Embedded Frame ΓòÉΓòÉΓòÉ
  4964.  
  4965.  
  4966. One simple use of multiple facets is for a containing part to provide a 
  4967. modified view (such as a magnification) in addition to the standard view of an 
  4968. embedded frame. You can also use multiple facets to tile the area of an 
  4969. embedded frame with multiple miniature images of the frame's contents. 
  4970.  
  4971. A similar but more complex example is shown in the following figure. In this 
  4972. case, multiple facets are used to break up the image in an embedded frame, to 
  4973. allow the tiled parts to be moved, as in a sliding puzzle. 
  4974.  
  4975. The clip shapes for the facets in the preceding figure are smaller than the 
  4976. frame shape and have offset origins so that they cover different portions of 
  4977. the image in the frame. Initially, as shown on the left, their external 
  4978. transforms have offsets that reflect the offsets in the shape definitions, and 
  4979. the facets just fill the area of the frame. Subsequently, as shown on the 
  4980. right, the containing part can cause any pair of facets to change places in the 
  4981. frame simply by swapping their external transforms. 
  4982.  
  4983.  
  4984. ΓòÉΓòÉΓòÉ 6.3.8.2.3. Providing Split-Frame Views ΓòÉΓòÉΓòÉ
  4985.  
  4986.  
  4987. One of the most useful implementations of multiple facets may be for the 
  4988. construction of split-frame views, in which the user can independently view and 
  4989. scroll two or more portions of a single document. This use of multiple facets 
  4990. is somewhat more complex than the others presented here, because it also 
  4991. involves use of subframes, embedded frames that display the same part as their 
  4992. containing frame. The following figure shows one example of how to use two 
  4993. subframes to implement a split-frame view. 
  4994.  
  4995. In the preceding figure, the part to be displayed has one frame (frame 1) and 
  4996. facet (facet 1) that represent its current overall frame size and display. The 
  4997. part creates frames 2 and 3 as embedded frames, specifying that the containing 
  4998. frame for both is frame 1, and also specifying that they are to be subframes of 
  4999. their containing frame. (Alternatively the part can call the frames' 
  5000. SetSubframe method to make them subframes). The diagram in the lower right of 
  5001. shows the object relationships involved, using the object-diagram conventions 
  5002. described in Run-Time Object Relationships. 
  5003.  
  5004. The part now needs to negotiate for frames 2 and 3 only with itself. It creates 
  5005. facets for them, embedded within facet 1. The part can now position the 
  5006. contents of frame 2 and frame 3 independently, by changing their external 
  5007. tranforms. It uses the external transforms to place facets 2 and 3 within 
  5008. facet1 as shown, and the two facets together fill the area of frame 1 and show 
  5009. different parts of the document. 
  5010.  
  5011. You can also achieve a split-frame view with a somewhat simpler method that 
  5012. does not require the use of subframes. In this case, your part must perform 
  5013. extra work to split its content display. The method relies on multiple facets 
  5014. only for duplicate display of embedded parts; as the following figure shows, 
  5015. your part has only a single display frame and facet. 
  5016.  
  5017. You create two facets (subfacets of your display frame's facet) for each 
  5018. embedded part that is visible in both halves of the split view. By your own 
  5019. means, you separate the display of your part's intrinsic content and, at the 
  5020. same time, you apply the appropriate external transforms to each embedded facet 
  5021. so that embedded parts appear in their proper locations in each portion of your 
  5022. split view. (The diagram in the lower right of the preceding figure shows the 
  5023. object relationships). 
  5024.  
  5025.  
  5026. ΓòÉΓòÉΓòÉ 6.4. Printing ΓòÉΓòÉΓòÉ
  5027.  
  5028. To print a document, the user selects Print from the Document menu, and the 
  5029. root part displays a print dialog box (see Print document). If the user 
  5030. confirms the print command, the root part then sets up the environment for 
  5031. printing and prints the document. 
  5032.  
  5033. In printing, the printer is represented by a separate canvas object from the 
  5034. screen display, although part editors in general use normal drawing calls to 
  5035. print their content. 
  5036.  
  5037. Because any part can be the root part of a document, all parts should in 
  5038. general support the printing commands. The root part has greater responsibility 
  5039. in printing, but all visible embedded parts are asked to draw themselves, and 
  5040. they can adjust their drawing process for the presence of a static canvas. They 
  5041. can also directly access the platform-specific printing structure, if 
  5042. necessary. 
  5043.  
  5044. Page setup 
  5045. When your part is the root part, it also handles the Page Setup command. 
  5046.  
  5047. OpenDoc does not replace a platform's printing interface; OpenDoc objects 
  5048. provide access to platform-specific structures and provide a context in which 
  5049. you make platform-specific calls. 
  5050.  
  5051. This section first discusses the specific printing responsibilities of the root 
  5052. part, then addresses those of embedded parts, and finally notes aspects of 
  5053. printing that apply to all parts. 
  5054.  
  5055.  
  5056. ΓòÉΓòÉΓòÉ 6.4.1. Root-Part Responsibilities ΓòÉΓòÉΓòÉ
  5057.  
  5058. If your part is the root part, it defines the basic printing behavior of its 
  5059. document. It sets things up, makes the platform-specific printing calls, and 
  5060. performs any frame negotiation that is to occur. 
  5061.  
  5062.  
  5063. ΓòÉΓòÉΓòÉ 6.4.1.1. Using the Same Frame for Printing as for Drawing ΓòÉΓòÉΓòÉ
  5064.  
  5065. If your part's document uses the same page layout for printing as for screen 
  5066. display, printing is simpler. You use your part's existing display frame (the 
  5067. window's root frame) as the frame for printing. That way, you need not create 
  5068. any new frames, including embedded frames. Using your existing display frame 
  5069. makes most sense in situations where you do not engage in frame negotiation, 
  5070. because you can reuse the same layout after printing. 
  5071.  
  5072.  
  5073. ΓòÉΓòÉΓòÉ 6.4.1.2. Using a Separate Printing Frame ΓòÉΓòÉΓòÉ
  5074.  
  5075. For greater flexibility, you may want to allow the printed version of your 
  5076. document to have a somewhat different layout from the onscreen version. For 
  5077. example, you may want to give embedded parts a chance to remove scroll bars and 
  5078. resize their frames or otherwise lay themselves out differently. To do that, 
  5079. and to retain your original layout for post-printing display, you can create a 
  5080. separate display frame for printing, as described next. 
  5081.  
  5082.  
  5083. ΓòÉΓòÉΓòÉ 6.4.1.3. Printing the Document ΓòÉΓòÉΓòÉ
  5084.  
  5085. After you have followed the steps listed in Print document, and after the user 
  5086. has confirmed the print dialog, your part is ready to print its document. It is 
  5087. assumed that you have created a platform-specific printing structure, such as a 
  5088. presentation space associated with a printer device context on OS/2. You should 
  5089. then take these general steps: 
  5090.  
  5091.    1. If you do not change layout or support frame negotiation for printing, 
  5092.       skip this step and use your current display frame as the printing frame. 
  5093.       Otherwise, create a separate printing frame, like this: 
  5094.  
  5095.           Call your draft's CreateFrame method to create a new, nonpersistent 
  5096.            frame as a display frame for your part, to be used as the printing 
  5097.            frame. 
  5098.  
  5099.           Also create new frames for each of your part's embedded parts, with 
  5100.            the printing frame as their containing frame. 
  5101.  
  5102.    2. Create an external transform and clip shape for your printing facet. Make 
  5103.       the clip shape equal to your page size. 
  5104.  
  5105.    3. Create a new facet for the printing frame, using the window state 
  5106.       object's CreateFacet method. Assign the transform and clip to the 
  5107.       printing facet. 
  5108.  
  5109.    4. Create a platform canvas object using the facet's CreatePlatformCanvas 
  5110.       method, and specify the printer presentation space. 
  5111.  
  5112.    5. Create a static canvas with the printing facet's CreateCanvas method. Use 
  5113.       the SetPlatformCanvas method to assign the platform canvas object to the 
  5114.       canvas. Create and initialize a PRINTDEST structure, and use the 
  5115.       SetPlatformPrintJob method to assign the printing structure itself to the 
  5116.       canvas. 
  5117.  
  5118.    6. Assign the canvas to the printing facet by calling the facet's 
  5119.       ChangeCanvas method. Notify the printing frame of the presence of the 
  5120.       printing facet by calling its FacetAdded method. 
  5121.  
  5122.       (If you have not created a separate printing frame, each of your embedded 
  5123.       parts with a facet is at this point notified of the presence of a static 
  5124.       canvas and may attempt frame negotiation. As root part, you may permit or 
  5125.       deny the requests). 
  5126.  
  5127.    7. Loop through all pages in your part's content area (or the page range 
  5128.       specified in the job dialog box), and print each one. For each page, do 
  5129.       the following: 
  5130.  
  5131.           Reset your printing facet's clip shape and/or transform so that it 
  5132.            covers this page. 
  5133.  
  5134.           Create facets for your newly visible embedded frames, and release 
  5135.            facets for frames no longer in view. At this point, allow frame 
  5136.            negotiation with your part's embedded parts if you support 
  5137.            negotiation. 
  5138.  
  5139.           Invalidate the printing facet's area and force a redrawing, by 
  5140.            calling the facet's Update method. 
  5141.  
  5142.    8. When finished printing, clean up. Remove the printing facet from the 
  5143.       printing frame and release it. Delete the platform-specific structures 
  5144.       (such as the print job) and the platform canvas object that you have 
  5145.       created. If you have created a printing frame, remove it by calling its 
  5146.       Remove method. 
  5147.  
  5148.  
  5149. ΓòÉΓòÉΓòÉ 6.4.2. Embedded-Part Responsibilities ΓòÉΓòÉΓòÉ
  5150.  
  5151. Embedded parts have these few specific responsibilities in printing. 
  5152.  
  5153.  
  5154. ΓòÉΓòÉΓòÉ 6.4.2.1. Engaging in Frame Negotiation ΓòÉΓòÉΓòÉ
  5155.  
  5156. Your part must handle printing properly when it is an embedded part and is 
  5157. assigned a new display frame or facet. It should examine the facet's associated 
  5158. canvas to determine whether it is dynamic or static and perform frame 
  5159. negotiation if appropriate. On a static canvas, you might engage in a frame 
  5160. negotiation to make all of your part's content visible, or you might need to 
  5161. resize your frame to account for elimination of scroll bars or other items that 
  5162. are appropriate for screen display only. 
  5163.  
  5164. The best point at which to test for the presence of a static canvas is when 
  5165. your facet is added or when its canvas changes, not when your Draw method is 
  5166. called. At drawing time it is too late to engage in frame negotiation. 
  5167.  
  5168.  
  5169. ΓòÉΓòÉΓòÉ 6.4.2.2. Responding to GetPrintResolution ΓòÉΓòÉΓòÉ
  5170.  
  5171. Your part may receive a call to its GetPrintResolution method as a printing job 
  5172. is being set up. This is its interface: 
  5173.  
  5174. ODULong GetPrintResolution(in ODFrame frame);
  5175.  
  5176. Your GetPrintResolution method should first call the GetPrintResolution method 
  5177. of any of its own embedded parts that would be visible within the specified 
  5178. frame. It should then return the highest of all returned values and your own 
  5179. part's minimum printing resolution (in dots per inch) as the method result. 
  5180.  
  5181. On OS/2, the print resolution for a print job cannot be set programmatically; 
  5182. however, a part that is initiating the print job might try to query the 
  5183. resolution of available printers to find one that is satisfactory. 
  5184.  
  5185.  
  5186. ΓòÉΓòÉΓòÉ 6.4.3. Issues for All Parts ΓòÉΓòÉΓòÉ
  5187.  
  5188. Your part draws to the printer canvas just as it draws to its window canvas. 
  5189. Your Draw method is called when the facet that displays your part is being 
  5190. imaged. 
  5191.  
  5192. When your part draws to a static canvas (use the IsDynamic method of the canvas 
  5193. to find out), you may not want to draw adornments and interactive features such 
  5194. as scroll bars that are appropriate for screen display only. 
  5195.  
  5196. On a static canvas, you may also want to perform color matching to take into 
  5197. account the characteristics of the device on which you are drawing. 
  5198.  
  5199. Note that all printing canvases are static, but not all static canvases are for 
  5200. printing. The presence of a static canvas does not guarantee that a print job 
  5201. or job object exists. You can call the HasPlatformPrintJob method of the canvas 
  5202. to find out if a printing structure exists. If it does, it is available through 
  5203. the GetPlatformPrintJob method of the printing canvas. You might want to access 
  5204. the print job or job object directly to determine, for example, whether you are 
  5205. printing on a PostScript printer. 
  5206.  
  5207.  
  5208. ΓòÉΓòÉΓòÉ 7. User Events ΓòÉΓòÉΓòÉ
  5209.  
  5210. This is the third of eight chapters that discuss the OpenDoc programming 
  5211. interface in detail. This chapter describes the OpenDoc event-handling 
  5212. mechanism and discusses how your part editor handles user events to activate 
  5213. itself and to manipulate its user interface. 
  5214.  
  5215. It is by handling user events that your part editor interacts with the user and 
  5216. cooperates with the user in constructing the compound documents that contain 
  5217. your parts. 
  5218.  
  5219. OpenDoc distinguishes user events from semantic events, the messages related to 
  5220. the OpenDoc scripting extension, although user events can be converted into 
  5221. semantic events. Semantic events are discussed in Semantic Events and 
  5222. Scripting. 
  5223.  
  5224. Before reading this chapter, you should be familiar with the concepts presented 
  5225. in Introduction and Development Overview. For additional concepts related to 
  5226. your part editor's run-time environment, see OpenDoc Run-Time Features. 
  5227.  
  5228. This chapter starts with a discussion of what user events are, and then shows 
  5229. how your part can 
  5230.  
  5231.      Handle mouse events to activate itself 
  5232.      Transfer various types of focus to and from itself 
  5233.      Handle display-related events, for purposes such as hit-testing and 
  5234.       scrolling 
  5235.  
  5236.  
  5237. ΓòÉΓòÉΓòÉ 7.1. About Event Handling in OpenDoc ΓòÉΓòÉΓòÉ
  5238.  
  5239. Your OpenDoc part editor is required to respond to a specific set of actions or 
  5240. messages from OpenDoc that constitute the majority of user interactions with 
  5241. your parts. In OpenDoc, these messages are called user events. 
  5242.  
  5243. User events in OpenDoc include mouse clicks and keystrokes, menu commands, 
  5244. activation and deactivation of windows, and other events available on only some 
  5245. platforms. This section defines the different types of events and discusses how 
  5246. your part editor's HandleEvent method handles them. 
  5247.  
  5248.  
  5249. ΓòÉΓòÉΓòÉ 7.1.1. How User Events Are Handled ΓòÉΓòÉΓòÉ
  5250.  
  5251. Certain user events are handled by the dispatcher. The dispatcher accepts the 
  5252. user events from the underlying operating system through the document shell and 
  5253. dispatches them to the part editors. The dispatching system is modular and can 
  5254. be extended to handle new classes of events by adding a dispatch module. Each 
  5255. dispatch module is responsible for deciding which frame or part should be asked 
  5256. to handle each event that the module deals with. 
  5257.  
  5258. When the OpenDoc dispatcher receives an event intended for your part, it 
  5259. locates a dispatch module for the event.  The dispatch module in turn calls 
  5260. your part's HandleEvent method. (Your part's Draw method can be called 
  5261. indirectly because of an event, through the Update method of a window or 
  5262. facet). 
  5263.  
  5264. Your part becomes the target for a specific type of user event (other than 
  5265. geometry-based events) by obtaining the focus for that event. The OpenDoc 
  5266. arbitrator keeps track of which part owns which foci by consulting a focus 
  5267. module, which tracks, for example, which part is currently active and therefore 
  5268. should receive keyboard events. Foci and focus modules are described further in 
  5269. Focus Types. 
  5270.  
  5271. Geometry-based events, such as mouse clicks, are generally dispatched to the 
  5272. parts within which they occur regardless of which part currently has the 
  5273. selection focus-that is, regardless of which part is currently active. This 
  5274. permits inside-out activation to occur. 
  5275.  
  5276. Your part receives some of the information about its events in the ODEventData 
  5277. structure. This structure is described in OpenDoc for OS/2 Programming 
  5278. Reference. 
  5279.  
  5280. Other information about the event is passed to your part in an OpenDoc-defined 
  5281. event-info structure: 
  5282.  
  5283. For any geometry-based event (mouse event) that is passed to your part, the 
  5284. coordinates of the event are passed in the where field of the structure. For 
  5285. events in embedded frames that are passed to your part, the frame and facet 
  5286. within which the event occurred are passed in the embeddedFrame and 
  5287. embeddedFacet fields. 
  5288.  
  5289.  
  5290. ΓòÉΓòÉΓòÉ 7.1.2. Types of User Events ΓòÉΓòÉΓòÉ
  5291.  
  5292. Your parts must, in general, handle the following types of user events: 
  5293.  
  5294.      Mouse events 
  5295.      Mouse events in embedded frames 
  5296.      Keyboard events 
  5297.      Menu events 
  5298.      Window events 
  5299.      Activate events 
  5300.      Update events 
  5301.      Null events 
  5302.      Other events 
  5303.  
  5304.  The following sections describe how you handle each of these kinds of events. 
  5305.  
  5306.  
  5307. ΓòÉΓòÉΓòÉ 7.1.2.1. Mouse Events ΓòÉΓòÉΓòÉ
  5308.  
  5309. When the user presses or releases the mouse button while the mouse pointer is 
  5310. in the content area of an OpenDoc window, the dispatcher finds the correct part 
  5311. to handle the mouse event by traversing the hierarchy of facets in the window. 
  5312.  
  5313. The dispatcher searches depth-first (trying the most deeply embedded facets 
  5314. first) and front-to-back (trying the front-most of sibling facets first). The 
  5315. dispatcher sends the event to the editor of the first-that is, most deeply 
  5316. embedded and front-most frame it finds whose active shape contains the pointer 
  5317. position. In this way, the smallest enclosing frame surrounding the pointer 
  5318. location receives the mouse event, preserving the OpenDoc inside-out activation 
  5319. model. None of the part editors of any containing parts in that frame's 
  5320. embedding hierarchy are involved in handling the event. 
  5321.  
  5322. When the user presses a mouse button while the pointer is within a facet of 
  5323. your part, the dispatcher calls your part's HandleEvent method, passing it an 
  5324. event containing the mouse message. 
  5325.  
  5326. When the user releases the mouse button while the pointer is within your facet, 
  5327. the dispatcher again calls your part's HandleEvent method, passing the mouse 
  5328. message. 
  5329.  
  5330. The event-dispatching code does not itself activate and deactivate the relevant 
  5331. parts; it is up to the editor of the part receiving the mouse event to decide 
  5332. whether to activate itself or not. See Mouse Events, Activation, and Dragging 
  5333. for information on how your part should handle mouse-down and mouse-up events 
  5334. within its facets for the purposes of part activation, window activation, and 
  5335. drag-and-drop. 
  5336.  
  5337. The dispatcher also tracks pointer position at all times when the mouse button 
  5338. is not pressed. 
  5339.  
  5340.      When the pointer enters a facet of your part, moves within your facet or 
  5341.       leaves your facet, the dispatcher calls your part's HandleEvent method, 
  5342.       passing a WM_MOUSEMOVE event. 
  5343.  
  5344.  You can use these events to, for example, change the cursor appearance. See 
  5345.  Handling Mouse Events. 
  5346.  
  5347.  In some situations, OpenDoc redirects or changes mouse events: 
  5348.  
  5349.      If the user holds down the Shift key, Alt key or Ctrl key while pressing 
  5350.       or releasing the mouse button, the dispatcher instead sends the event to 
  5351.       the frame with the selection focus. This allows users to extend 
  5352.       selections by Shift-clicking or Command-clicking. 
  5353.  
  5354.      If the mouse event is in the title bar or re-size box of a window, the 
  5355.       dispatcher converts it to a window event. 
  5356.  
  5357.      If the mouse event is in the menu bar, the dispatcher converts it to a 
  5358.       menu event. 
  5359.  
  5360.      If a frame has the modal focus (see Acquiring and Relinquishing the Modal 
  5361.       Focus), mouse events that occur outside of its border are sent to it. 
  5362.       However, mouse events that occur within frames embedded within the frame 
  5363.       with the modal focus are sent to the embedded frames, as expected. 
  5364.  
  5365.  Mouse clicks within controls associated with your part can be handled in a 
  5366.  number of ways, as discussed in Controls. 
  5367.  
  5368.  
  5369. ΓòÉΓòÉΓòÉ 7.1.2.2. Mouse Events in Embedded Frames ΓòÉΓòÉΓòÉ
  5370.  
  5371. If your part contains embedded frames, the dispatcher can also send you special 
  5372. mouse events that occur within and on the borders of the embedded frames' 
  5373. facets. 
  5374.  
  5375. The following events occur when your part's frame is the active frame and the 
  5376. embedded frame is selected, bundled, or in icon view type, or if the user 
  5377. Shift-clicks or Ctrl-clicks or Alt-clicks in the embedded frame to extend a 
  5378. selection: 
  5379.  
  5380.      When the user presses a mouse button while the pointer is within a facet 
  5381.       of the embedded frame, the dispatcher calls your part's HandleEvent 
  5382.       method, passing it an event type of kODEvtMouseDownEmbedded. 
  5383.  
  5384.      When the user releases a mouse button while the pointer is within the 
  5385.       embedded facet, the dispatcher again calls your part's HandleEvent 
  5386.       method, this time passing it an event type of kODEvtMouseUpEmbedded. 
  5387.  
  5388.       Your part does not receive the mouse-up event if the user clicks in a 
  5389.       selected embedded frame. If the user initiates a drag operation, the 
  5390.       mouse-up event is not sent; instead, it is converted to a drop operation. 
  5391.       If the user does not initiate a drag, the mouse-up event is sent to the 
  5392.       embedded frame so that the embedded part can activate itself. See Mouse 
  5393.       Events, Activation, and Dragging for more information, including how to 
  5394.       handle events in a background process. 
  5395.  The following event occurs when the frame embedded within your part is the 
  5396.  active frame: 
  5397.  
  5398.      When the user presses the mouse button while the pointer is within the 
  5399.       active border of a facet of the embedded frame, the dispatcher calls your 
  5400.       part's HandleEvent method, passing it an event type of 
  5401.       kODEvtMouseDownBorder. 
  5402.  
  5403.  These events allow your part to activate itself and select or drag the 
  5404.  embedded part. 
  5405.  
  5406.  
  5407. ΓòÉΓòÉΓòÉ 7.1.2.3. Keystroke Events ΓòÉΓòÉΓòÉ
  5408.  
  5409. When the user presses a key on the keyboard and your part has the keyboard 
  5410. focus, the dispatcher calls your part's HandleEvent method, passing it an event 
  5411. type of kODEvtKeyDown. When the user releases the key, the dispatcher again 
  5412. calls your part's HandleEvent method, this time passing it an event type of 
  5413. kODEvtKeyUp. 
  5414.  
  5415. Exceptions to this convention include keystrokes that are keyboard equivalents 
  5416. to menu commands when the menu has the focus, which go to your part as menu 
  5417. events, and keystroke events involving the Page Up, Page Down, Home and End 
  5418. keys, which go to the frame-if any-that has the scrolling focus. 
  5419.  
  5420.  
  5421. ΓòÉΓòÉΓòÉ 7.1.2.4. Menu Events ΓòÉΓòÉΓòÉ
  5422.  
  5423. If the user presses the mouse button when the mouse pointer is within the menu 
  5424. bar, or if the user enters a keyboard equivalent to that action, the OpenDoc 
  5425. converts the mouse-down or keystroke event into a menu event of type kODEvtMenu 
  5426. and calls the HandleEvent method of the part with the menu focus. 
  5427.  
  5428. On the OS/2 platform, the message field of the event structure passed to 
  5429. HandleEvent contains WM_COMMAND. Processing of the WM_COMMAND message for menu 
  5430. events is handled the same as for a PM application window procedure. 
  5431.  
  5432. For a description of the HandleEvent method, see the OpenDoc for OS/2 
  5433. Programming Reference. Handling individual menu commands is discussed in Menus. 
  5434.  
  5435.  
  5436. ΓòÉΓòÉΓòÉ 7.1.2.5. Window Events ΓòÉΓòÉΓòÉ
  5437.  
  5438. If the user presses the mouse button while the pointer is within a non-content 
  5439. position of the window (such as the close icon in the window), or if the user 
  5440. enters a keyboard equivalent to that action, OpenDoc converts the mouse-down or 
  5441. keystroke event into an event of type kODEvtWindow and the document shell 
  5442. handles the event. 
  5443.  
  5444. How to handle window events when your part is the root part is described in 
  5445. Handling Window Events. 
  5446.  
  5447.  
  5448. ΓòÉΓòÉΓòÉ 7.1.2.6. Activate Events ΓòÉΓòÉΓòÉ
  5449.  
  5450. On platforms that support activation and deactivation of windows, OpenDoc sends 
  5451. activate events and deactivate events, of type kODEvtActivate, to each facet in 
  5452. the window when the window changes state. 
  5453.  
  5454. If the user clicks in the title bar of an inactive window, OpenDoc activates 
  5455. the window and brings it to the front. If the user clicks in the content area 
  5456. of an inactive window, the part at the click location brings the window to the 
  5457. front. Either way, when an active window becomes inactive because another 
  5458. window has become active, each facet of each part displayed in the window being 
  5459. deactivated receives a deactivate event, and each facet of each part displayed 
  5460. in the window being activated receives an activate event. 
  5461.  
  5462. Your part's HandleEvent method can use these events to store and retrieve 
  5463. information with which it can decide whether or not to activate itself when its 
  5464. window becomes active; see Handling Activate Events for an explanation. 
  5465.  
  5466.  
  5467. ΓòÉΓòÉΓòÉ 7.1.2.7. Update Events ΓòÉΓòÉΓòÉ
  5468.  
  5469. To support redrawing of previously invalidated areas of a window, frame, or 
  5470. facet, OpenDoc handles update events and calls the Draw methods of the 
  5471. appropriate parts. 
  5472.  
  5473. Update events are themselves triggered by the existence of invalid areas, 
  5474. created through changes to the content of parts, the activation of windows, or 
  5475. the removal of obscuring objects such as floating windows. 
  5476.  
  5477. OpenDoc does not pass update events to your HandleEvent method. When an update 
  5478. event occurs that involves a facet of your part, the dispatcher calls the 
  5479. Update method of the window, which results in a call to your Draw method. For 
  5480. more information, see Invalidating and Updating. 
  5481.  
  5482.  
  5483. ΓòÉΓòÉΓòÉ 7.1.3. Propagating Events ΓòÉΓòÉΓòÉ
  5484.  
  5485. A containing part can set a flag in an embedded frame that allows the 
  5486. containing part to receive events not handled by the embedded frame. If your 
  5487. part contains embedded frames with that flag set, your HandleEvent method 
  5488. receives the events originally sent to them. OpenDoc sets the propagated field 
  5489. in the EventInfo structure to true when it passes a propagated event to your 
  5490. part. 
  5491.  
  5492. Whenever you add a facet to a frame, you can check the state of the flag by 
  5493. calling the frame's DoesPropagateEvents method. You can then set or clear the 
  5494. flag by calling the frame's SetPropagateEvents method. 
  5495.  
  5496. This is a specialized feature of OpenDoc, not likely to be used by most part 
  5497. editors. You might possibly use it for purposes such as manipulating embedded 
  5498. selections; for example, you could use tab-key events to allow the user to tab 
  5499. between embedded parts that do not themselves support tabbing. 
  5500.  
  5501. If you do not set the event-propagating flag for any of your embedded frames, 
  5502. your HandleEvent method receives only those embedded-frame events described in 
  5503. Mouse Events in Embedded Frames. 
  5504.  
  5505.  
  5506. ΓòÉΓòÉΓòÉ 7.1.4. HandleEvent Method of your Part Editor ΓòÉΓòÉΓòÉ
  5507.  
  5508. The dispatcher calls your part's HandleEvent method to pass it a user event 
  5509. meant for your part. This is the interface to the method: 
  5510.  
  5511. ODBoolean HandleEvent(inout ODEventData event,
  5512.                       in ODFrame frame,
  5513.                       in ODFacet facet),
  5514.                       inout ODEventInfo eventInfo);
  5515.  
  5516. Your implementation of HandleEvent might be similar to this: 
  5517.  
  5518.    1. Initialize the result flag to kODFalse. 
  5519.  
  5520.    2. Obtain the part info data from the frame or facet to which the event was 
  5521.       directed, if you have stored relevant information there. 
  5522.  
  5523.    3. Execute a switch statement with one case for each event type. Pass 
  5524.       execution to the appropriate handler for each event type. Set the result 
  5525.       flag to kODTrue if an individual handler handles the event. 
  5526.  
  5527.    4. Return the result flag as the method result. 
  5528.  
  5529.  Your individual event handlers should function as described in other sections 
  5530.  of this chapter. Each should return kODTrue to HandleEvent if it handles an 
  5531.  event, and kODFalse if it does not. 
  5532.  
  5533.  
  5534. ΓòÉΓòÉΓòÉ 7.2. Mouse Events, Activation, and Dragging ΓòÉΓòÉΓòÉ
  5535.  
  5536. This section discusses how your part should respond to mouse-down, mouse-up, 
  5537. and activate events in order to activate your part or your window, initiate a 
  5538. dragging operation, or create a single-click selection. Your HandleEvent method 
  5539. (see HandleEvent Method of your Part Editor) should dispatch events to routines 
  5540. that perform the actions described here. For other information about creating 
  5541. and modifying selections, see Mouse-Down Tracking and Selection. 
  5542.  
  5543.  
  5544. ΓòÉΓòÉΓòÉ 7.2.1. How Part Activation Happens ΓòÉΓòÉΓòÉ
  5545.  
  5546. A part's frame activates itself in these situations: 
  5547.  
  5548.      When it receives a mouse event within its content area 
  5549.  
  5550.      When its window first opens and the part has stored information 
  5551.       specifying that the frame should be active on opening 
  5552.  
  5553.      When its window becomes active and the part has stored information 
  5554.       specifying that the frame should be active upon window activation 
  5555.  
  5556.      When data is dropped on the part as a result of a drag-and-drop operation 
  5557.  
  5558.      When it has another reason for becoming active (such as the need to 
  5559.       display a selection, such as a link source, to the user) 
  5560.  
  5561.  The part activates itself by acquiring the selection focus (see Focus Types) 
  5562.  for one of its display frames. The part is then responsible for displaying its 
  5563.  contents appropriately (such as by restoring the highlighting of a selection) 
  5564.  and for providing any menus, controls, palettes, floating windows, or other 
  5565.  auxiliary items that are part of its active state. The part must also obtain 
  5566.  ownership of any other foci that it needs. OpenDoc draws the active frame 
  5567.  border around the frame with the selection focus. the following figure 
  5568.  illustrates some of the visual changes caused by activation. 
  5569.  
  5570.  In the preceding figure, the graphics part is active. OpenDoc draws the active 
  5571.  frame border around its frame, it has a highlighted selection, and it displays 
  5572.  Font, Size, and Style menus. 
  5573.  
  5574.  Typically, one part is deactivated when another is activated. A part is 
  5575.  expected to deactivate itself when it receives a request to relinquish the 
  5576.  selection focus, plus, possibly, other foci. The deactivating part is 
  5577.  responsible for clearing its selections-an active part in the active window 
  5578.  should not maintain a background selection-and for removing any menus and 
  5579.  other items that were part of its active state. OpenDoc removes the active 
  5580.  frame border from around the (now inactive) part and draws it around the part 
  5581.  that currently has the selection focus. 
  5582.  
  5583.  Mouse events that cause part activation can also cause window activation and 
  5584.  can lead to dragging of part content. The following figure illustrates some of 
  5585.  the elements you must consider in handling mouse-down events for these 
  5586.  purposes. As the following sections explain, your part should handle mouse 
  5587.  events based on whether your part is active or inactive, whether it is in an 
  5588.  active or inactive window, and whether the event location corresponds to one 
  5589.  of the elements- such as the active frame border or an embedded part's 
  5590.  icon-that are shown in the following figure. 
  5591.  
  5592.  Note these points from the previous figure: 
  5593.  
  5594.      Embedded parts can be represented by either frames or icons. Frames can 
  5595.       be active or inactive, and inactive frames can be either selected or 
  5596.       unselected. (Not shown in the figure is that inactive frames can also be 
  5597.       bundled). 
  5598.  
  5599.      There can be only one active frame in the active window, and no active 
  5600.       frame in an inactive window (except that a dialog box can appear in front 
  5601.       of a window that contains the active part). 
  5602.  
  5603.      All selected items must be within the active frame. 
  5604.  
  5605.      A selection in the active window becomes a background selection if the 
  5606.       window becomes inactive. 
  5607.  
  5608.      A selection (either foreground or background) can consist of either 
  5609.       intrinsic content or an embedded frame or icon, or a combination of both. 
  5610.  
  5611.      "Click-selectable intrinsic content" in the figure means any item of 
  5612.       intrinsic content that can be selected by a single mouse click, such as a 
  5613.       graphic object in a draw part. 
  5614.  
  5615.      "White space" in the figure means any location in the content area of a 
  5616.       part that is neither click-selectable intrinsic content nor an embedded 
  5617.       part frame or icon. It includes empty space, but also includes content 
  5618.       (such as text or painting) that requires a sweeping gesture, rather than 
  5619.       a single click, for selection. 
  5620.  
  5621.      An inactive window may be in the current process (if, for example, it is 
  5622.       a part window of the active document) or in a background process (if, for 
  5623.       example, it is a window of another document). 
  5624.  
  5625.  The event-handling guidelines given here are designed to provide the user with 
  5626.  maximum consistency and flexibility when activating parts and when dragging 
  5627.  selections. 
  5628.  
  5629.  
  5630. ΓòÉΓòÉΓòÉ 7.2.2. Handling Mouse Events ΓòÉΓòÉΓòÉ
  5631.  
  5632. On the OS/2 platform, mouse events are sent to your part's HandleEvent as 
  5633. normal PM mouse messages. The flags field of the EventInfo structure contains 
  5634. information about where the mouse event occurred. It will be either 
  5635. kODPropagated, kODInBorder or kODInEmbedded. 
  5636.  
  5637.  
  5638. ΓòÉΓòÉΓòÉ 7.2.3. Handling Activate Events ΓòÉΓòÉΓòÉ
  5639.  
  5640. As noted in Activate Events, your part receives an activate event for each of 
  5641. its facets when your window becomes active, and a deactivate event when your 
  5642. window becomes inactive. 
  5643.  
  5644. When a window becomes inactive, the part that holds the selection focus 
  5645. relinquishes that focus but can maintain, as a background selection, any 
  5646. selection it had been displaying. Conversely, when a window becomes active, the 
  5647. part that had held the selection focus when the window became inactive normally 
  5648. regains the selection focus. That part may or may not be the part that actually 
  5649. activated the window. 
  5650.  
  5651. This part-activation convention requires that your part respond to activate and 
  5652. deactivate events by recording or retrieving stored information on its focus 
  5653. transfers; see On Window Activation for more information. 
  5654.  
  5655. Activate events in a window go first to the most deeply embedded facets and 
  5656. last to the root facet. This dispatch order gives the root part the opportunity 
  5657. to obtain the selection focus if no embedded part has done so. It also allows 
  5658. the root part to override any activation actions taken by embedded parts. 
  5659.  
  5660.  
  5661. ΓòÉΓòÉΓòÉ 7.3. Focus Transfer ΓòÉΓòÉΓòÉ
  5662.  
  5663. Part activation is the process of making a part and frame ready for editing. As 
  5664. noted previously, activation typically occurs when the user clicks the mouse 
  5665. button when the pointer is within a frame that is not currently active, but 
  5666. also happens when a window opens, when a window is activated, and as a result 
  5667. of drag-and-drop operations. 
  5668.  
  5669. In the OpenDoc model of part activation, part editors use the concept of focus 
  5670. to activate and deactivate themselves (rather than being activated and 
  5671. deactivated by OpenDoc) and to arbitrate the transfer of several types of 
  5672. shared resources among themselves. 
  5673.  
  5674.  
  5675. ΓòÉΓòÉΓòÉ 7.3.1. Focus Types ΓòÉΓòÉΓòÉ
  5676.  
  5677. A part makes itself the recipient of a certain type of user event or other 
  5678. action by obtaining the focus for it. A focus is a designation of ownership of 
  5679. a given shared resource, feature, or event type; for example, the frame that 
  5680. owns the keystroke focus receives all keystroke events until it passes 
  5681. ownership of the keystroke focus to another frame. 
  5682.  
  5683. Focus types are defined as ISO strings, and the standard set defined by OpenDoc 
  5684. includes those in the following table. 
  5685.  
  5686. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5687. ΓöéConstant            ΓöéISO String          ΓöéDescription         Γöé
  5688. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5689. ΓöékODKeyFocus         Γöé"Key"               ΓöéKeystroke events areΓöé
  5690. Γöé                    Γöé                    Γöésent to the frame   Γöé
  5691. Γöé                    Γöé                    Γöéwith this focus.    Γöé
  5692. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5693. ΓöékODMenuFocus        Γöé"Menu"              ΓöéMenu events are sentΓöé
  5694. Γöé                    Γöé                    Γöéto the frame with   Γöé
  5695. Γöé                    Γöé                    Γöéthis focus.         Γöé
  5696. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5697. ΓöékODSelectionFocus   Γöé"Selection"         ΓöéShift-click and     Γöé
  5698. Γöé                    Γöé                    ΓöéCommand-click mouse Γöé
  5699. Γöé                    Γöé                    Γöéevents are sent to  Γöé
  5700. Γöé                    Γöé                    Γöéthe frame with this Γöé
  5701. Γöé                    Γöé                    Γöéfocus. OpenDoc drawsΓöé
  5702. Γöé                    Γöé                    Γöéthe active frame    Γöé
  5703. Γöé                    Γöé                    Γöéborder around all   Γöé
  5704. Γöé                    Γöé                    Γöéfacets of this      Γöé
  5705. Γöé                    Γöé                    Γöéframe.              Γöé
  5706. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5707. ΓöékODModalFocus       Γöé"Modal"             ΓöéThe frame that owns Γöé
  5708. Γöé                    Γöé                    Γöéthis focus is       Γöé
  5709. Γöé                    Γöé                    Γöénotifying other     Γöé
  5710. Γöé                    Γöé                    Γöéframes that it is   Γöé
  5711. Γöé                    Γöé                    Γöéthe only current    Γöé
  5712. Γöé                    Γöé                    Γöémodal frame.        Γöé
  5713. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5714. ΓöékODScrollingFocus   Γöé"Scrolling"         ΓöéScrolling-specific  Γöé
  5715. Γöé                    Γöé                    Γöékeystroke events    Γöé
  5716. Γöé                    Γöé                    Γöé(such as Page Up andΓöé
  5717. Γöé                    Γöé                    ΓöéPage Down) are sent Γöé
  5718. Γöé                    Γöé                    Γöéto the frame with   Γöé
  5719. Γöé                    Γöé                    Γöéthis focus.         Γöé
  5720. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5721. ΓöékODClipboardFocus   Γöé"Clipboard"         ΓöéThe frame that owns Γöé
  5722. Γöé                    Γöé                    Γöéthis focus has      Γöé
  5723. Γöé                    Γöé                    Γöéaccess to the       Γöé
  5724. Γöé                    Γöé                    Γöéclipboard.          Γöé
  5725. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5726. ΓöékODMouseFocus       Γöé"Mouse"             ΓöéThe frame that owns Γöé
  5727. Γöé                    Γöé                    Γöéthis focus receives Γöé
  5728. Γöé                    Γöé                    Γöéall mouse-within    Γöé
  5729. Γöé                    Γöé                    Γöéevents whenever the Γöé
  5730. Γöé                    Γöé                    Γöépointer moves,      Γöé
  5731. Γöé                    Γöé                    Γöéregardless of which Γöé
  5732. Γöé                    Γöé                    Γöéfacet the pointer isΓöé
  5733. Γöé                    Γöé                    Γöéwithin.             Γöé
  5734. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5735. ΓöékODStatusLineFocus  Γöé"StatusLine"        ΓöéThe frame that owns Γöé
  5736. Γöé                    Γöé                    Γöéthis focus has      Γöé
  5737. Γöé                    Γöé                    Γöéaccess to the statusΓöé
  5738. Γöé                    Γöé                    Γöéline window.        Γöé
  5739. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5740.  
  5741. To obtain event foci, part editors request them by name from the arbitrator. 
  5742. (You obtain access to the arbitrator by calling the GetArbitrator method of the 
  5743. session object). 
  5744.  
  5745. You need to convert focus names into tokens before using them in any method 
  5746. calls. You call the Tokenize method of the session object to convert ISO 
  5747. strings to tokens. 
  5748.  
  5749. Foci may be manipulated singly or in groups called focus sets. A focus set is 
  5750. an OpenDoc object (of class ODFocusSet) listing a group of foci that a part 
  5751. editor wants to obtain or release as a group. 
  5752.  
  5753. Foci are owned by frames. Note that, in general, mouse events anywhere within 
  5754. the content area of an OpenDoc window always go to the most deeply embedded 
  5755. frame that encloses the click point; thus there is no "mouse focus.". However, 
  5756. Shift-click, Ctrl-click or Alt-click events, regardless of their location, are 
  5757. sent to the frame with the selection focus to allow for extending selections. 
  5758.  
  5759. OpenDoc does not require that the same frame own the selection focus, keystroke 
  5760. focus, and menu focus, although this is most often the case. Nor does OpenDoc 
  5761. require that the selection focus be in an active window, although this is 
  5762. usually the case. 
  5763.  
  5764. In most cases, when a frame is activated, the part editor for that frame 
  5765. requests the selection focus, keystroke focus, and menu focus. A frame with 
  5766. scroll bars might also request the scrolling focus. Your part editor might 
  5767. create a focus set ahead of time, perhaps during part initialization, that 
  5768. includes the tokenized names of the foci that your part expects to request when 
  5769. it becomes active. You use the arbitrator's CreateFocusSet method to create the 
  5770. focus set. 
  5771.  
  5772. A simple part, such as a small text-entry field in a dialog box, might request 
  5773. only the selection focus and keystroke focus on receiving a mouse-up event 
  5774. within its frame area. An even simpler part, such as a button, might not even 
  5775. request the selection focus. It might simply track the mouse until the button 
  5776. is released and then run a script, never having changed the menu bar, put up 
  5777. palettes or rulers, or become active. 
  5778.  
  5779. Your part editor can define additional focus types as needed. You can define 
  5780. other kinds of focus, perhaps to handle other kinds of user events (such as 
  5781. input from new kinds of devices). To create a new kind of focus, you need to 
  5782. create a new kind of focus module, the OpenDoc object that the arbitrator uses 
  5783. to determine focus ownership. Semantic Events and Scripting describes how to 
  5784. use focus modules to extend OpenDoc's focus management. 
  5785.  
  5786. Foci may be exclusive or nonexclusive. All of the standard foci defined by 
  5787. OpenDoc are exclusive, meaning that only one frame at a time can own a focus. 
  5788. But if you create a new kind of focus, you can make it nonexclusive, meaning 
  5789. that several frames could share ownership of it. 
  5790.  
  5791.  
  5792. ΓòÉΓòÉΓòÉ 7.3.2. Arbitrating Focus Transfers ΓòÉΓòÉΓòÉ
  5793.  
  5794. This section discusses how to request or relinquish foci to activate or 
  5795. deactivate your frames. 
  5796.  
  5797.  
  5798. ΓòÉΓòÉΓòÉ 7.3.2.1. Requesting Foci ΓòÉΓòÉΓòÉ
  5799.  
  5800. A part can request, for one of its frames, ownership of a single focus or a set 
  5801. of foci. You request a focus by calling the arbitrator's RequestFocus method; 
  5802. you request a focus set by calling the arbitrator's RequestFocusSet method. If 
  5803. the request succeeds, your part's frame obtains the focus or focus set. 
  5804.  
  5805. The arbitrator's RequestFocus and RequestFocusSet methods perform a two-stage 
  5806. transaction in transferring a focus or focus set: 
  5807.  
  5808.    1. The arbitrator first asks the current owning frame of each focus if it is 
  5809.       willing to relinquish the focus, by calling the BeginRelinquishFocus 
  5810.       method of the frame's part. 
  5811.  
  5812.    2. If any owner of the focus is unwilling to relinquish it, the arbitrator 
  5813.       cancels the request by calling each part's AbortRelinquishFocus method. 
  5814.       In this case, RequestFocus or RequestFocusSet returns false. 
  5815.  
  5816.    3. If all focus owners are willing to relinquish, the arbitrator calls each 
  5817.       part's CommitRelinquishFocus method. In this case, RequestFocus or 
  5818.       RequestFocusSet returns true. 
  5819.  
  5820.  
  5821. ΓòÉΓòÉΓòÉ 7.3.2.2. Relinquishing Foci ΓòÉΓòÉΓòÉ
  5822.  
  5823. A part can relinquish foci either on request or when a change to its state 
  5824. (such as the closure of its frame or a completion of a method) warrants it. An 
  5825. active part might unilaterally relinquish certain foci (such as the clipboard 
  5826. focus) as soon as it is finished handling an event, but it might not relinquish 
  5827. other foci (such as the selection focus) until another part asks for them. 
  5828. Nevertheless, most parts willingly relinquish the common foci when asked. 
  5829.  
  5830. Relinquishing foci on request is a two-step process, because multiple foci 
  5831. requested as a focus set must all be provided to the requestor simultaneously; 
  5832. if one is not available, none need be relinquished. Your part editor 
  5833. participates in the process through calls to its BeginRelinquishFocus, 
  5834. CommitRelinquishFocus, and AbortRelinquishFocus methods. 
  5835.  
  5836.    1. In your BeginRelinquishFocus method, you need do nothing other than 
  5837.       return kODTrue or kODFalse, based on the type of focus and the identities 
  5838.       of the frames (current and proposed focus owners) passed to you. In most 
  5839.       cases, you can simply return kODTrue, unless your part is displaying a 
  5840.       dialog box and another part is requesting the modal focus. In that case, 
  5841.       because you do not want to yield the modal focus until your dialog box 
  5842.       window closes, you return kODFalse. See Acquiring and Relinquishing the 
  5843.       Modal Focus for more information. 
  5844.  
  5845.    2. Your part's CommitRelinquishFocus method, verifies that you have actually 
  5846.       relinquished the focus type you responded to in BeginRelinquishFocus. The 
  5847.       method should take appropriate action, such as removing menus or 
  5848.       palettes, disabling menu items, removing highlighting, and performing 
  5849.       whatever other tasks are part of losing that type of focus. Remember that 
  5850.       the focus may possibly be moving from one frame to another of your part, 
  5851.       so the exact actions can vary. 
  5852.  
  5853.    3. If, after your part responds with kODTrue to BeginRelinquishFocus, the 
  5854.       focus is actually not transferred from your frame, OpenDoc calls your 
  5855.       part's AbortRelinquishFocus method. If your part has done anything more 
  5856.       than return the Boolean result in BeginRelinquishFocus, it can undo those 
  5857.       effects in the AbortRelinquishFocus method. 
  5858.  
  5859.    4. If your part is one of several focus owners called to relinquish the foci 
  5860.       of a focus set, and if you return kODFalse to BeginRelinquishFocus, your 
  5861.       CommitRelinquishFocus method is not called (because you chose not to give 
  5862.       up the focus). However, your AbortRelinquishFocus method is still called 
  5863.       (because all owners of a focus set are notified if any one refuses to 
  5864.       relinquish the focus). 
  5865.  
  5866.  Your part does not relinquish its focus on request only. For example, in your 
  5867.  part's DisplayFrameClosed and DisplayFrameRemoved methods, you should include 
  5868.  a call to the arbitrator's RelinquishFocus or RelinquishFocusSet method to 
  5869.  unilaterally relinquish any foci owned by the frame that you are closing. When 
  5870.  your part closes, its ReleaseAll method should likewise relinquish all of its 
  5871.  foci. When your part finishes displaying a modal dialog box, it should 
  5872.  relinquish or transfer the modal focus; when your part finishes accessing the 
  5873.  clipboard, it should relinquish the clipboard focus. 
  5874.  
  5875.  
  5876. ΓòÉΓòÉΓòÉ 7.3.2.3. Transferring Focus without Negotiation ΓòÉΓòÉΓòÉ
  5877.  
  5878. There are some situations in which the normal process of requesting and 
  5879. relinquishing foci is not used. Another piece of software interrupts your 
  5880. part's execution, and your part loses a focus without being given a chance to 
  5881. relinquish it, or gains focus without having asked for it. To handle those 
  5882. situations, your part editor must implement versions of the methods 
  5883. FocusAcquired and FocusLost. The arbitrator calls these methods when your part 
  5884. has just acquired, or just lost, a specified focus without having negotiated 
  5885. the transaction. 
  5886.  
  5887. For example, a containing part, to support keyboard navigation, might call 
  5888. FocusAcquired in turn on each of its embedded parts as the user makes 
  5889. successive keystrokes. Or, if a custom input device with its own focus type 
  5890. were in use and then became detached, the part using the device might receive a 
  5891. call to its FocusLost method. 
  5892.  
  5893. These are the interfaces to FocusAcquired and FocusLost: 
  5894.  
  5895. void FocusAcquired(in ODTypeToken focus,
  5896.                    in ODFrame ownerFrame);
  5897.  
  5898. void FocusLost(in ODTypeToken focus,
  5899.                in ODFrame ownerFrame);
  5900.  
  5901. Your FocusAcquired and FocusLost methods should perform any actions your part 
  5902. editor deems appropriate in response to having just acquired or lost a focus. 
  5903.  
  5904. The arbitrator's methods TransferFocus and TransferFocusSet allow you to 
  5905. initiate a transfer of focus ownership without negotiation. A part can use 
  5906. these calls to transfer focus among parts and frames that it controls directly. 
  5907. For example, in a modal dialog box consisting of several parts, these methods 
  5908. can be used to transfer a focus from the outer part (the dialog box) directly 
  5909. to an inner part (such as a text field) and back. 
  5910.  
  5911. When focus is transferred with TransferFocus or TransferFocusSet, the 
  5912. arbitrator calls the FocusAcquired method of the new frame's part and the 
  5913. FocusLost method of the previous frame's part-except that, when the frame 
  5914. performing the transfer (the frame representing the part that calls 
  5915. TransferFocus) is the frame receiving or losing the focus, its FocusAcquired or 
  5916. FocusLost method is not called. 
  5917.  
  5918.  
  5919. ΓòÉΓòÉΓòÉ 7.3.2.3.1. Calling your Own FocusAcquired and FocusLost ΓòÉΓòÉΓòÉ
  5920.  
  5921.  
  5922. It might seem natural to call your own FocusAcquired method when your request 
  5923. for foci succeeds, or to call your own FocusLost method from your own 
  5924. CommitRelinquishFocus method. A better practice, however, is to have related 
  5925. methods call a shared private method, so that you maintain a clear separation 
  5926. between public and private interfaces. 
  5927.  
  5928.  
  5929. ΓòÉΓòÉΓòÉ 7.3.3. Recording Focus Transfers ΓòÉΓòÉΓòÉ
  5930.  
  5931. Different frames may need different sets foci when activated. Selection focus, 
  5932. keystroke focus, and menu focus are commonly needed together. However, a frame 
  5933. with scroll bars might also need the scrolling focus, and a frame for a 
  5934. modeless dialog box might not even want the selection focus. 
  5935.  
  5936. OpenDoc does not save or restore focus assignments. Therefore, during 
  5937. deactivation of windows and frames, and during closing of windows, you can 
  5938. record the state of focus ownership in order to restore it at a later 
  5939. activation or reopening. Your display frame's part info is an appropriate place 
  5940. to keep that information. Your part's initialization method might create a 
  5941. focus set with those foci, to use whenever your display frames become active. 
  5942.  
  5943.  
  5944. ΓòÉΓòÉΓòÉ 7.3.3.1. On Frame Activation ΓòÉΓòÉΓòÉ
  5945.  
  5946. When a previously inactive frame in a window becomes active, the part editors 
  5947. involved should-besides negotiating the focus transfer-record the gain or loss 
  5948. of selection focus for the respective frames. If you maintain that information, 
  5949. your activation and deactivation routines can check the state and exit quickly 
  5950. if not needed. 
  5951.  
  5952.      If you are activating your part's frame, you might record, in a Boolean 
  5953.       flag with a name such as fHasRequiredFoci in the frame's part info data, 
  5954.       the fact that the frame has the selection focus. You can perform this 
  5955.       action in your FocusAcquired method, after its call to the arbitrator's 
  5956.       RequestFocusSet method succeeds. 
  5957.  
  5958.      If you are deactivating your part's frame, you might set the 
  5959.       fHasRequiredFoci flag in the frame's part info data to false. You can 
  5960.       perform this action in your FocusLost method and/or your 
  5961.       CommitRelinquishFocus method. 
  5962.  
  5963.  
  5964. ΓòÉΓòÉΓòÉ 7.3.3.2. On Window Activation ΓòÉΓòÉΓòÉ
  5965.  
  5966. As mentioned in Activate Events, all parts displayed in a window receive an 
  5967. activate event when the window becomes active, and a deactivate event when the 
  5968. window becomes inactive. 
  5969.  
  5970. When an active facet of a frame of your part becomes inactive through window 
  5971. deactivation and your part loses the selection focus, your part's HandleEvent 
  5972. method can-upon receiving the deactivate event-store a flag in the facet's part 
  5973. info field to note that the facet was active before window deactivation. Your 
  5974. part then can also maintain, as a background selection, any selection it had 
  5975. been displaying. 
  5976.  
  5977. Conversely, when a facet of a frame of your part receives an activate event 
  5978. because of window activation, your part's HandleEvent method can examine the 
  5979. state of the flag in the part info field to decide whether or not it was the 
  5980. active part when the window became inactive. If so, it should request the 
  5981. selection focus, reset the flag, and convert any background selection it may 
  5982. have maintained into a foreground selection. 
  5983.  
  5984.  
  5985. ΓòÉΓòÉΓòÉ 7.3.3.3. On Closing and Reopening Documents ΓòÉΓòÉΓòÉ
  5986.  
  5987. Normally, the root part of a newly opened window should activate itself as a 
  5988. matter of course. However, if an embedded had the selection focus when the 
  5989. window closed, the root part can-if it chooses to-allow the embedded part to 
  5990. recapture that focus when the window reopens. 
  5991.  
  5992. When the state of a window is saved in a document and the document is 
  5993. subsequently reopened, the root part recreates the window. If you want to 
  5994. restore the selection-focus state of your part (plus perhaps the selection 
  5995. itself), you can save the selection and the state of the selection-focus flag 
  5996. in your frame's part info data when the window is closed, and restore them when 
  5997. the window is opened (when your part's DisplayFrameConnected method is called). 
  5998.  
  5999. If your part is the root part in this situation, you can either allow the 
  6000. embedded part's request for selection focus at this time, or you can acquire 
  6001. the selection focus yourself, when your own DisplayFrameAdded or 
  6002. DisplayFrameConnected method is called. (The root part is called last). 
  6003.  
  6004.  
  6005. ΓòÉΓòÉΓòÉ 7.4. Display-Related Events ΓòÉΓòÉΓòÉ
  6006.  
  6007. Your part editor needs to respond to events that select or change the position 
  6008. or visibility of your intrinsic content, by highlighting or preparing to move 
  6009. or redraw the content. This section discusses general event-handling issues 
  6010. related to drawing and highlighting. Display concepts are described more 
  6011. completely in Layout and Embedding. 
  6012.  
  6013. Just as with intrinsic content, your part editor is responsible for knowing 
  6014. what embedded frames look like and when they become visible or invisible. When 
  6015. update events or events related to scrolling or editing cause an embedded frame 
  6016. to become visible, your part is responsible for creating facets for those 
  6017. frames. If events cause an embedded facet to move, your part must modify the 
  6018. facet's external transform to reflect the move. If the embedded facet moves so 
  6019. as to become no longer visible, your part is responsible for deleting the 
  6020. embedded facet from its containing facet (or marking it purge-able). 
  6021.  
  6022.  
  6023. ΓòÉΓòÉΓòÉ 7.4.1. Hit-Testing ΓòÉΓòÉΓòÉ
  6024.  
  6025. Hit-testing is the interpretation of mouse events in terms of content elements 
  6026. within a frame. For example, when the user clicks the mouse somewhere within 
  6027. your part's content area to select an item or to set an insertion point, you 
  6028. must use the click location to decide which item has been selected or which 
  6029. characters correspond to the insertion point. You can then highlight the proper 
  6030. item or draw the text caret at the proper location. 
  6031.  
  6032. Coordinate conversion is necessary to assign content locations to hit-testing 
  6033. events; in that sense, hit-testing is the inverse of drawing. Coordinate 
  6034. conversion and the application of transforms during drawing is discussed in 
  6035. Transforms and Coordinate Spaces. 
  6036.  
  6037. If a mouse click occurs in a facet of your embedded part's frame, OpenDoc 
  6038. applies the inverse of all external transforms from the canvas facet to your 
  6039. facet, passing to you the mouse event in your part's frame coordinates. These 
  6040. coordinates are stored in the ODPoint field of the EventInfo structure. It is 
  6041. then your responsibility to apply the inverse of your own internal transform to 
  6042. the event location to convert it to the content coordinates of your part. 
  6043.  
  6044. If the entire content of your part's frame is scrolled, the application of your 
  6045. frame's internal transform yields the correct location for everything within 
  6046. the frame. If, however, your part has drawn scroll bars or other nonscrolling 
  6047. items within the frame, it is important not to apply the internal transform to 
  6048. events over those items. See Scrolling for more information. 
  6049.  
  6050.  
  6051. ΓòÉΓòÉΓòÉ 7.4.2. Invalidating and Updating ΓòÉΓòÉΓòÉ
  6052.  
  6053. When keystroke or mouse events involved with editing have changed the visible 
  6054. content of your part, you should invalidate the affected areas (by calling your 
  6055. frame's Invalidate method), so that an update event will be generated to force 
  6056. a redraw. If the same presentation of your part is displayed in more than one 
  6057. frame (see Synchronizing Display Frames), you are responsible for invalidating 
  6058. those frames as well, if necessary. 
  6059.  
  6060. Sometimes, a portion of a window needs to be redrawn because it has been 
  6061. invalidated by actions taken by the documents' parts or by the system (as when 
  6062. a window is uncovered). In this case, the document shell receives notification 
  6063. of that fact and passes an update event to the dispatcher, which calls the 
  6064. Update method of the window. The window in turn calls the Update method its 
  6065. root facet. 
  6066.  
  6067. The root facet's Update method examines all of the root facet's embedded facets 
  6068. (and their embedded facets, and so on) and marks each one that intersects the 
  6069. area that must be updated. Then, each facet that needs to be redrawn calls the 
  6070. Draw method of its frame's part, passing it the appropriate shape that 
  6071. represents its portion of the area to be updated. 
  6072.  
  6073. Your part can, if desired, modify the order in which embedded parts draw their 
  6074. content, by making explicit calls to the Draw, DrawChildren, and 
  6075. DrawChildrenAlways methods of an embedded facet. See Draw Method of your Part 
  6076. Editor and Asynchronous Drawing for more information. 
  6077.  
  6078.  
  6079. ΓòÉΓòÉΓòÉ 7.4.3. Scrolling ΓòÉΓòÉΓòÉ
  6080.  
  6081. The scrolled position of a part's contents within a frame is controlled by the 
  6082. frame's internal transform. (The transform object can also support scaling, 
  6083. translation, rotation, and perspective transformations of a frame's contents. 
  6084. See the figure on transforms in Transforms and Coordinate Spaces for an 
  6085. example. 
  6086.  
  6087. In general, the user specifies the amount of scrolling to apply to a frame. The 
  6088. part editor then modifies the offset specified in the frame's internal 
  6089. transform. (Depending on the new scrolled position of the part's contents, the 
  6090. part editor might also have to add or remove facets for embedded frames that 
  6091. have become visible or obscured by the scrolling). 
  6092.  
  6093. There are a number of ways for your part editor to support scrolling: 
  6094.  
  6095.      It can create scroll bars for its content, placing them at the margins of 
  6096.       its display frames. 
  6097.  
  6098.      It can create scroll bars, sliders, or other kinds of controls and place 
  6099.       them outside of its frame, as separate frames, or as elements in a 
  6100.       floating window. 
  6101.  
  6102.      It can support auto-scrolling, by tracking the mouse pointer when the 
  6103.       user moves it beyond your part's frame, while holding down the mouse 
  6104.       button. 
  6105.  
  6106.  Each of these methods requires different event handling by your part to 
  6107.  achieve the same result: a modified internal transform for the frame. Your 
  6108.  part then draws the scrolled display as described in Scrolling your Part in a 
  6109.  Frame. 
  6110.  
  6111.  
  6112. ΓòÉΓòÉΓòÉ 7.4.3.1. Event-Handling in Scroll Bars within your Frame ΓòÉΓòÉΓòÉ
  6113.  
  6114. You can create scroll bars for your content inside the margins of your frame. 
  6115. One approach to handling events in those scroll bars is to create an extra, 
  6116. private "content shape" within your frame. The content shape is the same as the 
  6117. frame shape, except that it does not include the areas of the scroll bars. 
  6118.  
  6119. When interpreting mouse events within your frame, it is important that the 
  6120. current scrolled position of your content be taken into account for content 
  6121. editing but not for scroll-bar manipulation. Thus, for points that fall within 
  6122. your content shape, you apply the inverse of the frame's internal transform to 
  6123. mouse events, whereas outside of it (in the scroll bar area) you do not. See 
  6124. the following figure. 
  6125.  
  6126. Mouse events within the scroll bar area specify how to set the frame's internal 
  6127. transform; based on the transform's new value, you then redraw your part's 
  6128. content (and the scroll bar slider). Mouse events within the area of the 
  6129. content shape specify how to select or edit the appropriately scrolled content. 
  6130.  
  6131.  
  6132. ΓòÉΓòÉΓòÉ 7.4.3.2. Event Handling in Scroll Bars in Separate Frames ΓòÉΓòÉΓòÉ
  6133.  
  6134. If you place scroll bars or adornments in completely separate frames from your 
  6135. content, (see Placing Scroll Bars in a Separate Frame), you avoid having to 
  6136. define a separate content shape. Your part has one display frame that encloses 
  6137. both the scroll bars and the content; you draw the scroll bars directly in this 
  6138. frame, and you draw the content in a sub-frame. Only the sub-frame's internal 
  6139. transform changes. 
  6140.  
  6141. When a mouse event occurs in the nonscrolling frame, your part interprets it 
  6142. and sets the internal transform of the scrolling sub-frame accordingly. 
  6143.  
  6144.  
  6145. ΓòÉΓòÉΓòÉ 7.4.4. Mouse-Down Tracking and Selection ΓòÉΓòÉΓòÉ
  6146.  
  6147. A selection exists only in the context of a particular part. A selection's 
  6148. boundaries may not span part boundaries; all of its margins must be in the same 
  6149. part. However, a selection can include any number of embedded frames (which 
  6150. themselves can be considered to include any number of more deeply embedded 
  6151. frames). 
  6152.  
  6153. Selections are typically created by mouse events, or keyboard-modified mouse 
  6154. events, within an already active frame or a frame that has been made 
  6155. potentially active by an initial mouse-down event within its area. When a 
  6156. mouse-down event occurs, OpenDoc passes the pointer location, in the frame 
  6157. coordinates of the most deeply imbedded frame enclosing the event location, to 
  6158. the part displayed in that frame. If a drag-selection occurs (that is, if a 
  6159. drag-and-drop operation does not occur), the subsequent mouse-up event location 
  6160. is passed in the same coordinates to the same part. Thus, the active frame is 
  6161. not changed simply because the cursor passes across a frame boundary while 
  6162. making a selection. 
  6163.  
  6164. The selection actions your part takes during mouse-down tracking depend on your 
  6165. content model. You should provide feedback to the user while the dragging is in 
  6166. progress. 
  6167.  
  6168. Your part editor should support extending selections through Shift-clicking, 
  6169. Ctrl-clicking and Alt-clicking. Note that, because selection is possible only 
  6170. within one part at a time, a part editor can extend a selection outside of its 
  6171. display frame boundary only to items within another of its own display frames. 
  6172.  
  6173. If your part is a containing part and allows the user to drag selected content, 
  6174. including embedded frames, dragging may lead to frame negotiation. If an 
  6175. embedded frame is clipped by the edge of a page, for example, you may need to 
  6176. change its size. 
  6177.  
  6178. Selected frames should be highlighted appropriately, as described in Drawing 
  6179. Selections. 
  6180.  
  6181.  
  6182. ΓòÉΓòÉΓòÉ 7.4.5. Resizing Selected Frames ΓòÉΓòÉΓòÉ
  6183.  
  6184. Typically, the user resizes embedded frames within your part is by selecting 
  6185. them and then dragging their resize handles. It is your part, as the (active) 
  6186. containing part, that handles resizing of its (selected) embedded frames. 
  6187.  
  6188. A user can select an embedded frame in several ways, as noted previously. Once 
  6189. a frame is selected,  and if your part allows resizing, you can handle resizing 
  6190. events like this: 
  6191.  
  6192.    1. A mouse-down event on a resize handle in a selected frame border 
  6193.       initiates a resize operation. You track the mouse until the button is 
  6194.       released, giving the user visual feedback on the potential appearance of 
  6195.       the resized frame. The potential shape of the resized frame can depend on 
  6196.       what kind of resize handle (such as corner or side) is being dragged. 
  6197.  
  6198.    2. When the mouse-up event occurs, you determine if its location is 
  6199.       consistent with your part's content model, in terms of allowing a 
  6200.       resizing to that location. If it is not, you can either terminate the 
  6201.       resize operation or adjust the location to an appropriate point. 
  6202.  
  6203.    3. Change the frame size, as discussed in Resizing an Embedded Frame. 
  6204.  
  6205.  
  6206. ΓòÉΓòÉΓòÉ 7.4.6. Mouse-Up Tracking ΓòÉΓòÉΓòÉ
  6207.  
  6208. OpenDoc calls your part's HandleEvent method whenever the mouse pointer enters, 
  6209. moves within, or leaves a facet of a display frame of your part and the mouse 
  6210. button is up (not pressed). Your part can use this method call to display a 
  6211. custom cursor while the pointer is within your part's frames. 
  6212.  
  6213. Your part is responsible for providing the appropriate cursor appearances as 
  6214. defined by OpenDoc. 
  6215.  
  6216.  
  6217. ΓòÉΓòÉΓòÉ 7.4.7. Mouse-Up Feedback while Drawing ΓòÉΓòÉΓòÉ
  6218.  
  6219. In certain modal situations, such as when drawing polygons or connected line 
  6220. segments, the user typically draws by clicking the mouse button once for each 
  6221. successive vertex or joint. (The user might complete the polygon and exit the 
  6222. mode by double-clicking or by clicking in the menu bar or another window). 
  6223. During the drawing operation, while the mouse button is up, the part editor 
  6224. must provide feedback to the user, showing a potential line segment extending 
  6225. from the last vertex to the current mouse position. 
  6226.  
  6227. Your part can support this kind of drawing feedback by requesting the mouse 
  6228. focus (kODMouseFocus) when the user clicks to make the first vertex after 
  6229. selecting the appropriate drawing mode (perhaps from a tool palette that you 
  6230. maintain). Your part then receives events when the mouse moves, regardless of 
  6231. which facet the cursor travels over; the facet passed to your HandleEvent 
  6232. method is the one in which the initial mouse-down event occurred. Receiving 
  6233. these events allows you to provide visual feedback regardless of where the user 
  6234. moves the mouse pointer. 
  6235.  
  6236. Your part also receives all mouse-down and mouse-up events until it 
  6237. relinquishes the focus. In addition, as long as your part holds the mouse 
  6238. focus, OpenDoc sends no mouse events to any facet. 
  6239.  
  6240. When the user completes the drawing operation, relinquish the mouse focus. 
  6241.  
  6242.  
  6243. ΓòÉΓòÉΓòÉ 8. Windows and Menus ΓòÉΓòÉΓòÉ
  6244.  
  6245. This is the fourth of eight chapters that discuss the OpenDoc programming 
  6246. interface in detail. This chapter describes how your part editor can present 
  6247. and manipulate some of the major elements of its user interface. 
  6248.  
  6249. This chapter is a continuation of the previous chapter: it discusses 
  6250. event-handling and other programming issues involved with your part's user 
  6251. interface. 
  6252.  
  6253. Before reading this chapter, you should be familiar with the concepts presented 
  6254. in Introduction and Development Overview. For additional concepts related to 
  6255. your part editor's run-time environment, see OpenDoc Run-Time Features. 
  6256.  
  6257. This chapter discusses the following topics: 
  6258.  
  6259.      Windows 
  6260.      Dialog boxes 
  6261.      Controls 
  6262.      Menus 
  6263.      Undo 
  6264.  
  6265.  
  6266. ΓòÉΓòÉΓòÉ 8.1. Windows ΓòÉΓòÉΓòÉ
  6267.  
  6268. Windows are platform-specific data structures through which documents display 
  6269. themselves. This section discusses how to use OpenDoc window objects (which are 
  6270. basically wrappers for those structures) regardless of which platform you are 
  6271. developing for. 
  6272.  
  6273.  
  6274. ΓòÉΓòÉΓòÉ 8.1.1. Creating and Using Windows ΓòÉΓòÉΓòÉ
  6275.  
  6276. The OpenDoc class ODWindow is a wrapper for a pointer to a platform-specific 
  6277. window structure. For some operations, your part editor must retrieve the 
  6278. window pointer from the ODWindow object and use the platform's facilities. In 
  6279. most cases, however, the interface to ODWindow provides the capability you need 
  6280. for interacting with your windows. 
  6281.  
  6282.  
  6283. ΓòÉΓòÉΓòÉ 8.1.1.1. Window State Object ΓòÉΓòÉΓòÉ
  6284.  
  6285. There is a single instantiated window state object (class ODWindowState) for 
  6286. each OpenDoc session. The window state consists of a list of the currently 
  6287. existing window objects. You can access all open windows in a session through 
  6288. the window state. 
  6289.  
  6290. The document shell and dispatcher use the window state to pass events to parts 
  6291. so that they can activate themselves, handle user input, and adjust their menus 
  6292. as necessary. A part may be displayed in any number of frames, in any window of 
  6293. a document. The dispatcher uses the window state to make sure that it passes 
  6294. events to the correct part, no matter what window encloses the active frame and 
  6295. how many other frames the part has. 
  6296.  
  6297. Normally, your part editor calls the window state only when it creates new 
  6298. windows, when it needs access to a particular window, and when it needs access 
  6299. to the base menu bar object. 
  6300.  
  6301. If for some reason your part needs access to all windows, you can create an 
  6302. ODWindowIterator object, which gives you access to all windows referenced by 
  6303. the window state. 
  6304.  
  6305.  
  6306. ΓòÉΓòÉΓòÉ 8.1.1.2. Creating and Registering a Window ΓòÉΓòÉΓòÉ
  6307.  
  6308. In order to receive events in a window (except in the case of modal dialog 
  6309. boxes, to which you can pass an event filter routine), you must create an 
  6310. OpenDoc window object for it. Windows in OpenDoc are created and maintained 
  6311. through the window-state object, which you obtain from the session object. 
  6312.  
  6313. You first create a window with platform-specific calls; you then call the 
  6314. window state object to create an OpenDoc window object describing the 
  6315. platform-specific window. You call either of two methods: 
  6316.  
  6317.      You call the RegisterWindow method of ODWindowState when you create a 
  6318.       window that is not a root window or has never yet been written to 
  6319.       storage. 
  6320.  
  6321.      You call the call the RegisterWindowForFrame method of ODWindowState when 
  6322.       you create a root window from a previously stored root frame. 
  6323.       (RegisterWindowForFrame takes fewer parameters than RegisterWindow 
  6324.       because the frame passed in with the method already contains some of the 
  6325.       needed information). 
  6326.  
  6327.  A window has an is-root property. If the property is true, the root part of 
  6328.  the window is the root part of its document; in that case, the window is a 
  6329.  root window, which is the same as a document window. If a window's is-root 
  6330.  property is false, the window is a part window that has been opened from a 
  6331.  source frame within a root window. The document associated with a document 
  6332.  window is kept open as long as the document window is open. (OpenDoc permits 
  6333.  multiple document windows for a single document, as long as the root part 
  6334.  provides a user interface to support it). The document shell closes a document 
  6335.  when its last document window is closed. 
  6336.  
  6337.  Windows also have a should-save property that, if true, specifies that the 
  6338.  state of the window is saved persistently after the window closes. Usually, 
  6339.  only document windows should be marked as should-save. 
  6340.  
  6341.  The creator of a window can specify the view type and presentation of the root 
  6342.  frame, the frame that displays the root part. The view type specifies whether 
  6343.  the root part should draw itself as an icon, and the presentation specifies 
  6344.  what kind of appearance the part content should have if not drawn as an icon. 
  6345.  View type and presentation are suggestions to the part editor that draws 
  6346.  within that frame. View type and presentation are described in more detail in 
  6347.  Defining General Display Characteristics. 
  6348.  
  6349.  OpenDoc assumes that each window has a single canvas, attached to its root 
  6350.  facet, the facet created for the root frame. On the OpenDoc platform, the root 
  6351.  frame in the window has the same shape as the window's content region. 
  6352.  
  6353.  Your part should create windows as invisible and then made visible as 
  6354.  described in Opening a Window. 
  6355.  
  6356.  
  6357. ΓòÉΓòÉΓòÉ 8.1.1.3. Opening a Window ΓòÉΓòÉΓòÉ
  6358.  
  6359. After creating a window, your part editor typically makes calls to these three 
  6360. methods, in this order: 
  6361.  
  6362.    1. The window's Open method, which creates the root facet 
  6363.    2. The window's Show method, which makes the window visible 
  6364.    3. The window's Select method, which brings the window to the front 
  6365.  
  6366.  
  6367. ΓòÉΓòÉΓòÉ 8.1.1.4. Window IDs ΓòÉΓòÉΓòÉ
  6368.  
  6369. Your part editor should not maintain references to ODWindow objects for 
  6370. accessing OpenDoc windows, because the document shell or the window state 
  6371. object can close a window and invalidate the reference. Instead, the window 
  6372. state assigns window IDs that are valid for the length of a session. Use the 
  6373. window's GetID method to get the ID of a window when you create it, and then 
  6374. pass that ID to the window state's AcquireWindow method for subsequent access 
  6375. to the window. 
  6376.  
  6377.  
  6378. ΓòÉΓòÉΓòÉ 8.1.1.5. Closing a Window ΓòÉΓòÉΓòÉ
  6379.  
  6380. If your part editor needs to close a window programmatically, it calls the 
  6381. window's CloseAndRemove method. That method closes the window, releases the 
  6382. window object and disposes of the platform-specific window structure, deletes 
  6383. the root facet and canvas, and removes the root frame from the document. It 
  6384. also makes any necessary platform-specific calls to dispose of the window 
  6385. itself. 
  6386.  
  6387.  
  6388. ΓòÉΓòÉΓòÉ 8.1.1.6. Storing and Retrieving Window Characteristics ΓòÉΓòÉΓòÉ
  6389.  
  6390. Whenever a document is saved, OpenDoc writes certain information into the 
  6391. storage unit of the window's root frame. The window's bounding rectangle, 
  6392. title, and other characteristics are saved in a property of type 
  6393. kODPropWindowProperties in the frame's storage unit. 
  6394.  
  6395. When you create a root window, you retrieve that information from the stored 
  6396. frame, and use it to specify the platform-specific window's characteristics. 
  6397. You can use functions of the WinUtils utility library (provided with OpenDoc) 
  6398. to extract that information, or you can access the frame's storage unit 
  6399. directly. The kODPropWindowProperties property contains a persistent reference 
  6400. to another storage unit, which contains the following properties: 
  6401.  
  6402.      kODPropShouldShowlinks 
  6403.      kODPropSourceFrame 
  6404.      kODPropWindowHasCloseBox 
  6405.      kODPropWindowIsFloating 
  6406.      kODPropWindowIsResizable 
  6407.      kODPropWindowIsRootWindow 
  6408.      kODPropWindowIsVisible 
  6409.      kODPropWindowProcID 
  6410.      kODPropWindowRect 
  6411.      kODPropWindowRefCon 
  6412.      kODPropWindowTitle 
  6413.  
  6414.  Making sure a window is on screen 
  6415.  If your part is a root part that recreates a previously stored document 
  6416.  window, you must make sure that the window is visible onscreen. Your document 
  6417.  may have been moved from one system to another with a different monitor 
  6418.  configuration or size. You may need to move or resize the window to fit its 
  6419.  new environment. 
  6420.  
  6421.  
  6422. ΓòÉΓòÉΓòÉ 8.1.1.7. Open Method of your Part Editor ΓòÉΓòÉΓòÉ
  6423.  
  6424. Opening your part means creating a window for it and displaying it in the 
  6425. window. 
  6426.  
  6427. Your part itself initiates the opening of a window when the user selects the 
  6428. Open as window command from the View menu (see View Menu), and when it creates 
  6429. its own dialog boxes. Otherwise, your part opens a window only when your part's 
  6430. Open method is called. This is the interface to the Open method: 
  6431.  
  6432. ODID Open(in ODFrame frame);
  6433.  
  6434. The Open method is called in these circumstances. 
  6435.  
  6436.      When your part is initially created from a template-meaning that it has 
  6437.       no previously stored frame or window information-OpenDoc calls your 
  6438.       part's Open method and passes a null value kODNULL for the frame 
  6439.       parameter. 
  6440.  
  6441.      When your part is an embedded part whose frame is selected, and the user 
  6442.       chooses the Open selection command from the Edit menu, your containing 
  6443.       part calls your part's Open method and passes a reference to the selected 
  6444.       frame in the frame parameter. 
  6445.  
  6446.      When your part is the active part, and the user chooses the Open as 
  6447.       window command from the View menu, you call your part's Open method 
  6448.       passing in your frame. 
  6449.  
  6450.      When your part is the root part of a document being opened, OpenDoc calls 
  6451.       your part's Open method and passes a reference to the root frame in the 
  6452.       frame parameter. 
  6453.  
  6454.  In your implementation of Open, you can take steps similar to the following, 
  6455.  depending on the circumstances under which it was called. 
  6456.  
  6457.    1. If you are creating an initial window (frame = null), skip this step and 
  6458.       go to step 2. 
  6459.  
  6460.           If you are opening a frame into a part window (frame = an embedded 
  6461.            frame), check to see if the window already exists. If you have 
  6462.            created the part window previously and saved its window ID, pass 
  6463.            that ID to the AcquireWindow method of the window state object. If 
  6464.            the method returns a valid window, bring the window to the front and 
  6465.            exit. If the window does not yet exist, go to step 2. 
  6466.  
  6467.           If you are opening a stored document into a window (frame = a root 
  6468.            frame), read in the saved window data from the storage unit of the 
  6469.            frame passed to the method (see Storing and Retrieving Window 
  6470.            Characteristics). 
  6471.  
  6472.    2. Create a platform-specific window and register it with the window state 
  6473.       object, as described in Creating and Registering a Window. 
  6474.  
  6475.           If you are opening a stored document into a window, apply the stored 
  6476.            characteristics to the platform-specific window. Call the window 
  6477.            state object's RegisterWindowForFrame method. 
  6478.  
  6479.           If you are opening a frame into a window or creating an initial 
  6480.            window, apply your default characteristics to the platform-specific 
  6481.            window. Call the window state object's RegisterWindow method. 
  6482.  
  6483.    3. Get the window's window ID and save it for future reference. 
  6484.  
  6485.    4. Open and bring the window to the front, as described in Opening a Window. 
  6486.       If you are opening a stored document into a window, skip this step 
  6487.       because there may be more than one window to open and OpenDoc determines 
  6488.       which window is to be in front. 
  6489.  
  6490.  Note:  You are not absolutely required to open a window when your Open method 
  6491.         is called. Your part does whatever is appropriate, given its nature and 
  6492.         the conditions under which the method is called. For example, if your 
  6493.         part is a very simple sound player, it might simply play its sound and 
  6494.         never create a window. 
  6495.  
  6496.  
  6497. ΓòÉΓòÉΓòÉ 8.1.2. Handling Window Events ΓòÉΓòÉΓòÉ
  6498.  
  6499. To receive events in its windows that it creates, your part must create an 
  6500. ODWindow object for each platform-specific window it uses, including dialog 
  6501. boxes (except for modal dialog boxes; see Modal Dialog Boxes). 
  6502.  
  6503. The document shell handles most window events outside of the content region of 
  6504. the window. Nevertheless, the OpenDoc dispatcher first sends a kODEvtWindow 
  6505. event to the root part. If the part editor of the root part wishes to override 
  6506. the action the document shell would otherwise take, it can intercept and act on 
  6507. the event. 
  6508.  
  6509. If your part handles a window event, its HandleEvent method must return true. 
  6510. If it does not handle an event, its HandleEvent method must return false so 
  6511. that the document shell can handle the event. 
  6512.  
  6513.  
  6514. ΓòÉΓòÉΓòÉ 8.1.2.1. Resizing ΓòÉΓòÉΓòÉ
  6515.  
  6516. The document shell usually resizes windows, although the root part can 
  6517. intercept and handle the event. The document shell relies on default size 
  6518. limits for windows, so if your part allows-for example-very small window sizes, 
  6519. it may have to intercept this event and handle the resizing itself (by calling 
  6520. AdjustWindowShape). 
  6521.  
  6522. When a window is resized, the active part does not change, but the part editor 
  6523. for the root frame is informed of the resizing through calls by OpenDoc to its 
  6524. FrameShapeChanged and GeometryChanged methods. The root part can then do any 
  6525. necessary invalidation and subsequent redrawing, including creation of new 
  6526. facets if embedded parts have become visible due to the resizing. 
  6527.  
  6528.  
  6529. ΓòÉΓòÉΓòÉ 8.1.2.2. Closing ΓòÉΓòÉΓòÉ
  6530.  
  6531. The document shell handles a mouse click in the Close icon of a window or user 
  6532. action of Close or its keyboard equivalent. The document shell closes the 
  6533. window, after which the window cannot be reopened. 
  6534.  
  6535. If the window is a document window and is the only one open for that document, 
  6536. the document shell closes the document. 
  6537.  
  6538. If your part editor needs to close a window programmatically, it can call the 
  6539. window's CloseAndRemove method. The window is closed and the window object is 
  6540. released. 
  6541.  
  6542.  
  6543. ΓòÉΓòÉΓòÉ 8.1.2.3. Dragging ΓòÉΓòÉΓòÉ
  6544.  
  6545. The document shell handles some platform-specific window-moving actions, such 
  6546. as dragging of a window by its title bar. No event-handling is required of the 
  6547. window's root part. 
  6548.  
  6549. Parts in other windows may need to be updated because of the window's move; 
  6550. they receive update events as appropriate. 
  6551.  
  6552.  
  6553. ΓòÉΓòÉΓòÉ 8.1.3. Modal Dialog Boxes ΓòÉΓòÉΓòÉ
  6554.  
  6555. When your part editor displays a modal dialog box, it does not need to create 
  6556. an ODWindow object, as with a regular window. However, it should still request 
  6557. the modal focus (using its own display frame as the modal-focus owner), and it 
  6558. can still receive events by providing an event filter 
  6559.  
  6560. In addition, to ensure that floating windows are properly deactivated, your 
  6561. part must deactivate the front window before displaying a Modal dialog and it 
  6562. must reactivate the front window after dismissing it. 
  6563.  
  6564. Your part can create and register its own dialog window, request the modal 
  6565. focus for the window's root frame, and handle the dialog box. 
  6566.  
  6567.  
  6568. ΓòÉΓòÉΓòÉ 8.1.3.1. Acquiring and Relinquishing the Modal Focus ΓòÉΓòÉΓòÉ
  6569.  
  6570. A frame displaying a modal dialog box should own the modal focus, a focus type 
  6571. that exists to constrain certain events. 
  6572.  
  6573. For example, a mouse click outside the frame that has the modal focus still 
  6574. goes to that frame. If your part's frame has the modal focus and the user 
  6575. clicks outside the frame, your part's HandleEvent method is called and passed a 
  6576. facet of kODNULL. The method should check for a null facet in this situation 
  6577. and either alert the user with a beep or dismiss the dialog box, as 
  6578. appropriate. 
  6579.  
  6580. A click in a frame embedded within the frame that has the modal focus goes to 
  6581. the embedded frame. This behavior facilitates the construction of dialog boxes 
  6582. and other controls from multiple parts. 
  6583.  
  6584. Your part obtains and relinquishes the modal focus as it does other foci, as 
  6585. described in Requesting Foci and Relinquishing Foci. 
  6586.  
  6587. In general, your part should not be willing to relinquish the modal focus on 
  6588. request. If your part is displaying a modal dialog, you probably do not want 
  6589. any other modal dialog to be displayed at the same time. To make sure that your 
  6590. part holds on to the modal focus, your part editor's BeginRelinquishFocus 
  6591. method should return kODFalse if the requested focus is kODModalFocus and the 
  6592. proposed new owner of the focus is not one of your own display frames. 
  6593.  
  6594. When you have finished displaying a modal dialog box, you can directly transfer 
  6595. it to its previous owner by calling the arbitrator's TransferFocus method, as 
  6596. noted in Handling a Simple Modal Dialog Box. 
  6597.  
  6598.  
  6599. ΓòÉΓòÉΓòÉ 8.1.3.2. Event Filters ΓòÉΓòÉΓòÉ
  6600.  
  6601. With modal dialog boxes, your part editor's dialog-box event filter controls 
  6602. which events you receive while a dialog box or alert box is being displayed. To 
  6603. pass received null events, update events, and activate events on to OpenDoc or 
  6604. other windows for handling, your event filter can send them to the OpenDoc 
  6605. dispatcher by calling its Dispatch method. 
  6606.  
  6607. Your event filter should not pass other events, such as mouse events, to the 
  6608. dispatcher. 
  6609.  
  6610.  
  6611. ΓòÉΓòÉΓòÉ 8.1.3.3. Handling a Simple Modal Dialog Box ΓòÉΓòÉΓòÉ
  6612.  
  6613. To display a simple modal dialog box or Alert box, you can take these steps: 
  6614.  
  6615.    1. Get a reference to the frame that currently owns the modal focus by 
  6616.       calling the arbitrator's GetFocusOwner method. Request the modal focus 
  6617.       from the arbitrator, using its RequestFocus method. If you obtain the 
  6618.       focus, proceed. 
  6619.  
  6620.    2. Install your dialog event filter function. 
  6621.  
  6622.    3. Create the dialog box, using a Dialog Manager call such as GetNewDialog. 
  6623.  
  6624.    4. To handle floating windows properly, deactivate the currently active 
  6625.       window by calling DeactivateFrontWindow method of the window state 
  6626.       object. 
  6627.  
  6628.    5. Handle the dialog box with a Dialog Manager call such as ModalDialog. Act 
  6629.       on the results and, when finished, dispose of the dialog box with a 
  6630.       Dialog Manager call such as DisposeDialog. 
  6631.  
  6632.    6. Reactivate the previously active window (to restore floating windows), by 
  6633.       calling the window state's ActivateFrontWindows method. 
  6634.  
  6635.    7. Remove your dialog event filter function. 
  6636.  
  6637.    8. Restore the modal focus to its previous owner by calling the arbitrator's 
  6638.       TransferFocus method. 
  6639.  
  6640.  By always saving and restoring the owner of the modal focus, your part can use 
  6641.  this approach for nested modal dialog boxes, such as a dialog box that is 
  6642.  built from several embedded parts. 
  6643.  
  6644.  
  6645. ΓòÉΓòÉΓòÉ 8.1.3.4. Handling a Movable Modal Dialog Box ΓòÉΓòÉΓòÉ
  6646.  
  6647. In OpenDoc, to implement a full-featured movable modal dialog box-that is, one 
  6648. that allows process switching-you must create a window object (ODWindow) to 
  6649. contain it. To display a movable modal dialog box, you can take these steps: 
  6650.  
  6651.    1. Use the appropriate methods to create the structures for the dialog box. 
  6652.  
  6653.    2. Create a window object, using the window state's RegisterWindow method. 
  6654.       Give it properties appropriate for your modal dialog, such as floating, 
  6655.       nonpersistent and floating. 
  6656.  
  6657.    3. Request the modal focus for the root frame of the dialog window. 
  6658.  
  6659.    4. Adjust menus, as necessary, for the presence of the dialog box. 
  6660.  
  6661.    5. Call the Open, Show, and Select methods of the modal dialog window. 
  6662.  
  6663.    6. Handle events in the dialog box through your normal event-handling 
  6664.       mechanism. 
  6665.  
  6666.  To make sure you dismiss the modal dialog box at the right time, you can take 
  6667.  actions such as these when you receive a mouse-down event in the dialog box: 
  6668.  
  6669.    1. Determine whether the event applies to your dialog and, if so, what item 
  6670.       the user selected. 
  6671.  
  6672.    2. If the user chose to close the dialog box, relinquish the modal focus and 
  6673.       call the window's CloseAndRemove method to delete the window and its root 
  6674.       frame. 
  6675.  
  6676.    3. Re-enable any menus or menu items that you disabled for display during of 
  6677.       the dialog box. 
  6678.  
  6679.       Note:  It is also possible to create a modal dialog box that is movable, 
  6680.              but does not support process switching, by using a filter function 
  6681.              and other functions in a utility library (DlogUtil) provided with 
  6682.              OpenDoc. 
  6683.  
  6684.  
  6685. ΓòÉΓòÉΓòÉ 8.1.4. Modeless Dialog Boxes ΓòÉΓòÉΓòÉ
  6686.  
  6687. Modeless dialog boxes are more like regular windows than modal dialogs are. 
  6688. They can be activated and deactivated, and they need not be dismissed for your 
  6689. part to become active and editable. 
  6690.  
  6691.  
  6692. ΓòÉΓòÉΓòÉ 8.1.4.1. Showing the Dialog Box ΓòÉΓòÉΓòÉ
  6693.  
  6694. To display a modeless dialog box in OpenDoc, you must create a window object 
  6695. (ODWindow) to contain it. To display the dialog box, you can take steps such as 
  6696. these: 
  6697.  
  6698.    1. In case the dialog window already exists, try to get a reference to it by 
  6699.       passing its ID (previously stored in your part) to the window state's 
  6700.       AcquireWindow method. If it does not yet exist, create the 
  6701.       platform-specific structures for the dialog box, and create a window 
  6702.       object with the window state's RegisterWindow method. Call the window's 
  6703.       Open method. 
  6704.  
  6705.    2. Call the window's Show and Select methods to make it visible and active. 
  6706.  
  6707.    3. If you do not already have the window ID of the dialog window, get it by 
  6708.       calling the window's GetID method. Save it for use in step 1 the next 
  6709.       time the user chooses the action that brings up the modeless dialog box. 
  6710.  
  6711.  
  6712. ΓòÉΓòÉΓòÉ 8.1.4.2. Closing the Dialog Box ΓòÉΓòÉΓòÉ
  6713.  
  6714. When the user clicks in the close box of a modeless dialog, you may hide the 
  6715. dialog window, rather than close it, so that it is not destroyed. This is an 
  6716. optimization that allows you to quickly display the dialog box again. 
  6717.  
  6718. In your part's HandleEvent method, you can respond in this general way to a 
  6719. mouse click within a window's close box: 
  6720.  
  6721.    1. From the frame or facet passed to HandleEvent, obtain information that 
  6722.       can identify the window. For example, get a reference to the window 
  6723.       object in which the event occurred (by calling the facet's GetWindow 
  6724.       method), or examine the frame's presentation or part info data for 
  6725.       identifying characteristics. 
  6726.  
  6727.    2. Compare that information to stored information that defines your modeless 
  6728.       dialog box. Get a reference to your modal dialog's window object (by 
  6729.       passing its ID to the window state's AcquireWindow method), for example, 
  6730.       or check a stored value that defines your modeless dialog's presentation. 
  6731.  
  6732.    3. If the two are the same, hide the window instead of closing it. 
  6733.  
  6734.  
  6735. ΓòÉΓòÉΓòÉ 8.1.4.3. Hiding a Dialog Box when Deactivating a Frame ΓòÉΓòÉΓòÉ
  6736.  
  6737. When your part is deactivated, it should hide any of its modeless dialog boxes. 
  6738.  
  6739. When your part relinquishes the selection focus, it can get a reference to the 
  6740. dialog window (by passing its ID to the window state's AcquireWindow method), 
  6741. call the window's IsShown method to see if it is currently being shown, and 
  6742. then save that shown state and hide the window. 
  6743.  
  6744. When your part reacquires the selection focus, it can retrieve a reference to 
  6745. the dialog window by passing its ID to the window state's AcquireWindow method. 
  6746. Then, if the dialog window had been visible at deactivation, your part can once 
  6747. again show it. 
  6748.  
  6749.  
  6750. ΓòÉΓòÉΓòÉ 8.2. Controls ΓòÉΓòÉΓòÉ
  6751.  
  6752. This section discusses what kinds of controls you construct them, and how to 
  6753. handle events within controls It also discusses two specific issues for 
  6754. palettes: how to share them among instances of your part, and how to use them 
  6755. to embed parts within your part. 
  6756.  
  6757.  
  6758. ΓòÉΓòÉΓòÉ 8.2.1. Design Issues for Controls ΓòÉΓòÉΓòÉ
  6759.  
  6760. Controls in OpenDoc have the same function as in conventional applications: 
  6761. they are graphical objects that allow the user to interact with and manipulate 
  6762. documents in a variety of ways. However, there are some differences: 
  6763.  
  6764.      In a conventional application, controls typically apply to the entire 
  6765.       document. They are always present unless dismissed explicitly. In an 
  6766.       OpenDoc document, however, each part may have its own set of controls, 
  6767.       and thus controls can appear and disappear rapidly as the user edits. 
  6768.       This rapid change can be irritating if not carefully managed. 
  6769.  
  6770.      In a conventional application, finding the space in which to display a 
  6771.       control may be less of a consideration than in OpenDoc. It may be a 
  6772.       challenge for small embedded parts to find sufficient space to  display 
  6773.       rulers, scroll bars, and palettes. 
  6774.  
  6775.      In OpenDoc, controls can be constructed as independent parts, assemblages 
  6776.       of parts, different frames of a single part, or content elements of a 
  6777.       part. This can give you more flexibility in constructing user-interface 
  6778.       elements than is possible for conventional applications. 
  6779.  
  6780.      OpenDoc controls can have attached scripts or can communicate with each 
  6781.       other, or with other parts, using the OpenDoc extension mechanism. This 
  6782.       gives OpenDoc controls the ability to be far more integrated and 
  6783.       context-sensitive than standard controls. 
  6784.  
  6785.  Standard types of controls you might wish to include with your parts include: 
  6786.  
  6787.      Push buttons, radio buttons, and checkboxes 
  6788.      Scroll bars and sliders, or other gauges 
  6789.      Pop-up menus 
  6790.      Rulers 
  6791.      Tool bars 
  6792.      Palettes 
  6793.  
  6794.  Rulers usually reflect some settings of the current selection context and 
  6795.  contain controls that allow the user to change these settings. Tool bars are 
  6796.  like rulers but they often trigger actions instead of changing settings. 
  6797.  Status bars display the progress of some long-running operation or suggest 
  6798.  actions to users. 
  6799.  
  6800.  In conventional applications, rulers and tool bars commonly occupy the margins 
  6801.  of the window. In an OpenDoc document, controls can be displayed at the 
  6802.  margins of the window, in separate frames outside of the embedded frame they 
  6803.  apply to, or within the frame they apply to. 
  6804.  
  6805.  A ruler for a text part, for example, can be an additional frame associated 
  6806.  with the part. Events in the ruler are handled by the part's editor. 
  6807.  Conversely, the ruler may be its own part with its own editor. In this case, 
  6808.  the text part editor must maintain a reference to the ruler part and be able 
  6809.  to communicate with it through semantic events or some other extension 
  6810.  mechanism. 
  6811.  
  6812.  A ruler that is a separate part can have its own embedded parts, such as 
  6813.  buttons. The ruler part must then be able to communicate with its embedded 
  6814.  controls as well as with the part that it services. 
  6815.  
  6816.  Palettes often contain editing tools but can also contain choices for object 
  6817.  attributes like color or line width. Palettes commonly float freely beside or 
  6818.  over the document, although they can also be fixed at the window margins. 
  6819.  Palettes might also pop up, pull down, or be torn off of menus. 
  6820.  
  6821.  If all parts in a document can communicate with each other, they can 
  6822.  coordinate the drawing and hiding of palettes or other controls to avoid 
  6823.  irritating the user. For example, all parts in a document can share a single 
  6824.  palette, within which the various parts negotiate for space and in which they 
  6825.  draw only those tools that must change as the active part changes. 
  6826.  
  6827.  
  6828. ΓòÉΓòÉΓòÉ 8.2.2. Handling Events in Controls ΓòÉΓòÉΓòÉ
  6829.  
  6830. How you handle events in a control are handled depends on how you design the 
  6831. control: 
  6832.  
  6833.      If a control like a ruler is within the active frame, it might not have 
  6834.       its own frame, and the active part editor handles any events in the 
  6835.       ruler. 
  6836.  
  6837.      If a control has its own frame, it might be another display frame of the 
  6838.       active part. In this case also, the active part editor handles the event 
  6839.       in the control. 
  6840.  
  6841.      If a control is a separate part, its own part editor handles the event 
  6842.       and updates the state of the part, which might trigger scripts or calls 
  6843.       to other parts' extension interfaces. Likewise, the part itself can 
  6844.       receive queries from other part editors in the form of semantic events or 
  6845.       calls to its extension interface. 
  6846.  
  6847.  
  6848. ΓòÉΓòÉΓòÉ 8.2.3. Sharing Palettes and Utility Windows ΓòÉΓòÉΓòÉ
  6849.  
  6850. The user-interface guidelines state that you should hide any visible palettes, 
  6851. modeless dialog boxes, or other utility windows when your part becomes inactive 
  6852. or its document closes, and restore them-in the same positions-when the part 
  6853. becomes active once again or the document reopens. In addition, if your part 
  6854. editor maintains multiple parts in a document and the active state switches 
  6855. from one to another of them, any visible utility windows that apply to both 
  6856. parts should remain steadily visible, without any flicker caused by hiding and 
  6857. immediate restoring. 
  6858.  
  6859. One way to implement this behavior for a utility window is to follow, in 
  6860. general, steps such as these: 
  6861.  
  6862.      Make the window globally accessible to your parts by keeping its 
  6863.       reference and its state in an object that each of your parts acquires on 
  6864.       initialization and releases on closing. 
  6865.  
  6866.      Have the global object create the window in a normal manner the first 
  6867.       time it is to be displayed. When the user closes the window, the global 
  6868.       object can simply hide it by calling its Hide method. If the user 
  6869.       subsequently needs to display the window again, the global object can 
  6870.       show it again by calling its Show method. 
  6871.  
  6872.      When your part relinquishes the selection focus, its 
  6873.       CommitRelinquishFocus method can check to see if the part that is 
  6874.       receiving the focus also belongs to your part editor, and has a 
  6875.       presentation that uses the same utility window. There are a number of 
  6876.       ways that you can check this, such as by examining the presentation of 
  6877.       the newly active frame. 
  6878.  
  6879.      When your part acquires the selection focus, it notifies the global 
  6880.       object of that fact. The global object, in turn calls the ChangePart and 
  6881.       SetSourceFrame methods of the utility window's frame to assign the new 
  6882.       part and frame to the utility window. The new part can then adjust the 
  6883.       content of the utility window if needed, and also show or hide other 
  6884.       palettes or dialogs. 
  6885.  
  6886.  
  6887. ΓòÉΓòÉΓòÉ 8.2.4. Using a Tool Palette to Embed Parts ΓòÉΓòÉΓòÉ
  6888.  
  6889. An example of an OpenDoc-specific use for controls is to allow the user to 
  6890. embed parts by selecting items from a palette. Using a palette in this way, 
  6891. your part can create embedded parts from scratch, rather than through reading 
  6892. in existing part data. 
  6893.  
  6894. Your part can provide a palette, menu, or dialog box from which the user 
  6895. selects an item that specifies a part kind. As in many conventional 
  6896. applications, your palette could display a set of tools to the user-drawing 
  6897. tools, painting tools, text tools, and so on. In this case, however, selecting 
  6898. an item from the palette actually means that a new part of that kind is to be 
  6899. embedded in your part. 
  6900.  
  6901. The items could represent existing template documents in the user's system, or 
  6902. they could simply represent individual part kinds for which editors exist. If 
  6903. you are creating parts from scratch, follow steps such as these once the user 
  6904. has made a selection from your palette: 
  6905.  
  6906.      Create the new part by calling your draft's CreatePart method, passing it 
  6907.       the part kind that the user selected. 
  6908.  
  6909.      Call the new part's Externalize method (see The Externalize Method), so 
  6910.       the part can create and write initial data to the properties in its 
  6911.       storage unit. 
  6912.  
  6913.      Create a new embedded frame for the part, as described in Creating a New 
  6914.       Embedded Frame. 
  6915.  
  6916.      Give the new frame the proper link status, as described in Frame Link 
  6917.       Status. 
  6918.  
  6919.      If the new frame is visible, assign facets to it, as described in Adding 
  6920.       a Facet. 
  6921.  
  6922.      Notify your containing part and your draft that there has been a change 
  6923.       to your part's content; see Making Content Changes Known. 
  6924.  
  6925.  
  6926. ΓòÉΓòÉΓòÉ 8.3. Menus ΓòÉΓòÉΓòÉ
  6927.  
  6928. At any given moment while an OpenDoc document is open, responsibility for the 
  6929. menu bar is shared among three entities. The operating system provides any 
  6930. system-wide menus, the OpenDoc document shell creates the Document menu, Edit 
  6931. menu, View menu and Help menu. Individual part editors can create other menus 
  6932. as needed. (Part editors can also, with restrictions, add appropriate items to 
  6933. the Document and Edit menus). 
  6934.  
  6935. Different platforms have different conventions for enabling and disabling menus 
  6936. and menu items. In an OpenDoc document, the document shell, the root part, and 
  6937. the part with the menu focus together control which menu commands are available 
  6938. to the user. As each part becomes active, the OpenDoc document shell and the 
  6939. root part update their own menu items, and the active part editor takes care of 
  6940. the rest. 
  6941.  
  6942. Basic event handling for menu events is described in Menu Events. When the user 
  6943. chooses a menu item, the document shell either handles the command itself or 
  6944. dispatches a menu event to the active part; the part receives the event as a 
  6945. call to its HandleEvent method. 
  6946.  
  6947. This section discusses general issues of setting up and working with menus and 
  6948. then describes how to handle individual menu events for the standard OpenDoc 
  6949. menus (the Document menu and the Edit menu): 
  6950.  
  6951.      Document 
  6952.      Edit 
  6953.      View 
  6954.      Help 
  6955.  
  6956.  
  6957. ΓòÉΓòÉΓòÉ 8.3.1. Setting Up Menus ΓòÉΓòÉΓòÉ
  6958.  
  6959. This section describes how your part editor can set up and use menus and menu 
  6960. items. 
  6961.  
  6962.  
  6963. ΓòÉΓòÉΓòÉ 8.3.1.1. Base Menu Bar ΓòÉΓòÉΓòÉ
  6964.  
  6965. When it first opens a document, the document shell creates a menu bar object 
  6966. (type ODMenuBar) and installs it as the base menu bar by calling the window 
  6967. state's SetBaseMenuBar method. The base menu bar contains different menu and 
  6968. items on different platforms, but the Document menu and the Edit menu are 
  6969. always installed. 
  6970.  
  6971.  
  6972. ΓòÉΓòÉΓòÉ 8.3.1.2. Base Pop-Up Menu ΓòÉΓòÉΓòÉ
  6973.  
  6974. On the OS/2 platform, the document shell also creates a pop-up menu object 
  6975. (type ODPopup) and installs it as the base pop-up menu by calling the window 
  6976. state's SetBasePopup method. The base pop-up menu always installs the Open as 
  6977. properties, Show as, and Help menu items. 
  6978.  
  6979.  
  6980. ΓòÉΓòÉΓòÉ 8.3.1.3. Adding Part Menus to the Base Menu Bar ΓòÉΓòÉΓòÉ
  6981.  
  6982. When your part initializes itself, or when it first obtains the menu focus, it 
  6983. should create its own menu bar object by: 
  6984.  
  6985.    1. Copying the base menu bar using the window state's CopyBaseMenuBar 
  6986.       method. 
  6987.    2. Adding its own menu structures, by using menu-bar methods such as 
  6988.       AddMenuBefore and AddMenuLast. 
  6989.  
  6990.  If absolutely necessary, your part editor can add items to the end of the 
  6991.  Document and Edit menus, but you should not alter the existing items. 
  6992.  
  6993.  
  6994. ΓòÉΓòÉΓòÉ 8.3.1.4. Menu IDs ΓòÉΓòÉΓòÉ
  6995.  
  6996. You must identify each menu with a menu ID. A menu ID is a positive short; 
  6997. negative values are reserved by the operating system. 
  6998.  
  6999. All menus in the menu bar must have unique menu IDs. Therefore the document 
  7000. shell, the active part, and any shell plugs-in or services that also have menus 
  7001. must cooperate to ensure that there are no conflicts. Please follow the 
  7002. conventions listed in the following table list to ensure that your menu IDs do 
  7003. not conflict with those of others. 
  7004.  
  7005. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7006. ΓöéType of Software         ΓöéMenu ID Range                      Γöé
  7007. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7008. ΓöéDocument shell           Γöé0x0000 - 0x2FFF                    Γöé
  7009. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7010. ΓöéPart editors (when root) Γöé0x3000 - 0x3FFF                    Γöé
  7011. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7012. ΓöéShell plug-in/services   Γöé0x4000 - 0x4FFF                    Γöé
  7013. Γöé                         ΓöéNote: These menu IDs must be       Γöé
  7014. Γöé                         Γöédynamically assigned.              Γöé
  7015. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7016. ΓöéPart editors             Γöé0x5000 - 0x7FFF                    Γöé
  7017. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7018.  
  7019. A shell plug-in or service may have to adjust its menu ID dynamically at 
  7020. runtime, because another service or plug-in with that menu ID may already be 
  7021. installed. The plug-in should choose an ID, look for an installed menu with 
  7022. that ID, and-if it is found-add 1 to the ID and try again. 
  7023.  
  7024.  
  7025. ΓòÉΓòÉΓòÉ 8.3.1.5. Obtaining the Menu Focus ΓòÉΓòÉΓòÉ
  7026.  
  7027. When your part activates itself, it should request the menu focus (along with 
  7028. other foci) if it wants to use menus. See Requesting Foci for more information. 
  7029.  
  7030.  
  7031. ΓòÉΓòÉΓòÉ 8.3.1.6. Enabling and Disabling Menus and Commands ΓòÉΓòÉΓòÉ
  7032.  
  7033. When the user clicks in the menu bar, the OpenDoc dispatcher determines which 
  7034. part has the menu focus and calls that part's AdjustMenus method. It also calls 
  7035. the root part's AdjustMenus method, if the root part does not have the menu 
  7036. focus. 
  7037.  
  7038. Your part's AdjustMenus method can use methods of the menu bar object such as 
  7039. EnableCommand or EnableAndCheckCommand to change the appearance of your menu 
  7040. items, or it can make platform-specific calls to directly enable, disable, 
  7041. mark, or change the text of its menu items. 
  7042.  
  7043. Your AdjustMenus method typically acquires the clipboard focus and enables the 
  7044. Cut, Copy, Paste, and Paste as... items in the Edit menu. 
  7045.  
  7046.  
  7047. ΓòÉΓòÉΓòÉ 8.3.1.7. Menus and Read-Only Documents ΓòÉΓòÉΓòÉ
  7048.  
  7049. When your part permissions (see Drafts) specify that your document is 
  7050. read-only, your part editor needs to disable these menu commands: 
  7051.  
  7052.      Cut, Paste, Paste as..., and Delete items in the Edit menu 
  7053.  
  7054.      any part-specific content-editing commands 
  7055.  
  7056.  This situation can occur when the user views an early draft of a document, or 
  7057.  when a document is stored on read-only media. 
  7058.  
  7059.  Part viewers should disable these items and commands at all times. 
  7060.  
  7061.  
  7062. ΓòÉΓòÉΓòÉ 8.3.1.8. Menus and the Root Part ΓòÉΓòÉΓòÉ
  7063.  
  7064. In all OpenDoc documents, the root part is responsible for printing. The root 
  7065. part therefore should handle the Print document item from the Document menu, 
  7066. even if an embedded part has the menu focus. If the root part is a container, 
  7067. it is also responsible for opening an icon, tree, or details view of itself. 
  7068.  
  7069. To allow the root part access to these menu events, the dispatcher passes menu 
  7070. events to the root part if they are not handled by the part with the menu 
  7071. focus. Also, OpenDoc calls the root part's AdjustMenus method before it calls 
  7072. the AdjustMenus method of the part with the menu focus, so that the root part 
  7073. can adjust the state of those menu items. 
  7074.  
  7075. When your part's AdjustMenus method is called, it should check to see if your 
  7076. part is the root part and whether it has the menu focus. If it is the root part 
  7077. but does not have the menu focus, it should adjust only the Open as and Print 
  7078. document items from the Document menu. If it is an embedded part with the menu 
  7079. focus, it should not adjust those items. 
  7080.  
  7081. Likewise, when your part's HandleEvent method is called, it should first check 
  7082. to see if your part is the root part. If it is the root part, HandleEvent 
  7083. should return false if it is passed any menu events other than the Print 
  7084. document item and the Icons, Tree, or Details items of the Open as submenu in 
  7085. the Document menu. If it is an embedded part, HandleEvent should return false 
  7086. if it is passed Page setup or Print document. 
  7087.  
  7088.  
  7089. ΓòÉΓòÉΓòÉ 8.3.2. Document Menu ΓòÉΓòÉΓòÉ
  7090.  
  7091. This section describes how your part editor should interact with the Document 
  7092. menu. The OpenDoc document shell handles most Document menu commands, as 
  7093. described in Handling the Document Menu. Individual part editors must respond 
  7094. only to the Open as and Print document commands. 
  7095.  
  7096.  
  7097. ΓòÉΓòÉΓòÉ 8.3.2.1. Open as ΓòÉΓòÉΓòÉ
  7098.  
  7099. The user chooses the Open as (in an OpenDoc document) into its window. 
  7100.  
  7101. The root part handles this command. It should display one of the user selected 
  7102. views (icons, tree, or details) using the ODViewExtension class. 
  7103.  
  7104. Your part does not need to support this command if it is not a container. 
  7105.  
  7106.  
  7107. ΓòÉΓòÉΓòÉ 8.3.2.2. Print document ΓòÉΓòÉΓòÉ
  7108.  
  7109. The root part of the window handles the Print document command. Root parts are 
  7110. responsible for defining the printing behavior of their documents. When the 
  7111. user chooses this command and your part is the root part of the active window, 
  7112. OpenDoc passes the command OD_PRINT to your part's HandleEvent method. If the 
  7113. root part does not handle the event, the document shell prints the document. 
  7114. The document shell prints only the visible content of the root frame and its 
  7115. embeds. If your part supports multiple pages or its content area is greater 
  7116. that its frame, you need to handle the print command yourself. 
  7117.  
  7118. Your routine to handle the Print document command should set up for printing. 
  7119.  
  7120.  
  7121. ΓòÉΓòÉΓòÉ 8.3.3. Edit Menu ΓòÉΓòÉΓòÉ
  7122.  
  7123. Most items in the Edit menu are handled by individual part editors. Most apply 
  7124. to the current selection in the currently active part. 
  7125.  
  7126. Choices on the Edit menu are as follows: 
  7127.  
  7128.      Undo 
  7129.      Redo 
  7130.      Create 
  7131.      Cut 
  7132.      Copy 
  7133.      Paste 
  7134.      Paste as... 
  7135.      Paste link 
  7136.      Break link 
  7137.      Delete 
  7138.      Select all 
  7139.      Deselect all 
  7140.      Open selection 
  7141.      Selection properties 
  7142.      Show selection as 
  7143.  The following figure shows the Edit menu. 
  7144.  
  7145.  Each item is explained in detail in the following sections. 
  7146.  
  7147.  
  7148. ΓòÉΓòÉΓòÉ 8.3.3.1. Undo ΓòÉΓòÉΓòÉ
  7149.  
  7150. The user selects Undo from the Edit menu in order to reverse recently enacted 
  7151. user actions, including previous uses of Undo or Redo. Undo reverses the 
  7152. effects of the last undoable user action and restores all parts to their states 
  7153. before that action. Not all user actions are undoable. OpenDoc supports 
  7154. multiple levels of Undo. For example, if the user selects Undo three times in 
  7155. succession, then the last three undoable actions are undone in order. 
  7156.  
  7157. The document shell handles the Undo item, passing control to the Undo object. 
  7158. The Undo object, in turn, calls the UndoAction method of any part editors 
  7159. involved in the Undo. 
  7160.  
  7161. Your part should respond to Undo as described in Undo. 
  7162.  
  7163.  
  7164. ΓòÉΓòÉΓòÉ 8.3.3.2. Redo ΓòÉΓòÉΓòÉ
  7165.  
  7166. The user selects Redo from the Edit menu in order to reverse the last use of 
  7167. Undo. Redo is available only if the last undoable user action was Undo or Redo. 
  7168. Redo reverses the effects of the last undoable user action, restoring all parts 
  7169. to their states before the Undo action. OpenDoc supports multiple levels of 
  7170. Redo. Each time the user selects Redo, the previous Undo is redone. This works 
  7171. only if the user had invoked Undo multiple times in succession. 
  7172.  
  7173. The document shell handles the Redo item, passing control to the Redo object. 
  7174. The Redo object, in turn, calls the RedoAction method of any part editors 
  7175. involved in the Redo. 
  7176.  
  7177. Your part should respond to Redo as described in Undo. 
  7178.  
  7179.  
  7180. ΓòÉΓòÉΓòÉ 8.3.3.3. Create ΓòÉΓòÉΓòÉ
  7181.  
  7182. The user selects Create to create a new part of the same type as the selected 
  7183. part. The part will be created on the clipboard. When Create is selected, the 
  7184. Paste link menu item and the Paste Link push button in the Paste As... dialog 
  7185. should be grayed because linking is not possible at this point. 
  7186.  
  7187.  
  7188. ΓòÉΓòÉΓòÉ 8.3.3.4. Cut, Copy, and Paste ΓòÉΓòÉΓòÉ
  7189.  
  7190. The user selects Cut, Copy, or Paste from the Edit menu in order to place data 
  7191. onto the clipboard or retrieve data from the clipboard. 
  7192.  
  7193. The Cut, Copy, and Paste choices are familiar mechanisms for copying and moving 
  7194. content around in the system. In OpenDoc, function has been added for handling 
  7195. embedded parts. The function added consists of: 
  7196.  
  7197.      Operating on parts in addition to intrinsic content. The parts may be 
  7198.       represented as frames or icons. 
  7199.  
  7200.      Making embed versus incorporate decisions. 
  7201.  
  7202.      Wrapping intrinsic content inside a part in certain circumstances. 
  7203.  
  7204.  Your part should disable the Cut and Paste items when its draft permissions 
  7205.  are read-only; see Menus and Read-Only Documents. 
  7206.  
  7207.  
  7208. ΓòÉΓòÉΓòÉ 8.3.3.5. Paste as... ΓòÉΓòÉΓòÉ
  7209.  
  7210. The user selects Paste as... from the Edit menu in order to specify the manner 
  7211. in which clipboard data is to be pasted into the active part. 
  7212.  
  7213. The Paste as... choice displays a dialog box that allows the user to specify 
  7214. the data format for pasting the clipboard into the destination. The clipboard 
  7215. content is converted to the user-specified format, and links to it can be 
  7216. created. Edit Menu lists the kinds of pasting that the user can specify. When 
  7217. the user selects the command, OpenDoc passes the command information to your 
  7218. part's HandleEvent method. 
  7219.  
  7220. Your routine to handle the Paste as... command should prepare to read from the 
  7221. clipboard, like this: 
  7222.  
  7223.    1. Acquire the clipboard focus and gain access to its content storage unit, 
  7224.       following the initial steps described in Pasting from the Clipboard. 
  7225.  
  7226.    2. Display the Paste As... dialog box, by calling the ShowPasteAsDialog 
  7227.       method of the clipboard object. Pass the function the active frame into 
  7228.       which the paste is to occur. 
  7229.  
  7230.    3. If the method returns kODTrue, the user has pressed the OK button; use 
  7231.       the results of the interaction to determine which kind of pasting action 
  7232.       to take. Then read the appropriate kind of data from the clipboard, 
  7233.       continuing with the procedures shown in Pasting from the Clipboard. 
  7234.  
  7235.  
  7236. ΓòÉΓòÉΓòÉ 8.3.3.6. Paste link ΓòÉΓòÉΓòÉ
  7237.  
  7238. The user chooses the Paste link command from the Edit menu in order to insert 
  7239. the link from the clipboard into your part. 
  7240.  
  7241. In your routine to handle paste link, you should: 
  7242.  
  7243.    1. Create an empty "linkspec" 
  7244.    2. Read in the "linkspec" from the clipboard 
  7245.    3. Create a link from the "linkspec" 
  7246.  
  7247.  
  7248. ΓòÉΓòÉΓòÉ 8.3.3.7. Break link ΓòÉΓòÉΓòÉ
  7249.  
  7250. The user selects Break link to copy the source information to the document and 
  7251. break the link with the source. The action cannot be undone. A confirmation 
  7252. dialog will be given before the link is broken. The Break link choice is for 
  7253. destination links only. 
  7254.  
  7255.  
  7256. ΓòÉΓòÉΓòÉ 8.3.3.8. Delete selection ΓòÉΓòÉΓòÉ
  7257.  
  7258. The user selects Delete selection to delete the selected content from the 
  7259. active part. 
  7260.  
  7261. Your routine to handle the Delete selection command should remove the items 
  7262. that make up the selection from your part content. That may involve deleting 
  7263. embedded parts as well as intrinsic content. 
  7264.  
  7265.  
  7266. ΓòÉΓòÉΓòÉ 8.3.3.9. Select all ΓòÉΓòÉΓòÉ
  7267.  
  7268. The user selects Select all from the Edit menu to make the current selection 
  7269. encompass all of the content of the active part. 
  7270.  
  7271. Your routine to handle the Select all command must include all of your part's 
  7272. content in the selection structure that you maintain and it must highlight the 
  7273. visible parts of it appropriately. 
  7274.  
  7275.  
  7276. ΓòÉΓòÉΓòÉ 8.3.3.10. Deselect all ΓòÉΓòÉΓòÉ
  7277.  
  7278. The user selects Deselect all from the Edit menu to deselect all the content of 
  7279. the active part. 
  7280.  
  7281. Your routine to handle the Deselect all command must include all of your part's 
  7282. content in the selection structure that you maintain and it must highlight the 
  7283. visible parts of it appropriately. 
  7284.  
  7285.  
  7286. ΓòÉΓòÉΓòÉ 8.3.3.11. Selection properties ΓòÉΓòÉΓòÉ
  7287.  
  7288. The user chooses the Selection properties command from the Edit menu to display 
  7289. the Properties notebook containing standard information about the current 
  7290. selected embedded parts. When the user chooses the command, OpenDoc passes the 
  7291. command information to your active part's HandleEvent method. Your routine to 
  7292. handle the Selection properties command should display the Properties notebook 
  7293. that describes the characteristics of the current selection. 
  7294.  
  7295. In your routine to handle the Selection properties command, you can take the 
  7296. following steps, 
  7297.  
  7298.      If the current selection is an embedded frame border, display the 
  7299.       Properties notebook for the part in that frame, using the 
  7300.       ShowPartFrameInfo method of the info object (class ODInfo). You obtain a 
  7301.       reference to the Info object by calling the session object's GetInfo 
  7302.       method. OpenDoc handles all changes made by the user and updates the 
  7303.       information in the storage units for the embedded part and frame, 
  7304.       including performing any requested translation. 
  7305.  
  7306.       OpenDoc determines the information it displays in the Properties notebook 
  7307.       by reading the part's Info properties, the set of properties-separate 
  7308.       from the part's contents-that can be displayed to, and in some cases, 
  7309.       changed by the user. All stored parts include them. If your part creates 
  7310.       an extension to the Properties notebook (see The Settings Extension), it 
  7311.       can define and display additional properties. Your routine should support 
  7312.       both single and multiple selection. 
  7313.  
  7314.  
  7315. ΓòÉΓòÉΓòÉ 8.3.3.12. Open selection ΓòÉΓòÉΓòÉ
  7316.  
  7317. The user chooses the Open selection command from the Edit menu to open the 
  7318. selected embedded parts within a window. When the user chooses this command, 
  7319. OpenDoc passes the command to your active part's HandleEvent method. Your 
  7320. routine to handle Open selection should do the following: 
  7321.  
  7322.    1. From your private data structures, determine which of your embedded 
  7323.       frames is the selected one. (Each embedded part, even if displayed in an 
  7324.       icon view type, has a frame). 
  7325.  
  7326.    2. Call the AcquirePart method of the selected frame, followed by the Open 
  7327.       method of the part returned by the AcquirePart method. The Open method is 
  7328.       described in Open Method of your Part Editor. 
  7329.  
  7330.  Your routine should support both single and multiple selection. 
  7331.  
  7332.  
  7333. ΓòÉΓòÉΓòÉ 8.3.3.13. Show selection as ΓòÉΓòÉΓòÉ
  7334.  
  7335. The user chooses the Show selection as command from the Edit menu to change the 
  7336. view type of the selected embedded parts into large icons, small icons, 
  7337. thumbnails, or frames. When the user chooses this command, OpenDoc passes the 
  7338. command to your active part's HandleEvent method. Your routine to handle Show 
  7339. selection as should do the following: 
  7340.  
  7341.    1. For each embeded selection frame, obtain a reference to the part that 
  7342.       owns the frame. 
  7343.  
  7344.    2. Call that frame's ChangeViewType method, passing in the view type choosen 
  7345.       by the user. 
  7346.  
  7347.  
  7348. ΓòÉΓòÉΓòÉ 8.3.4. View Menu ΓòÉΓòÉΓòÉ
  7349.  
  7350. The View menu shows the views of the active part or controls the display of 
  7351. related windows like tool bars or palettes. All container parts should support 
  7352. Icons, Tree, and Details views. 
  7353.  
  7354. The View choices are as follows: 
  7355.  
  7356.      Show frame outline 
  7357.      Open as 
  7358.      Properties 
  7359.      Show as 
  7360.      Show links 
  7361.  The following figure shows the View menu. 
  7362.  
  7363.  Each item is explained in detail in the following sections. 
  7364.  
  7365.  
  7366. ΓòÉΓòÉΓòÉ 8.3.4.1. Show frame outline ΓòÉΓòÉΓòÉ
  7367.  
  7368. The user selects this command to reposition your part's content-that is, to 
  7369. change the portion of it displayed in the frame in the document window. In the 
  7370. part window, display a 1-pixel wide black-and-white border around the content 
  7371. currently visible in the display frame in the document window, and allow the 
  7372. user to drag the frame outline. 
  7373.  
  7374. This appears in the View menu for parts opened into a window. When it is 
  7375. selected, an outline of the frame is shown to indicate the portion of a part's 
  7376. contents that is displayed in its frame. The user can drag this outline to 
  7377. adjust the visible region of the part. Show frame outline toggles with Hide 
  7378. frame outline. 
  7379.  
  7380. Your part should add the Show frame outline command to the View menu when your 
  7381. part's content area is greater than the area of its display frame, the frame is 
  7382. opened into a part window, and the part window is active. 
  7383.  
  7384.  
  7385. ΓòÉΓòÉΓòÉ 8.3.4.2. Open as ΓòÉΓòÉΓòÉ
  7386.  
  7387. The user chooses the Open as command from the View menu to display an icon, 
  7388. tree or details view of your part and its embeds. If your part is a containing 
  7389. part, you should support these views. 
  7390.  
  7391. Display the view for your frame by calling the DisplayView method of the 
  7392. ODViewExtension class, passing in the view type selected by the user. 
  7393.  
  7394.  
  7395. ΓòÉΓòÉΓòÉ 8.3.4.3. Properties ΓòÉΓòÉΓòÉ
  7396.  
  7397. The user chooses the Properties command from the View menu to display a 
  7398. Properties notebook for your part. 
  7399.  
  7400. The Properties notebook is displayed for your frame using the ShowPartFrameInfo 
  7401. method of the ODInfo class. You obtain a reference to the info object by 
  7402. calling the session object's GetInfo method. OpenDoc handles all changes made 
  7403. by the user. 
  7404.  
  7405.  
  7406. ΓòÉΓòÉΓòÉ 8.3.4.4. Show as ΓòÉΓòÉΓòÉ
  7407.  
  7408. The user chooses the Show as item from the View menu to change the view type of 
  7409. your part's frame. Your part should call its SetViewType method, passing in the 
  7410. view type selected by the user. 
  7411.  
  7412.  
  7413. ΓòÉΓòÉΓòÉ 8.3.4.5. Show links ΓòÉΓòÉΓòÉ
  7414.  
  7415. The user selects this command to show the link border for all links in the 
  7416. active part. The Show links menu item toggles with Hide links. 
  7417.  
  7418.  
  7419. ΓòÉΓòÉΓòÉ 8.3.5. Help Menu ΓòÉΓòÉΓòÉ
  7420.  
  7421. The Help menu choices are as follows: 
  7422.  
  7423.      Help index 
  7424.      General help 
  7425.      <part> information 
  7426.  The following figure shows the Help menu. 
  7427.  
  7428.  
  7429. ΓòÉΓòÉΓòÉ 8.3.5.1. Help index ΓòÉΓòÉΓòÉ
  7430.  
  7431. Index for the active part. When the part receives this command, it should 
  7432. display its index by calling the DisplayHelpIndex method of the ODHelp class. A 
  7433. part obtains a reference to the ODHelp class by calling the GetHelp method of 
  7434. the ODSession class. 
  7435.  
  7436.  
  7437. ΓòÉΓòÉΓòÉ 8.3.5.2. General help ΓòÉΓòÉΓòÉ
  7438.  
  7439. A general description of the part. When a part receives this command, it should 
  7440. display its general help by calling the DisplayHelp method of the ODHelp class. 
  7441. A part obtains a reference to the ODHelp class by calling the GetHelp method of 
  7442. the ODSession class. 
  7443.  
  7444.  
  7445. ΓòÉΓòÉΓòÉ 8.3.5.3. <part> information ΓòÉΓòÉΓòÉ
  7446.  
  7447. This menu provides information about the active part. This menu is optional and 
  7448. should be implemented by the part. 
  7449.  
  7450.  
  7451. ΓòÉΓòÉΓòÉ 8.3.6. Pop-Up Menu ΓòÉΓòÉΓòÉ
  7452.  
  7453. The pop-up menu choices are as follows: 
  7454.  
  7455.      Open as 
  7456.      Properties 
  7457.      Show as 
  7458.      Help 
  7459.  
  7460.  Additional actions that a part can perform on the part should also be listed 
  7461.  in the pop-up menu. Related choices should be grouped together. The commands 
  7462.  generated from the pop-up menus are the same as those generated from the menu 
  7463.  bar. 
  7464.  
  7465.      View choices (for example, Open as, Properties, and so forth) 
  7466.      Clipboard/data transfer (for example, Cut, Paste, Delete, and so forth) 
  7467.      Printing 
  7468.      Part actions 
  7469.      Container actions (for example, Align) 
  7470.      Help 
  7471.  
  7472.  
  7473. ΓòÉΓòÉΓòÉ 8.3.7. Pop-Up Menus and Multiple Selection ΓòÉΓòÉΓòÉ
  7474.  
  7475. In the Workplace Shell on OS/2 when you select multiple objects and then bring 
  7476. up a pop-up menu, you get the intersection of choices you can perform. In the 
  7477. first release of OpenDoc, limited support for this feature will be provided. 
  7478. There are three different cases to consider: 
  7479.  
  7480.      When the multiple selection includes intrinsic content only 
  7481.      When multiple embedded parts are selected only 
  7482.      When both intrinsic content and embedded parts are selected 
  7483.  
  7484.  In the first case, the part editor should be able to provide intersection of 
  7485.  choices that apply to all the intrinsic data that is selected. 
  7486.  
  7487.  Part developers are free to add more choices to the pop-up menu. For example, 
  7488.  if the parts are members of a suite of parts, and the part editor can 
  7489.  correctly determine the intersection of choices, then they should do so. 
  7490.  
  7491.  In the third case, at a minimum, any container choices (for example, Align) 
  7492.  that can be performed on parts should be displayed. Part editors can add more 
  7493.  choices as long as they apply to both the part and the selection. 
  7494.  
  7495.  
  7496. ΓòÉΓòÉΓòÉ 8.3.8. Accelerator Table Sharing ΓòÉΓòÉΓòÉ
  7497.  
  7498. OpenDoc creates a default accelerator table containing pre-defined accelerator 
  7499. keys for OpenDoc. Parts can add to the accelerator table by following these 
  7500. steps: 
  7501.  
  7502.    1. Fill in an ODACCEL structure with the accelerator information. 
  7503.    2. Call the AddToAccelTable method of the ODMenuBar class. 
  7504.  
  7505.  The AddToAccelTable method can add up to 20 accelerator keys to the 
  7506.  accelerator table with each method call. 
  7507.  
  7508.  
  7509. ΓòÉΓòÉΓòÉ 8.3.9. Status Line ΓòÉΓòÉΓòÉ
  7510.  
  7511. There are two uses for the status line. One is to display help for menu items. 
  7512. The other is to display information or progress to the user for actions 
  7513. occuring on within the active part. 
  7514.  
  7515. To use the status line as help for menu items, a part should call the 
  7516. SetMenuItemStatusText method of the ODMenuBar class, passing in the menu ID and 
  7517. the text to be displayed. OpenDoc displays the text when the menu item is 
  7518. selected by the user. 
  7519.  
  7520. To use the status line to display information to the user, a part needs to do 
  7521. the following: 
  7522.  
  7523.    1. Call the session's AcquireExtension method for the status line extension. 
  7524.    2. Call the StatusLineExtension method of the ODArbitrator class. 
  7525.    3. Display the text using the status line extension's SetStatusLineText 
  7526.       method. 
  7527.    4. Release the focus when done. 
  7528.  
  7529.  
  7530. ΓòÉΓòÉΓòÉ 8.4. Undo ΓòÉΓòÉΓòÉ
  7531.  
  7532. The Undo command (and its reverse, Redo) is a common feature on many software 
  7533. platforms. It is designed to allow users to recover from errors that they 
  7534. recognize soon after making them. OpenDoc offers a flexible and powerful Undo 
  7535. capability. 
  7536.  
  7537.  
  7538. ΓòÉΓòÉΓòÉ 8.4.1. Multilevel, Cross-Document Capability ΓòÉΓòÉΓòÉ
  7539.  
  7540. Most systems support only a single-level of Undo; that is, only the most 
  7541. recently executed command can be reversed. Therefore, in most platforms, Undo 
  7542. is restricted to a single domain. A complex operation that involves 
  7543. transferring data from one document to another, for example, cannot be 
  7544. completely undone. 
  7545.  
  7546. OpenDoc, by contrast, supports multiple levels of Undo and Redo.; there is no 
  7547. limit, other than memory constraints on the user's system, to the number of 
  7548. times in succession that a user can invoke the Undo command. OpenDoc also 
  7549. allows for inter-document Undo and Redo. Together, these enhancements give 
  7550. users greater flexibility in recovering from errors than is possible with 
  7551. simpler Undo capabilities. 
  7552.  
  7553. The OpenDoc Undo feature does not offer infinite recoverability. Some user 
  7554. actions clear out the Undo action history, the cumulative set of reversible 
  7555. actions available at any one time, resetting it to empty. A typical example is 
  7556. saving a document; the user cannot the document by choosing Undo, and no 
  7557. actions executed prior to its saving can be undone. As a part developer, you 
  7558. decide which of your own actions are undoable, which ones are ignored for Undo 
  7559. purposes, and which ones reset the action history. In general, actions that do 
  7560. not change the content of a part (such as scrolling, making selections, and 
  7561. opening and closing windows) are ignorable and do not need to be undoable. 
  7562. Non-undoable actions that require clearing the action history are few; closing 
  7563. your part (see Closing your Part) is one of the few. 
  7564.  
  7565. When the user selects Redo, the effects of the last Undo are reversed. Redo is 
  7566. available only if the user has previously chosen Undo, and if nothing but 
  7567. ignorable actions have occurred since the user last chose Undo or Redo. Like 
  7568. Undo, Redo can be chosen several times in succession, limited only by the 
  7569. number of times Undo has been chosen in succession. As soon as the user 
  7570. performs an undoable action (such as an edit) OpenDoc clears the Redo history 
  7571. and Redo is no longer available until the user chooses Undo once again. 
  7572.  
  7573. To implement this multilevel Undo that spans different parts and different 
  7574. documents, OpenDoc maintains a centralized repository of undoable actions, 
  7575. stored by individual part editors as they perform such actions. Undo history is 
  7576. stored in the Undo object, an instantiation of the class ODUndo, created by 
  7577. OpenDoc and accessed through the session object's GetUndo method. Your part 
  7578. editor needs access to the Undo object to store undoable actions in it or 
  7579. retrieve them from it. 
  7580.  
  7581. Importance of Multilevel Undo 
  7582. Your part must support multiple levels of Undo. If your part supports only a 
  7583. single-level Undo command, other parts that support multilevel undo will lose 
  7584. their Undo history when they interact with your part. You should support 
  7585. multiple levels of Undo if you support Undo at all. 
  7586.  
  7587.  
  7588. ΓòÉΓòÉΓòÉ 8.4.2. Implementing Undo ΓòÉΓòÉΓòÉ
  7589.  
  7590. To implement support for Undo in your part editor, you need to be able to save 
  7591. information to the Undo object that allows you to recover previous states of 
  7592. your part, and your part editor needs to implement the following methods: 
  7593.  
  7594.      UndoAction 
  7595.      RedoAction 
  7596.      ReadActionState 
  7597.      WriteActionState 
  7598.      DisposeActionState 
  7599.  
  7600.  The Undo object calls your part's UndoAction and RedoAction methods when the 
  7601.  user selects the Undo and Redo items from the Edit menu, respectively. 
  7602.  
  7603.  The Undo object calls your part's DisposeActionState method when an Undo 
  7604.  action of yours is removed from the Undo action history. At that point, you 
  7605.  can dispose of any storage needed to perform the specified Undo action. 
  7606.  
  7607.  WriteActionState and ReadActionState 
  7608.  Your part's WriteActionState and ReadActionState methods exist to support a 
  7609.  future cross-session Undo capability. OpenDoc can call these methods when it 
  7610.  needs you to store persistently or retrieve your undo-related information. 
  7611.  Version 1.0 of OpenDoc does not support cross-session Undo, however, so you 
  7612.  need not override these methods. 
  7613.  
  7614.  
  7615. ΓòÉΓòÉΓòÉ 8.4.2.1. Adding an Action to the Undo History ΓòÉΓòÉΓòÉ
  7616.  
  7617. If your part performs an undoable action, it should call the Undo object's 
  7618. AddActionToHistory method. Your part passes an item of action data to the 
  7619. method; the action data contains enough information to allow your part to 
  7620. revert to the state it occupied just prior to the undoable action. The action 
  7621. data can be in any format; OpenDoc adds it to the action history in the Undo 
  7622. object and passes it back to your part if the user asks your part to perform an 
  7623. Undo. 
  7624.  
  7625. The item of data that you pass to AddActionToHistory must be of type 
  7626. ODActionData, which is a byte array. When you create the item, you can either 
  7627. copy the data itself into the byte array or you can copy a pointer to the data 
  7628. into the byte array; either way, you then pass the byte array to 
  7629. AddActionToHistory. 
  7630.  
  7631. You also pass two user-visible strings to the AddActionToHistory method. The 
  7632. strings have the text that you want to appear on the Edit menu, such as "Undo 
  7633. cut" and "Redo cut". You must also specify the data's action type, which is 
  7634. described under Creating an Action Subhistory. 
  7635.  
  7636. In general, you add most editing actions to the action history, unless their 
  7637. data is so large that you cannot practically recover the pre-action state. 
  7638. Opening or closing a document, or performing ignorable actions such as 
  7639. scrolling or selecting, should not cause you to add an action to the action 
  7640. history. 
  7641.  
  7642. You decide what constitutes a single action. Entering of an individual text 
  7643. character is not usually considered an action, although deleting or replacing a 
  7644. selection usually is. The sum of actions performed between repositionings of 
  7645. the insertion point is usually considered a single undoable action. 
  7646.  
  7647.  
  7648. ΓòÉΓòÉΓòÉ 8.4.2.2. Adding Two-Stage Actions ΓòÉΓòÉΓòÉ
  7649.  
  7650. Some transactions, such as drag-and-drop, have two stages-a beginning and an 
  7651. end. To add such a transaction to the Undo history, your part must define which 
  7652. stage you are adding, by using the action types kODBeginAction and 
  7653. kODEndAction. (For undoable actions that do not have separate stages, you 
  7654. specify an action type of kODSingleAction when calling AddActionToHistory). 
  7655.  
  7656. In the case of drag and drop, the sequence is like this: 
  7657.  
  7658.      The source part calls AddActionToHistory at the beginning of a drag, 
  7659.       specifying an action type of kODBeginAction. 
  7660.  
  7661.      The destination part calls AddActionToHistory when the drop occurs, 
  7662.       adding a single-stage action to the undo history by specifying 
  7663.       kODSingleAction. 
  7664.  
  7665.      The source part once again calls AddActionToHistory after the completion 
  7666.       of the drop (when the drag-and-drop object's StartDrag method returns), 
  7667.       specifying an action type of kODBeginAction. 
  7668.  
  7669.  Similarly, if the user selects the Paste with link checkbox in the Paste As 
  7670.  dialog box (see the figure in Handling the Paste As Dialog Box), the part 
  7671.  receiving the paste and creating the link destination adds the begin action 
  7672.  and end action, whereas the source part adds a single action when it creates 
  7673.  the link source. 
  7674.  
  7675.  As the case of drag and drop demonstrates, parts can add single-stage actions 
  7676.  to the undo history during the time that a two-stage undoable action is in 
  7677.  progress that is, between the times AddActionToHistory is called with 
  7678.  kODBeginAction and with kODEndAction, respectively. These actions become part 
  7679.  of the overall undoable action. 
  7680.  
  7681.  Menu strings and two-stage actions 
  7682.  The strings you can provide when calling AddActionToHistory are ignored if the 
  7683.  action type is kODBeginAction; only the strings passed for the action type 
  7684.  kODEndAction appear in the menu. 
  7685.  
  7686.  Removing a two-stage action 
  7687.  You can remove an incomplete two-stage action from the undo action history 
  7688.  without having to clear the entire history by using the 
  7689.  AbortCurrentTransaction method. See Clearing the Action History. 
  7690.  
  7691.  
  7692. ΓòÉΓòÉΓòÉ 8.4.2.3. Creating an Action Subhistory ΓòÉΓòÉΓòÉ
  7693.  
  7694. In general, the undoable actions a user performs while a modal dialog box is 
  7695. displayed-as long as the actions do not clear the Undo action history of your 
  7696. document-should not affect the action history previous to that modal state. 
  7697. After dismissing the dialog box, the user should be able to undo actions 
  7698. performed before the modal dialog box was displayed-even though at this point 
  7699. the user could not undo actions taken while the modal dialog box was open. 
  7700.  
  7701. To implement this behavior, you can put a mark into the action history that 
  7702. signifies the beginning of a new action subhistory. To do so, call the 
  7703. MarkActionHistory method of the Undo object. To clear the actions within a 
  7704. subhistory, you specify kODRespectMarks when you call the ClearActionHistory 
  7705. method. To clear the whole action history, specify kODDontRespectMarks instead. 
  7706.  
  7707. For every time you put a mark into the action history, you must make sure there 
  7708. is an equivalent call to ClearActionHistory to clear that subhistory. 
  7709.  
  7710.  
  7711. ΓòÉΓòÉΓòÉ 8.4.2.4. Undoing an Action ΓòÉΓòÉΓòÉ
  7712.  
  7713. When the user chooses to Undo an action added to the action history by your 
  7714. part, OpenDoc calls your part's UndoAction method, passing it the action data 
  7715. you passed in earlier. Your part should perform any reverse editing necessary 
  7716. to restore itself to the pre-action state. (When a two-stage transaction 
  7717. involving your part is undone, OpenDoc calls both your part and the other part 
  7718. involved, so that the entire compound action is reversed). 
  7719.  
  7720.  
  7721. ΓòÉΓòÉΓòÉ 8.4.2.5. Redoing an Action ΓòÉΓòÉΓòÉ
  7722.  
  7723. When the user chooses to Redo an action of your part, OpenDoc calls your part's 
  7724. RedoAction method, passing it the same action data that you had passed in 
  7725. earlier when the original action was performed. In this case, your task is to 
  7726. re-achieve the state represented by the action data, not reverse it. (When a 
  7727. two-stage transaction involving your part is redone, OpenDoc calls both your 
  7728. part and the other part involved, so that the entire compound action is 
  7729. reversed). 
  7730.  
  7731.  
  7732. ΓòÉΓòÉΓòÉ 8.4.2.6. Clearing the Action History ΓòÉΓòÉΓòÉ
  7733.  
  7734. As soon as your part performs an action that you decide cannot be undone, it 
  7735. must clear the action history by calling the Undo object's ClearActionHistory 
  7736. method. Actions that cannot be undone, and for which the action history should 
  7737. be cleared, include saving a changed document and performing an editing 
  7738. operation that is too large to be practically saved. Undoable actions such as 
  7739. normal editing and performing ignorable actions, such as scrolling or 
  7740. selecting, should not affect the action history. 
  7741.  
  7742. If your part initiates a two-stage action and, because of an error, must 
  7743. terminate it before adding the second stage to the action history, it can 
  7744. remove the incomplete undo action by calling the undo object's 
  7745. AbortCurrentTransaction method. AbortCurrentTransaction clears the beginning 
  7746. action and any subsequent single actions form the undo stack, without clearing 
  7747. the entire action history. 
  7748.  
  7749. OpenDoc itself clears the action history when it closes a document. 
  7750.  
  7751.  
  7752. ΓòÉΓòÉΓòÉ 8.4.3. Undo and Embedded Frames ΓòÉΓòÉΓòÉ
  7753.  
  7754. Every frame has a private flag, the in-limbo flag, that determines whether any 
  7755. part currently owns the frame. When a frame is initially created, whether 
  7756. through CreateFrame or by cloning, its in-limbo flag is cleared. 
  7757.  
  7758. Whenever your part cuts, pastes, drags, or drops an embedded frame, you must 
  7759. keep a reference to that frame in an undo action. When you take that action, 
  7760. and when you perform subsequent actions with the frame, you must set the 
  7761. frame's in-limbo flag accordingly. OpenDoc requires this information to handle 
  7762. moved and copied objects properly. 
  7763.  
  7764. The following table shows how to set the flag properly for each situation, and 
  7765. how to dispose of the frame referenced in your undo action when you part's 
  7766. DisposeActionState method is called. 
  7767.  
  7768. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7769. ΓöéAction    ΓöéSet flag to...ΓöéIf Undone, setΓöéIf Redone, setΓöéWhen DisposeActionState is  Γöé
  7770. Γöé          Γöé              Γöéflag to...    Γöéflag to...    Γöécalled                      Γöé
  7771. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7772. ΓöéCreating aΓöé(leave as-is) ΓöékODTrue       ΓöékODFalse      ΓöéIf kODTrue, call Remove; If Γöé
  7773. Γöéframe     Γöé              Γöé              Γöé              ΓöékODFalse, call Release      Γöé
  7774. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7775. ΓöéDeleting, ΓöékODTrue       ΓöékODFalse      ΓöékODTrue       ΓöéIf kODTrue, call Remove; If Γöé
  7776. Γöécutting,  Γöé              Γöé              Γöé              ΓöékODFalse, call Release      Γöé
  7777. Γöéor        Γöé              Γöé              Γöé              Γöé                            Γöé
  7778. Γöéstarting aΓöé              Γöé              Γöé              Γöé                            Γöé
  7779. Γöédrag-move Γöé              Γöé              Γöé              Γöé                            Γöé
  7780. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7781. ΓöéCopying a Γöé(leave as-is) Γöé(Note1)       Γöé(Note1)       Γöé(Note1)                     Γöé
  7782. Γöéframe     Γöé              Γöé              Γöé              Γöé                            Γöé
  7783. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7784. ΓöéPasting orΓöékODFalse (but Γöé(restore priorΓöékODFalse (but ΓöéIf kODFalse, call Release;  Γöé
  7785. Γöédropping aΓöésave prior    Γöévalue)        Γöésave prior    ΓöéIf prior value = kODTrue,   Γöé
  7786. Γöéframe     Γöévalue)        Γöé              Γöévalue)        Γöécall Release; Otherwise,    Γöé
  7787. Γöé          Γöé              Γöé              Γöé              Γöécall Remove                 Γöé
  7788. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7789. ΓöéWhen      ΓöékODFalse (if  Γöé(leave as-is) ΓöékODFalse (if  Γöé(nothing if drag was a copy;Γöé
  7790. ΓöéStartDrag Γöédrag was a    Γöé              Γöédrag was a    Γöéelse as for drag-move)      Γöé
  7791. Γöéreturns   Γöécopy; else    Γöé              Γöécopy; else    Γöé                            Γöé
  7792. Γöé          Γöéleave as-is)  Γöé              Γöéleave as-is)  Γöé                            Γöé
  7793. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7794.  
  7795. Note1:  Do not create an undo action for this situation. 
  7796.  
  7797. You set the value of a frame's in-limbo flag by calling its SetInLimbo method 
  7798. and passing either kODTrue or kODFalse. You can determine the value of a 
  7799. frame's in-limbo flag by calling its IsInLimbo method. 
  7800.  
  7801.  
  7802. ΓòÉΓòÉΓòÉ 9. Storage ΓòÉΓòÉΓòÉ
  7803.  
  7804. This is the fifth of eight chapters that discuss the OpenDoc programming 
  7805. interface in detail. This chapter describes the external storage facilities 
  7806. OpenDoc uses and provides. OpenDoc relies upon the native file-storage 
  7807. facilities of each of the individual OpenDoc platforms. The same fundamental 
  7808. storage concepts and structures are used consistently for document storage and 
  7809. for data transfer (clipboard transfer, drag-and-drop, and linking, described in 
  7810. the next chapter). 
  7811.  
  7812. Before reading this chapter, you should be familiar with the concepts presented 
  7813. in Introduction and Development Overview. Additional concepts related to your 
  7814. part editor's run-time environment are found in OpenDoc Run-Time Features. 
  7815.  
  7816. This chapter introduces the general architecture of the OpenDoc storage system, 
  7817. including how parts are stored, and then describes how your OpenDoc part editor 
  7818. can use that architecture to store and retrieve its own content. 
  7819.  
  7820.  
  7821. ΓòÉΓòÉΓòÉ 9.1. OpenDoc Storage System ΓòÉΓòÉΓòÉ
  7822.  
  7823. The OpenDoc storage system is a high-level mechanism for persistent or 
  7824. ephemeral storage that enables multiple part editors to effectively share a 
  7825. single document. The storage system is implemented on top of the native storage 
  7826. facilities of each platform that supports OpenDoc. 
  7827.  
  7828. The OpenDoc storage system effectively gives each part its own data stream for 
  7829. storage and supports reliable references from one stream to another. The system 
  7830. includes a robust annotation mechanism that allows many pieces of code to 
  7831. access information about a given part without disturbing its format. 
  7832.  
  7833. The identity of a part is consistent within a session; it is unique within its 
  7834. document and testable for equality with other part identities. Parts can 
  7835. persistently reference other objects in the same draft, including other parts, 
  7836. which allows run-time object structures to be saved and reconstructed in a 
  7837. future session. 
  7838.  
  7839. Parts have more than just their content to store persistently. Properties are 
  7840. used to store both the content of the part and supplemental information. 
  7841. OpenDoc defines a standard set of properties for all parts, and you can assign 
  7842. additional properties to a given part. The name of the preferred part editor is 
  7843. one example of a standard property that can be stored with a part. 
  7844.  
  7845. The storage system allows OpenDoc to swap parts out to external storage if 
  7846. memory is required for other parts. When a part is first needed, its part 
  7847. editor reads it from external storage into memory. When it is no longer needed, 
  7848. the draft releases it. If the part is needed again at a later time, the storage 
  7849. system can either return the in-memory part to the part editor or-if the part 
  7850. has been deleted because of low memory-bring the part once again into memory 
  7851. from storage. When it reads or writes its parts, your part editor may not know 
  7852. whether the data is currently being transferred to or from memory, or to or 
  7853. from external physical storage. 
  7854.  
  7855.  
  7856. ΓòÉΓòÉΓòÉ 9.1.1. Storage Units, Properties, and Values ΓòÉΓòÉΓòÉ
  7857.  
  7858. The OpenDoc storage system is not an object-oriented database. It is a system 
  7859. of structured storage, in which each unit of storage can contain many streams. 
  7860. This design eases the transition for developers working with existing code 
  7861. bases, which generally assume stream-based I/O. 
  7862.  
  7863. The controlling storage object is the storage system object, which instantiates 
  7864. and maintains a list of containers. The containers are objects in the container 
  7865. suite, a platform-specific storage implementation. Version 1.0 of OpenDoc is 
  7866. released with the Bento container suite, a container suite that can be used 
  7867. with or independently of OpenDoc. 
  7868.  
  7869. Each container object in a container suite can hold one or more document 
  7870. objects, each of which, in turn, contains one or more draft objects. Each draft 
  7871. contains a number of storage unit objects, each of which is much like a 
  7872. directory structure in a typical file system (although multiple storage units 
  7873. might be physically stored in a single file, or perhaps not stored in files at 
  7874. all). Storage units hold the streams of stored data. 
  7875.  
  7876. The run-time relationships of these storage objects are diagrammed in the 
  7877. following figure. the figure in section Document Storage 
  7878.  
  7879.  
  7880. ΓòÉΓòÉΓòÉ 9.1.1.1. Storage-Unit Organization ΓòÉΓòÉΓòÉ
  7881.  
  7882. You can visualize a storage unit as a set of properties, or categorized groups 
  7883. of data streams. A property is identified by its property name, an ISO string. 
  7884. Each property consists of a number of streams called values, each of which 
  7885. stores a different representation of the same data, in a format identified by a 
  7886. named type (a value type, also an ISO string). Thus there can be several 
  7887. properties (named categories) in a single storage unit, and several values 
  7888. (typed streams) in a single property. 
  7889.  
  7890. The following figure shows these relationships through a simplified diagram of 
  7891. the organization of a storage unit. 
  7892.  
  7893. The following figure is a simplified diagram of a specific storage unit in use. 
  7894. The storage unit contains a figure caption. The part that owns this storage 
  7895. unit has created a contents property, which contains the primary data of this 
  7896. storage unit, as well as a name property, which names the item stored in this 
  7897. storage unit. This particular storage unit has three representations of the 
  7898. contents property (the text of the caption) as three different types of values: 
  7899. its own custom styled text, plain text in a standard (international) text 
  7900. format, and a bitmap. The storage unit has only one representation of the name 
  7901. property. 
  7902.  
  7903. A caller that accesses this storage unit can read or write just the data of 
  7904. immediate interest. In the storage unit of the previous figure, for example, a 
  7905. caller could access only the value representing one of the data formats in the 
  7906. contents property without having to read the rest of the storage unit into 
  7907. memory. A caller could learn the part kinds of the data stored in the storage 
  7908. unit without having to read any of the contents into memory, even if the part 
  7909. editor that stored the data is not present. 
  7910.  
  7911. Fundamental to the OpenDoc storage system is the concept that all values within 
  7912. a property are analogous, or equivalent, representations of the same data. 
  7913. Every value in the contents property in the previous figure, for example, is a 
  7914. complete representation of the item's contents, (the caption text), expressed 
  7915. in the type of data that the value holds. 
  7916.  
  7917. Values in a storage unit can include references to other storage units, as 
  7918. described in Persistent References. Thus, storage units can be arranged in 
  7919. ordered structures such as hierarchies; OpenDoc stores the embedding structure 
  7920. of a document in this way. 
  7921.  
  7922.  
  7923. ΓòÉΓòÉΓòÉ 9.1.1.2. Standard Properties ΓòÉΓòÉΓòÉ
  7924.  
  7925. A basic feature of the OpenDoc storage system is that storage units are 
  7926. inspectable; that is, one can extract the data (values) of the various 
  7927. properties of a storage unit without first having to read the entire file or 
  7928. document that the storage unit is part of, and without having to understand the 
  7929. internal format of the data in any of the values. For example, if the storage 
  7930. unit for an embedded part includes a property that holds the part's name, you 
  7931. can extract that name without having to read in all the data of the part, even 
  7932. if you do not understand how to read or display the part's contents. 
  7933.  
  7934. To make the inspectability of storage useful across parts, documents, and 
  7935. platforms, OpenDoc publicly specifies certain standard properties that all part 
  7936. editors can recognize. Documents, windows, frames, and parts all have basic 
  7937. structures, defined by properties, that are accessible from both the stored and 
  7938. in-memory states. This accessibility allows OpenDoc and part editors to read 
  7939. only the information that is needed in a given situation and thus increase 
  7940. performance. The table in What a Draft Contains and the table in Info 
  7941. Properties list many of the common standard properties that might be found in 
  7942. storage units. 
  7943.  
  7944. Using storage-unit methods, you can access the values of any known property of 
  7945. any storage unit. 
  7946.  
  7947.  
  7948. ΓòÉΓòÉΓòÉ 9.1.1.3. Creating Properties and Values ΓòÉΓòÉΓòÉ
  7949.  
  7950. If you have a reference to a storage unit, you can add a property to it and 
  7951. then add several values to that property.  For the example illustrated in the 
  7952. previous figure, for example, you might use statements such as these (in which 
  7953. the storage unit reference is su): 
  7954.  
  7955. su->AddProperty(ev, kODPropContents);
  7956. su->AddValue(ev, kMyKind);
  7957. su->AddValue(ev, kKindTEXT);
  7958. su->AddValue(ev, kKindPICT);
  7959.  
  7960. These statements add the property kODPropContents to the storage unit and give 
  7961. it one standard (kODIntlText) and two custom (kCustomTextKind and 
  7962. kMyBitmapKind) value types. The kODPropContents property is a standard property 
  7963. name; you can add your own custom property and value types to a storage unit, 
  7964. using statements such as this: 
  7965.  
  7966. su->AddProperty(ev, kPropAnnotations);
  7967. su->AddValue(ev, kMyAnnotationsType);
  7968.  
  7969. These statements only set up the storage unit to receive data of a particular 
  7970. type; you then need to explicitly store the data in the values. To do so, you 
  7971. must first focus the storage unit, setting it up so that the data you write 
  7972. will be written to the desired value of the desired property. 
  7973.  
  7974.  
  7975. ΓòÉΓòÉΓòÉ 9.1.1.4. Focusing a Storage Unit ΓòÉΓòÉΓòÉ
  7976.  
  7977. Because any storage unit can contain a number of properties, and any property a 
  7978. number of values, finding the exact piece of data in an OpenDoc document can be 
  7979. more complex than finding it in a conventional document. OpenDoc allows you to 
  7980. focus a storage unit, that is, access the desired data stream (defined by 
  7981. property name and value type) within it before reading and writing. 
  7982.  
  7983. You focus on a particular stream by calling the storage unit's Focus method, 
  7984. and providing some combination of the following three types of specification: 
  7985.  
  7986.      Name:  property name or value type 
  7987.  
  7988.      Index:  the position of the property in the storage unit or the value in 
  7989.       the property 
  7990.  
  7991.      Position code:  a code that allows you to specify, for example, the next 
  7992.       or previous sibling (a sibling is another value in the same property, or 
  7993.       another property in the same storage unit) 
  7994.  
  7995.  If you are not focusing by relative position, you specify a position code of 
  7996.  kODPosUndefined when you call the Focus method.  For example, all of the 
  7997.  following calls would focus on the first value of the contents property of the 
  7998.  storage unit shown in the previous figure, 
  7999.  
  8000.      The names of the property and value: 
  8001.  
  8002.             su->Focus(ev,
  8003.                       kODPropContents,         // Property name
  8004.                       kODPosUndefined,
  8005.                       kMyKind,                 // Value type
  8006.                       0,
  8007.                       kODPosUndefined);
  8008.  
  8009.      The name of the property and the indexed position (1-based), within its 
  8010.       property, of the value: 
  8011.  
  8012.             su->Focus(ev,
  8013.                       kODPropContents,         // Property name
  8014.                       kODPosUndefined,
  8015.                       kODNULL,
  8016.                       1,                       // Value index
  8017.                       kODPosUndefined);
  8018.  
  8019.      The relative positions, compared to the current focus, of the property 
  8020.       and value: 
  8021.  
  8022.             su->Focus(ev,
  8023.                       kODPropContents          // Property type
  8024.                       kODPosUndefined,
  8025.                       kODNULL,
  8026.                       0,
  8027.                       kODPosFirstSib);         // Position code
  8028.  
  8029.      The storage-unit cursor that specifies the property-and-value pair you 
  8030.       want: 
  8031.  
  8032.             su->FocusWithCursor(ev, cursor);   // Storage-unit cursor
  8033.  
  8034.  A storage-unit cursor is an OpenDoc object that may be convenient if you 
  8035.  frequently switch back and forth among specific property-and-value 
  8036.  combinations. You can create a number of objects of class ODStorageUnitCursor, 
  8037.  initialize them with the storage-unit foci you need, and pass a storage-unit 
  8038.  cursor to the Focus method each time you wish to switch focus. You can set up 
  8039.  a storage-unit cursor either by explicitly specifying the property and value 
  8040.  of its focus, or by having it adopt the current focus of an existing storage 
  8041.  unit. 
  8042.  
  8043.  Once you have focused the storage unit, you can read and write its data, as 
  8044.  described next. 
  8045.  
  8046.  
  8047. ΓòÉΓòÉΓòÉ 9.1.1.5. Manipulating the Data in a Value ΓòÉΓòÉΓòÉ
  8048.  
  8049. To read or write the data of a value, remove data from a value, or insert data 
  8050. into a value, you first focus the storage unit on that particular value. 
  8051.  
  8052.      To write data at a particular position in a value, call the SetOffset 
  8053.       method to set the position of the insertion point in the value's stream, 
  8054.       followed by the SetValue method to write the data. 
  8055.  
  8056.       The SetValue method takes a buffer parameter of type of type ODByteArray; 
  8057.       see Handling Byte Arrays and Other Parameters for more information on 
  8058.       byte arrays. For example, to write information from the buffer pointed to 
  8059.       by dataPtr into the value at the position desiredPosition, you could set 
  8060.       up the byte array myData as shown and then call two methods: 
  8061.  
  8062.             ODByteArray MyData;
  8063.  
  8064.             myData._length = dataSize;
  8065.             myData._maximum = dataSize;
  8066.             myData._buffer = dataPtr;
  8067.  
  8068.             SetOffset(ev, desiredPosition);
  8069.             SetValue(ev, &myData);
  8070.  
  8071.       To read the data at a particular position in a value, call the SetOffset 
  8072.       method, followed by the GetValue method to read the data. To read 
  8073.       information from the position desiredPosition in the value into a buffer 
  8074.       specified by the byte array myData, you could make these calls: 
  8075.  
  8076.             SetOffset(ev, desiredPosition);
  8077.             GetValue(ev, &myData);
  8078.  
  8079.       You could then extract the data from the buffer pointed to by 
  8080.       myData._buffer. 
  8081.  
  8082.      To read or write data at the current offset in a value, simply call 
  8083.       GetValue or SetValue without first calling SetOffset. specified. To 
  8084.       insert data at a particular offset, without overwriting any data already 
  8085.       in the value, call the InsertValue method (after having called SetOffset, 
  8086.       if necessary). 
  8087.  
  8088.      To append data at the end of a value, call GetSize to get the size of the 
  8089.       value, then call SetOffset to set the mark to the end of the stream, and 
  8090.       then call SetValue to write the data into the stream. 
  8091.  
  8092.      To remove data of a particular size from a particular position in a 
  8093.       value, call SetOffset to set the mark to the desired point in the stream, 
  8094.       and then call DeleteValue to delete data of a specified length (in bytes) 
  8095.       from the stream. 
  8096.  
  8097.  Note:  If you change the data in one value of a property, remember that you 
  8098.         must make appropriate changes to all other values of that property. All 
  8099.         values must be complete and equivalent representations- each according 
  8100.         to its own format-of the information the property represents. 
  8101.  
  8102.  
  8103. ΓòÉΓòÉΓòÉ 9.1.1.6. Iterating through a Storage Unit ΓòÉΓòÉΓòÉ
  8104.  
  8105. To examine each of the properties of a storage unit in turn, access them in 
  8106. this way: 
  8107.  
  8108.    1. Call the Focus method of the storage unit, passing null values for 
  8109.       property name and value type, and kODPosAll for position code. The null 
  8110.       values "unfocus" the storage unit (that is, focus it on all properties). 
  8111.  
  8112.    2. Get the number of properties in the (unfocused) storage unit by calling 
  8113.       its CountProperties method. 
  8114.  
  8115.    3. Focus on each property in turn, by iterating through them using a 
  8116.       relative-position method of focusing: 
  8117.  
  8118.             su->Focus(ev,
  8119.                       kODNULL,
  8120.                       kODPosNextSib,           // Position code
  8121.                       kODNULL,
  8122.                       0,
  8123.                       kODPosUndefined);
  8124.  
  8125.  To examine in turn each of the values in a property of a storage unit, you 
  8126.  access them in a similar way: 
  8127.  
  8128.    1. Focus the storage unit on the desired property by calling its Focus 
  8129.       method and passing the desired property name and kODPosAll for relative 
  8130.       position of value. Using kODPosAll focuses the storage unit on all values 
  8131.       of that property. 
  8132.  
  8133.    2. Get the number of values in the property, by calling the CountValues 
  8134.       method of the focused storage unit. 
  8135.  
  8136.    3. Focus on each value in turn, by iterating through them using a 
  8137.       relative-position method of focusing for the values, while maintaining 
  8138.       the same property position: 
  8139.  
  8140.             su->Focus(ev,
  8141.                       kODNULL,
  8142.                       kODPosSame,              // Position code
  8143.                       kODNULL,
  8144.                       0,
  8145.                       kODPosNextSib);          // Position code
  8146.  
  8147.  
  8148. ΓòÉΓòÉΓòÉ 9.1.1.7. Removing Properties and Values ΓòÉΓòÉΓòÉ
  8149.  
  8150. You can remove a property from a storage unit by: 
  8151.  
  8152.    1. Focusing on the property to be removed; call the Focus method and pass it 
  8153.       a specific property name and a value position of kODPosAll. 
  8154.  
  8155.    2. Removing the property, by calling the Remove method on the focused 
  8156.       storage unit. 
  8157.  
  8158.  You can remove a value from a property in a storage unit by: 
  8159.  
  8160.    1. Focusing on the value to be removed; call the Focus method and pass it a 
  8161.       specific property name and a specific value type. 
  8162.  
  8163.    2. Removing the value; call the Remove method of the focused storage unit. 
  8164.  
  8165.  
  8166. ΓòÉΓòÉΓòÉ 9.1.1.8. Storage-Unit IDs ΓòÉΓòÉΓòÉ
  8167.  
  8168. At run-time, the draft object assigns an identifier to each of its storage 
  8169. units. A storage-unit ID is a non-persistent designation for a storage unit 
  8170. that is unique within its draft (storage-unit IDs are not unique across drafts 
  8171. and do not persist across sessions). You can use the ID to identify storage 
  8172. units, to compare two storage units for equality at run-time, and to recreate 
  8173. persistent objects from their storage units. 
  8174.  
  8175. Just as object references are the basic run-time identifiers for OpenDoc 
  8176. objects, storage-unit IDs are the basic run-time identifiers for the storage 
  8177. units of persistent objects (subclasses of ODPersistentObject). Methods that 
  8178. manipulate storage units often take a storage-unit ID as a parameter; 
  8179. ODDraft::AcquireStorageUnit and ODDraft::ReleaseStorageUnit are examples. 
  8180.  
  8181. For purposes in which the storage unit as a whole is passed or copied, an ID is 
  8182. better than a run-time object reference. For example, storage-unit IDs are used 
  8183. when cloning persistent objects (see Persistent References and Cloning). Using 
  8184. a storage-unit ID ensures that the copying occurs even if the storage unit's 
  8185. object is not in memory at the time. However, OpenDoc first looks for the 
  8186. object in memory, and uses it rather than the storage unit if its content is 
  8187. more recent than the storage unit's content. 
  8188.  
  8189. You generally instantiate a persistent object from storage by passing a 
  8190. storage-unit ID to the object's factory method (such as ODDraft::AcquireFrame 
  8191. and ODDraft::AcquirePart). You can also conveniently retrieve persistent 
  8192. objects that may or may not have been purged (such as frames scrolled out of 
  8193. and then back into view) by retaining the storage-unit ID for the object when 
  8194. you release it, and then supplying that ID when you need it again. Note also 
  8195. that, in discussions that refer to part ID or object ID for any persistent 
  8196. object, the ID being referred to is a storage-unit ID. 
  8197.  
  8198. When a part initializes itself, its InitPart or InitPartFromStorage method is 
  8199. passed a storage-unit ID representing its main storage unit. The part can then 
  8200. retrieve any of its previously stored auxiliary storage units (see Main and 
  8201. Auxiliary Storage Units) by passing a storage unit ID to 
  8202. ODDraft::AcquireStorageUnit. 
  8203.  
  8204. Storage-unit IDs are not persistent. Therefore, to get the correct storage-unit 
  8205. ID when instantiating a stored persistent object, a caller must have access to 
  8206. another, more permanent means of identifying a storage unit. For that purpose, 
  8207. OpenDoc uses persistent references. OpenDoc provides methods (such as 
  8208. ODDraft::GetIDFromStorageUnitRef) for obtaining a storage-unit ID from a 
  8209. persistent reference, and vice versa (such as 
  8210. ODStorageUnit::GetStrongStorageUnitRef). 
  8211.  
  8212.  
  8213. ΓòÉΓòÉΓòÉ 9.1.1.9. Persistent References ΓòÉΓòÉΓòÉ
  8214.  
  8215. A persistent reference is a number, stored somewhere within a given storage 
  8216. unit, that refers to another storage unit in the same document (see the 
  8217. following figure). The reference is preserved across sessions; if a document is 
  8218. closed and then reopened at another time or even on another machine, the 
  8219. reference is still valid. 
  8220.  
  8221. Persistent references allow data to be placed into multiple storage units. The 
  8222. storage units reflect the run-time objects whose data they store; the 
  8223. persistent references permit the reconstruction of the run-time relationships 
  8224. among those objects in subsequent sessions. 
  8225.  
  8226.  
  8227. ΓòÉΓòÉΓòÉ 9.1.1.9.1. Persistent References in OpenDoc ΓòÉΓòÉΓòÉ
  8228.  
  8229.  
  8230. OpenDoc uses persistent references in several situations, including these: 
  8231.  
  8232.      The stored data in a draft includes a list of persistent references to 
  8233.       the root frames of all windows. When a document is opened, the root 
  8234.       frames can then be found and their windows reconstructed. 
  8235.  
  8236.      A stored frame has a persistent reference to its part. When a frame is 
  8237.       read into memory, it can then find the part it displays. 
  8238.  
  8239.      A stored part has persistent references to all of its embedded frames. 
  8240.       When a part is read into memory, it can then find all of the embedded 
  8241.       frames that it contains. Persistent references to embedded frames are 
  8242.       essential to embedding; parts have no access to their embedded parts 
  8243.       except through embedded frames. 
  8244.  
  8245.      A stored part also may have persistent references to all of its display 
  8246.       frames. When a part is read into memory, it can then find all of the 
  8247.       frames that display it. 
  8248.  
  8249.      Parts can also use persistent references for hierarchical storage of 
  8250.       their own content data. 
  8251.  
  8252.  The following figure is a simplified diagram showing the persistent references 
  8253.  among stored objects in an OpenDoc Document. (The difference between the 
  8254.  strong and weak persistent references referred to in the figure is explained 
  8255.  in Persistent References and Cloning). 
  8256.  
  8257.  
  8258. ΓòÉΓòÉΓòÉ 9.1.1.9.2. Creating Persistent References ΓòÉΓòÉΓòÉ
  8259.  
  8260.  
  8261. To create a persistent reference, you first focus the storage unit on the value 
  8262. whose data stream is to hold the reference and then call the storage unit's 
  8263. GetStrongStorageUnitRef or GetWeakStorageUnitRef method, passing the ID of the 
  8264. storage unit that is to be referred to. You then store the returned reference 
  8265. in the focused value in a format consistent with the type of the value. Such a 
  8266. reference is then said to be from the value to the referenced storage unit. 
  8267.  
  8268. A persistent reference is a 32-bit value of type ODStorageUnitRef. You can 
  8269. create and store a virtually unlimited number of persistent references in a 
  8270. storage unit value; each persistent reference that you create from a particular 
  8271. value is guaranteed to be unique. Do not try to inspect or interpret a 
  8272. persistent reference; the classes ODStorageUnit and ODStorageUnitView provide 
  8273. methods for manipulating them. 
  8274.  
  8275. Note:  The scope of a persistent reference is limited to the value in which it 
  8276.        was originally stored. Do not store it in a different value; it will 
  8277.        almost certainly no longer refer to the correct storage unit. 
  8278.  
  8279.  Once a persistent reference is no longer needed, you should remove it from the 
  8280.  value in which it was written. Extra persistent references threaten the 
  8281.  robustness and efficiency of execution. A storage unit is aware of all 
  8282.  persistent references that it holds, even those that a part editor may have 
  8283.  stored within its contents property.  OpenDoc provides an iterator class, 
  8284.  ODStorageUnitRefIterator, through which a caller can retrieve all persistent 
  8285.  references in a given value. 
  8286.  
  8287.  
  8288. ΓòÉΓòÉΓòÉ 9.1.1.9.3. Persistent References and Cloning ΓòÉΓòÉΓòÉ
  8289.  
  8290.  
  8291. There are two kinds of persistent references: strong persistent references and 
  8292. weak persistent references. They are treated differently in cloning. 
  8293.  
  8294. To clone an object is to make a deep copy of it:  not only is the object itself 
  8295. copied, but also all objects that it references (plus the objects that they 
  8296. reference, and so on). The cloning process is described further in Cloning. 
  8297.  
  8298. In a clone operation, copies are made of all storage units referenced with a 
  8299. strong persistent reference in the object being cloned. Storage units 
  8300. referenced with a weak persistent reference are not copied. 
  8301.  
  8302. The use of weak persistent references allows you to clone only portions of a 
  8303. document or other structure of referenced storage units. The following figure, 
  8304. which shows the persistent references among a stored frame and part plus their 
  8305. embedded frame and part, illustrates how cloning gives different results, 
  8306. depending on which references are strong and which are weak. 
  8307.  
  8308. For example, if you were to clone the containing frame (A) in the previous 
  8309. figure, all four objects in the figure would be cloned, representing the 
  8310. containing frame and part plus its embedded frame and part; if, however, you 
  8311. were to clone the containing part (B), only the part plus its embedded frame 
  8312. and part (C and D) would be cloned, even though the containing part includes a 
  8313. persistent reference back to its display frame (A). Likewise, if you were to 
  8314. clone the embedded frame (C), only the frame and its part (D) would be cloned. 
  8315.  
  8316. You define a persistent reference as weak or strong by calling either the 
  8317. GetStrongStorageUnitRef or the GetWeakStorageUnitRef method of the storage unit 
  8318. that is to hold the reference. 
  8319.  
  8320. Stored display frames 
  8321. It is recommended, although not necessary, that you store your part's display 
  8322. frames persistently. This will ensure that the part can be closed and will look 
  8323. the same if it is reopened later. If you do store display frames, however, make 
  8324. sure that your part's persistent references to them are weak references. This 
  8325. will enable you to clone the part without its display frame(s), so that the 
  8326. clone can have its own display frame(s). 
  8327.  
  8328.  
  8329. ΓòÉΓòÉΓòÉ 9.1.1.10. Main and Auxiliary Storage Units ΓòÉΓòÉΓòÉ
  8330.  
  8331. Every part (or other persistent object) has a single main storage unit, whose 
  8332. kODPropContents property stores the content of that object. In most cases, you 
  8333. can simply stream all of your part's data into that one storage unit. It is 
  8334. possible, however, to create auxiliary storage units that hold additional data 
  8335. related to the data in a main storage unit. 
  8336.  
  8337. The procedure involves creating a strong persistent reference to the auxiliary 
  8338. storage unit and storing it in your main storage unit. You can subsequently 
  8339. retrieve the reference and convert it into an object reference to the auxiliary 
  8340. storage unit. See Creating Additional Storage Units for more information. 
  8341.  
  8342.  
  8343. ΓòÉΓòÉΓòÉ 9.1.1.11. Prefocused Access with Storage-Unit Views ΓòÉΓòÉΓòÉ
  8344.  
  8345. A storage-unit view is an OpenDoc object that represents a prefocused access to 
  8346. a storage unit. The class ODStorageUnitView has most of the functionality of 
  8347. the class ODStorageUnit, except that it has no methods for accessing different 
  8348. properties and values. A storage-unit view does not in itself store data; each 
  8349. storage-unit view is associated with a specific storage unit that actually does 
  8350. the storing. Calls you make to access the storage unit view are passed to its 
  8351. associated storage unit. 
  8352.  
  8353. Several methods of several OpenDoc classes take a storage-unit view as a 
  8354. parameter. The ODPart methods FulFillPromise, ReadPartInfo, WritePartInfo, 
  8355. ReadActionState, and WriteActionState, for example, all make use of 
  8356. storage-unit views. When one of your methods receives a storage-unit view as a 
  8357. parameter, the method can read from the storage-unit view or write to it 
  8358. without first focusing on any property or value or locking the storage unit. 
  8359.  
  8360. You can, if desired, create storage-unit views to pass prefocused storage units 
  8361. among your software components, or to any subclasses of OpenDoc objects (such 
  8362. as ODNameSpace) that you might create, and whose methods take storage-unit 
  8363. views. 
  8364.  
  8365.  
  8366. ΓòÉΓòÉΓòÉ 9.1.2. Documents, Drafts, and Parts ΓòÉΓòÉΓòÉ
  8367.  
  8368. Compound documents are fundamental to OpenDoc, and each compound document is 
  8369. represented by a document object. Documents are composed of one or more drafts. 
  8370. This section discusses the relationship of documents to drafts and to parts, 
  8371. describes how part data is stored, and discusses the objects that a document 
  8372. comprises. 
  8373.  
  8374. The document object is responsible for creating and deleting drafts, for 
  8375. storing the identity of the current draft, and for collapsing multiple drafts 
  8376. into one. Your part editor rarely interacts directly with its document object. 
  8377. However, see Creating a New Document for information on creating a document 
  8378. object. 
  8379.  
  8380.  
  8381. ΓòÉΓòÉΓòÉ 9.1.2.1. Drafts ΓòÉΓòÉΓòÉ
  8382.  
  8383. A draft is a specific version of an OpenDoc document. Multiple drafts can be 
  8384. maintained within a single document. There is always at least one draft, the 
  8385. base draft, within a document. An individual draft can be extracted from a 
  8386. document and placed in a new document for editing. 
  8387.  
  8388. Drafts are created by users with the help of the document shell, and maintained 
  8389. by the container suite. The figure in section Document Drafts shows an example 
  8390. of the Drafts dialog box, with which the user views and manipulates the drafts 
  8391. of a document. A user can save the current state of the document as a new draft 
  8392. at any time. In general, your part editor can ignore the existence of separate 
  8393. drafts in a document. The data you read or write is always associated with the 
  8394. currently open draft. 
  8395.  
  8396. Methods of ODDocument allow access to drafts by draft ID or by object reference 
  8397. and relative position in the document. Drafts have a specific set of 
  8398. properties, including creation date, modification date, and user name. Each 
  8399. draft object privately maintains whatever information it needs to distinguish 
  8400. itself from its predecessor draft. 
  8401.  
  8402. The draft object is responsible for creating and tracking frame objects, part 
  8403. objects, link-related objects, and storage units. It also manages the cloning 
  8404. process and flags changes to the content of any of its parts. Typically, it is 
  8405. to perform these tasks-and not to manipulate a draft as a version of a 
  8406. document-that your part editor interacts with its draft object. Only one user 
  8407. can edit a draft at a time, and only the most recent draft of a given document 
  8408. can be edited. (Drafts cannot be changed if other drafts are based on them). To 
  8409. enforce this, each open draft has an associated set of draft permissions. They 
  8410. specify the class of read/write access that your part editor has to the draft. 
  8411. The following table lists the draft permissions recognized by OpenDoc. 
  8412.  
  8413. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8414. ΓöéConstant                      ΓöéExplanation                   Γöé
  8415. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8416. ΓöékDPExclusiveWrite             ΓöéRead access and               Γöé
  8417. Γöé                              Γöéexclusive-write access        Γöé
  8418. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8419. ΓöékDPReadOnly                   ΓöéRead-only access              Γöé
  8420. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8421. ΓöékDPSharedWrite                ΓöéRead access and shared-write  Γöé
  8422. Γöé                              Γöéaccess                        Γöé
  8423. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8424. ΓöékDPTransient                  ΓöéNavigation-only access        Γöé
  8425. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8426. ΓöékDPNone                       ΓöéNo access                     Γöé
  8427. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8428.  
  8429. Note:  The Bento container suite supports only the kODReadOnly and 
  8430.        kODExclusiveWrite draft permissions. 
  8431.  
  8432.  When your part initializes itself, or at least before attempting to modify any 
  8433.  of its data, it should get the permissions of its draft (by calling the 
  8434.  draft's GetPermissions method) and behave accordingly. For example, your part 
  8435.  editor should not attempt to make changes to a part when its draft has been 
  8436.  opened read-only. Also, certain menu items should be disabled when the user 
  8437.  views a read-only draft; see Document Menu and Edit Menu for descriptions. 
  8438.  
  8439.  
  8440. ΓòÉΓòÉΓòÉ 9.1.2.2. Storage Model for Parts ΓòÉΓòÉΓòÉ
  8441.  
  8442. Parts, like other persistent objects, have a storage unit in which they can 
  8443. write their state persistently. At the same time, parts are directly involved 
  8444. in many other OpenDoc actions (such as binding, data translation, and data 
  8445. transfer) and thus must satisfy additional storage requirements, so they can 
  8446. share their data with other objects as needed. Here are some of requirements 
  8447. your parts must meet: 
  8448.  
  8449.      Your part must be able to store multiple representations of its content. 
  8450.       Each representation must be a full representation of the content; it 
  8451.       cannot contain just that data that differs from the data in another 
  8452.       representation. 
  8453.  
  8454.      A caller must be able to extract at least one representation from your 
  8455.       part's storage unit, without having to understand the format of any of 
  8456.       the representations. 
  8457.  
  8458.      A caller must be able to remove all but one representation from your 
  8459.       part's storage unit, without having to understand the format of any of 
  8460.       the representations. 
  8461.  
  8462.      You must store your part's representations in order of fidelity, which is 
  8463.       the faithfulness of the representation to that of your part editor's 
  8464.       native format. Store them in descending order of fidelity, with your part 
  8465.       editor's preferred format first. 
  8466.  
  8467.      It must be possible to distinguish the fundamental content of your part 
  8468.       from any annotations to it or information about it. OpenDoc-or any caller 
  8469.       with access to your storage unit-can delete these annotations and items 
  8470.       of information from memory at any time, without writing them to storage, 
  8471.       and therefore you cannot use them to store actual content. You can, 
  8472.       however, use them to store non-critical optimizations such as caches. 
  8473.  
  8474.      Because property names are ISO strings, only simple naming conventions, 
  8475.       such as prefixes to establish ownership, are possible. For example, "TC 
  8476.       corporation" might use the prefix "TC:" to identify all ISO strings for 
  8477.       which it controls the format and meaning. 
  8478.  
  8479.  To meet these requirements, your part must create a contents property, defined 
  8480.  by the property name kODPropContents, in your storage unit. In that property, 
  8481.  you need to create-for every representation you wish to store-a value whose 
  8482.  type is the part kind of the representation. (Part kind is described in Part 
  8483.  Kinds Stored in a Part). Into each of these values, you must write one and 
  8484.  only one representation of your part's contents, using the data format 
  8485.  appropriate to that part. Order the values by fidelity. 
  8486.  
  8487.  Do not store any part content outside of the contents property. Make sure that 
  8488.  all other properties in your part's storage unit are for annotations or extra 
  8489.  information, rather than for content. Your part's contents property, 
  8490.  however,can include persistent references to other storage units whose 
  8491.  contents properties contain additional content data. 
  8492.  
  8493.  To help you decide which data you should store as content and which you should 
  8494.  not, consider that content includes any data that the user should be able to 
  8495.  save as well as any data that should persist across different part editors, 
  8496.  different machines, and different platforms. 
  8497.  
  8498.  This storage model offers greater flexibility than is available for 
  8499.  application storage on many platforms' file systems. If your applications use 
  8500.  only a single stream to store all of their contents, your equivalent part can 
  8501.  simply store everything in a single value in the contents property of its 
  8502.  storage unit. If your applications use resources, multifork files, or some 
  8503.  other form of structured storage, then your equivalent part can use multiple 
  8504.  storage units referenced from a value in the contents property of your part's 
  8505.  main storage unit. 
  8506.  
  8507.  Because you can add more storage units at any time and save references to them 
  8508.  in any value, you can construct an arbitrarily complex structure for your 
  8509.  stored data. Each additional storage unit can have multiple properties, and 
  8510.  each property can have multiple values. (Remember that different values within 
  8511.  the same property should only be used for different representations of the 
  8512.  same data). 
  8513.  
  8514.  
  8515. ΓòÉΓòÉΓòÉ 9.1.2.3. Reading and Writing ΓòÉΓòÉΓòÉ
  8516.  
  8517. In OpenDoc, reading (also called internalization) is the process of converting 
  8518. a part or other persistent object into its in-memory form, by reading its data 
  8519. from persistent storage. Conversely, writing (also called externalization) 
  8520. converts an in-memory object to its persistent form by copying its essential 
  8521. data to external storage. In general, when a document is opened, its objects 
  8522. are read into memory. As the user edits the document the objects are modified. 
  8523. When the user saves the document, the modified objects are written back to 
  8524. storage. (As noted earlier, the container suite controls how data is physically 
  8525. stored; reading and writing may not necessarily involve an immediate transfer 
  8526. of data between memory and an external physical storage medium). 
  8527.  
  8528. In some instances, OpenDoc may read a part or other object but never write it 
  8529. back to storage. If no changes have been made to a part and it is no longer 
  8530. needed (for example, if its frame has scrolled out of sight on the screen), or 
  8531. if its document is being closed without saving changes, OpenDoc simply deletes 
  8532. the part, (after allowing it to release all of its references to other 
  8533. objects), causing it to be removed from memory. Releasing is described further 
  8534. in Reference-Counted Objects. 
  8535.  
  8536. To maximize performance, OpenDoc requires reading and writing only when 
  8537. absolutely necessary. 
  8538.  
  8539.      A part is not instantiated and read into memory until its draft's 
  8540.       CreatePart or AcquirePart method has been called-meaning that the part 
  8541.       editor is needed for tasks such as drawing, editing, frame negotiation, 
  8542.       or script execution. When a part is read in, OpenDoc has already bound it 
  8543.       to a part editor according to its part kind (and loaded the part editor 
  8544.       if it is not already in memory). 
  8545.  
  8546.      A part is not written to storage until the user performs a save operation 
  8547.       on its document, causing the part's Externalize method to be called. If 
  8548.       the user does not perform a save operation on a document, no changes to 
  8549.       any of its parts are permanently recorded. 
  8550.  
  8551.      When its document is saved or closed, no writing is required of a part if 
  8552.       it has not been altered since it was read into memory. 
  8553.  
  8554.  Your part editor can follow these policies strictly, or it can deviate from 
  8555.  them as necessary. For example, you can write out your part at any time, 
  8556.  without waiting for the user to save the entire document. Note, however, that, 
  8557.  no matter how many times your part writes its data to storage, none of those 
  8558.  changes will become persistent unless the user performs a save and your part's 
  8559.  Externalize method is called. 
  8560.  
  8561.  How to read and write your part's data is described in Reading and Writing 
  8562.  your Part. 
  8563.  
  8564.  
  8565. ΓòÉΓòÉΓòÉ 9.1.2.4. What a Draft Contains ΓòÉΓòÉΓòÉ
  8566.  
  8567. The following table shows some of the kinds of information that can be stored 
  8568. persistently as properties of the various objects that make up the storage 
  8569. units in a draft of an OpenDoc document. Note that some of the storage units 
  8570. shown in the following table reflect the objects and persistent references 
  8571. shown in the figure in Persistent References in OpenDoc, as well as the 
  8572. run-time object references shown in Run-Time Object Relationships. Furthermore, 
  8573. some properties should not be accessed by part editors. This list is not 
  8574. complete, nor are all properties shown here required to be present. For more 
  8575. information on these and other standard properties, see "Types, Constants, and 
  8576. Errors" in OpenDoc Class Reference for the Macintosh. 
  8577.  
  8578. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8579. ΓöéProperty                      ΓöéDescription                   Γöé
  8580. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8581. ΓöéAny Storage Unit:             Γöé                              Γöé
  8582. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8583. ΓöékODPropObjectType             ΓöéType of object stored in this Γöé
  8584. Γöé                              Γöéstorage unit (draft, frame,   Γöé
  8585. Γöé                              Γöépart, and so on)              Γöé
  8586. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8587. ΓöéDraft Storage Unit:           Γöé                              Γöé
  8588. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8589. ΓöékODPropRootPartSU             ΓöéStrong persistent reference toΓöé
  8590. Γöé                              Γöéthe root part of this draft   Γöé
  8591. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8592. ΓöéFrame Storage Unit            Γöé                              Γöé
  8593. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8594. ΓöékODPropPart                   ΓöéStrong persistent reference toΓöé
  8595. Γöé                              Γöéthe part displayed in this    Γöé
  8596. Γöé                              Γöéframe                         Γöé
  8597. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8598. ΓöékODPropContainingFrame        ΓöéWeak persistent reference to  Γöé
  8599. Γöé                              Γöéthe containing frame of this  Γöé
  8600. Γöé                              Γöéframe                         Γöé
  8601. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8602. ΓöékODPropFrameShape             ΓöéFrame shape of this frame     Γöé
  8603. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8604. ΓöékODPropPartInfo               ΓöéPart info (part-specific data)Γöé
  8605. Γöé                              Γöéassociated with this frame    Γöé
  8606. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8607. ΓöékODPropViewType               ΓöéView type of the part         Γöé
  8608. Γöé                              Γöédisplayed in this frame       Γöé
  8609. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8610. ΓöékODPropPresentation           ΓöéPresentation of the part      Γöé
  8611. Γöé                              Γöédisplayed in this frame       Γöé
  8612. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8613. ΓöékODPropInternalTransform      ΓöéInternal transform of this    Γöé
  8614. Γöé                              Γöéframe                         Γöé
  8615. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8616. ΓöékODPropFrameGroup             ΓöéGroup ID of the frame group   Γöé
  8617. Γöé                              Γöéthis frame belongs to         Γöé
  8618. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8619. ΓöékODPropSequenceNumber         ΓöéSequence number of this frame Γöé
  8620. Γöé                              Γöéin its frame group            Γöé
  8621. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8622. ΓöékODPropLinkStatus             ΓöéThe link status (in-source,   Γöé
  8623. Γöé                              Γöéin-destination, or not in     Γöé
  8624. Γöé                              Γöélink) of this frame           Γöé
  8625. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8626. ΓöékODPropIsRoot                 ΓöéTrue if this frame is root    Γöé
  8627. Γöé                              Γöéframe in window               Γöé
  8628. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8629. ΓöékODPropIsSubframe             ΓöéTrue if this frame is a       Γöé
  8630. Γöé                              Γöésubframe                      Γöé
  8631. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8632. ΓöékODPropIsOverlaid             ΓöéTrue if this frame is overlaidΓöé
  8633. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8634. ΓöékODPropIsFrozen               ΓöéTrue if this frame is bundled Γöé
  8635. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8636. ΓöékODPropDoesPropagateEvents    ΓöéTrue if this frame's part     Γöé
  8637. Γöé                              Γöépropagates events             Γöé
  8638. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8639. ΓöéPart Storage Unit:            Γöé                              Γöé
  8640. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8641. ΓöékODPropContents               ΓöéPart content (the actual      Γöé
  8642. Γöé                              Γöéstored data of this part)     Γöé
  8643. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8644. ΓöékODPropDisplayFrames          ΓöéWeak persistent references to Γöé
  8645. Γöé                              Γöéthe display frames of this    Γöé
  8646. Γöé                              Γöépart                          Γöé
  8647. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8648. ΓöéClipboard or Drag-and-Drop    Γöé                              Γöé
  8649. ΓöéStorage Unit:                 Γöé                              Γöé
  8650. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8651. ΓöékODPropContents               ΓöéThe contents of the Clipboard Γöé
  8652. Γöé                              Γöé(or drag-and-drop object)     Γöé
  8653. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8654. ΓöékODPropSuggestedFrameShape    ΓöéSuggested shape for frame, if Γöé
  8655. Γöé                              Γöécontents are embedded at      Γöé
  8656. Γöé                              Γöédestination                   Γöé
  8657. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8658. ΓöékODPropLinkSpec               ΓöéA link specification          Γöé
  8659. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8660. ΓöékODPropContentFrame           Γöé(Exists if data is a single   Γöé
  8661. Γöé                              Γöéembedded frame)               Γöé
  8662. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8663. ΓöékODPropProxyContents          ΓöéSuggested adornments to apply Γöé
  8664. Γöé                              Γöéto frame (if data is a single Γöé
  8665. Γöé                              Γöéembedded frame)               Γöé
  8666. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8667. ΓöéLink Storage Unit             Γöé                              Γöé
  8668. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8669. ΓöékODPropLinkSource             ΓöéWeak persistent reference to  Γöé
  8670. Γöé                              Γöéthe link-source object        Γöé
  8671. Γöé                              Γöéassociated with this link     Γöé
  8672. Γöé                              Γöéobject                        Γöé
  8673. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8674. ΓöéLink-Source Storage Unit:     Γöé                              Γöé
  8675. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8676. ΓöékODPropLink                   ΓöéWeak persistent reference to aΓöé
  8677. Γöé                              Γöélink object associated with   Γöé
  8678. Γöé                              Γöéthis link-source object       Γöé
  8679. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8680. ΓöékODPropSourcePart             ΓöéWeak persistent reference to  Γöé
  8681. Γöé                              Γöéthe part that contains (or    Γöé
  8682. Γöé                              Γöélast contained) the source    Γöé
  8683. Γöé                              Γöédata for this link            Γöé
  8684. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8685. ΓöékODPropLinkContentSU          ΓöéStrong persistent reference toΓöé
  8686. Γöé                              Γöéthe contents storage unit for Γöé
  8687. Γöé                              Γöéthe linked data               Γöé
  8688. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8689. ΓöékODPropChangeTime             ΓöéThe date and time of this     Γöé
  8690. Γöé                              Γöélink's last update            Γöé
  8691. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8692. ΓöékODPropUpdateID               ΓöéThe update ID for this link's Γöé
  8693. Γöé                              Γöélast update                   Γöé
  8694. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8695. ΓöékODPropAutoUpdate             ΓöéTrue if link is to be updated Γöé
  8696. Γöé                              Γöéautomatically                 Γöé
  8697. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8698.  
  8699. (Other standard part properties are listed in the following table. 
  8700.  
  8701. Your part editor is responsible for reading and writing only the data that is 
  8702. stored persistently by your parts; OpenDoc takes care of persistent storage of 
  8703. the other objects listed in the preceding table. Basically, each of the objects 
  8704. can read and write itself. 
  8705.  
  8706.  
  8707. ΓòÉΓòÉΓòÉ 9.1.2.5. Info Properties ΓòÉΓòÉΓòÉ
  8708.  
  8709. Some of the standard properties associated with a part are made visible to the 
  8710. user, either for information purposes only or to allow the user to modify them. 
  8711. This set of properties, called Info properties, is displayed in the Document 
  8712. Properties notebook. The last-modified date and time (kODPropModDate) is an 
  8713. example of an Info property that the user cannot change; the name of the part 
  8714. (kODPropName) is an example of an Info property that the user can change. The 
  8715. following table lists the standard Info properties of parts defined for version 
  8716. 1.0 of OpenDoc. 
  8717.  
  8718. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8719. ΓöéProperty                      ΓöéExplanation                   Γöé
  8720. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8721. ΓöékODPropName                   ΓöéThe user-assigned name of the Γöé
  8722. Γöé                              Γöépart                          Γöé
  8723. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8724. ΓöékODPropViewType               ΓöéThe view type of the part in  Γöé
  8725. Γöé                              Γöéthe currently selected frame  Γöé
  8726. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8727. ΓöékODPropIsFrozen               ΓöéTrue if the part is bundled,  Γöé
  8728. Γöé                              Γöéfalse if not                  Γöé
  8729. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8730. ΓöékODPropIsStationery           ΓöéTrue if the part is           Γöé
  8731. Γöé                              Γöéstationery, false if not      Γöé
  8732. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8733. ΓöékODPropIconFamily             ΓöéThe icons that represent this Γöé
  8734. Γöé                              Γöépart                          Γöé
  8735. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8736. ΓöékODPropPreferredKind          ΓöéThe user-specified part kind  Γöé
  8737. Γöé                              Γöéfor the data of this part     Γöé
  8738. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8739. ΓöékODPropPreferredEditor        ΓöéThe user-specified preferred  Γöé
  8740. Γöé                              Γöéeditor for editing this part  Γöé
  8741. Γöé                              Γöé(the ID of the editor that    Γöé
  8742. Γöé                              Γöélast wrote this part to       Γöé
  8743. Γöé                              Γöépersistent storage)           Γöé
  8744. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8745. ΓöékODPropCreateDate             ΓöéThe date and time at which    Γöé
  8746. Γöé                              Γöéthis part was originally      Γöé
  8747. Γöé                              Γöécreated                       Γöé
  8748. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8749. ΓöékODPropModDate                ΓöéThe date and time at which    Γöé
  8750. Γöé                              Γöéthis part was last modified   Γöé
  8751. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8752. ΓöékODPropModUser                ΓöéThe name of the user that lastΓöé
  8753. Γöé                              Γöémodified this part            Γöé
  8754. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8755. ΓöékODPropComments               ΓöéComments entered by the user  Γöé
  8756. Γöé                              Γöéinto this part's Document     Γöé
  8757. Γöé                              ΓöéProperties notebook           Γöé
  8758. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8759.  
  8760. Your part editor can define and attach additional user properties to its parts' 
  8761. storage units. You can then display them to the user in a Settings dialog box, 
  8762. accessible from the Document Properties notebook. See The Settings Extension 
  8763. for more information. 
  8764.  
  8765.  
  8766. ΓòÉΓòÉΓòÉ 9.1.2.6. Container Properties ΓòÉΓòÉΓòÉ
  8767.  
  8768. If your part contains embedded parts, you may want the embedded parts to adopt, 
  8769. by default, some of your current display settings or behavior. For example, if 
  8770. your part is a text part, it may be appropriate for other text parts embedded 
  8771. within it to have the same text characteristics (font, size, style, and so on), 
  8772. unless the user overrides them. 
  8773.  
  8774. You can define such a set of characteristics as properties and attach them to 
  8775. your parts' storage units. These container properties then become available to 
  8776. embedded parts for adoption. See Adopting Container Properties and Transmitting 
  8777. your Container Properties to Embedded Parts for more information. 
  8778.  
  8779.  
  8780. ΓòÉΓòÉΓòÉ 9.1.2.7. Creating a New Document ΓòÉΓòÉΓòÉ
  8781.  
  8782. Under most circumstances, your part editor never creates a document. Other 
  8783. parts of OpenDoc, such as the document shell, handle document creation when the 
  8784. user chooses a menu command such as New or drags a part to the desktop. 
  8785.  
  8786. If, however, your part editor provides its own document-creation interface to 
  8787. the user, or if it caches its own data in separate OpenDoc documents, then it 
  8788. must use methods of the container suite to create those documents. 
  8789.  
  8790. In your document creation method, you can follow steps such as these: 
  8791.  
  8792.    1. Create a file object, following whatever platform-specific procedures are 
  8793.       required by the file system that is in use. 
  8794.  
  8795.    2. Create an OpenDoc container, document, and draft for the file. Call the 
  8796.       session object's CreateFileContainer method, then the file container's 
  8797.       AcquireDocument method, and then the document's AcquireBaseDraft method. 
  8798.  
  8799.    3. Create the root part. Call the base draft's CreatePart method, then 
  8800.       obtain the root part's storage unit and assign it to the draft. Call the 
  8801.       draft's Externalize method to save the storage unit. 
  8802.  
  8803.    4. Assign the proper file type to the file. This involves giving it a file 
  8804.       type (an OSType) that represents the root part's part kind and assigning 
  8805.       the document a creator type (also an OSType) that is the signature of the 
  8806.       OpenDoc document shell (Open Scripting Architecture Quick 
  8807.       Referenceodtm'). 
  8808.  
  8809.    5. Release the objects you have created:  the root part, the draft, the 
  8810.       document, and the container. Finally, delete the platform-specific file 
  8811.       object that you created. (This does not delete the file from persistent 
  8812.       storage). 
  8813.  
  8814.  
  8815. ΓòÉΓòÉΓòÉ 9.2. Reading and Writing your Part ΓòÉΓòÉΓòÉ
  8816.  
  8817. This section discusses how your part reads and writes its own content data, as 
  8818. well as related OpenDoc objects, such as frames, that it uses. 
  8819.  
  8820. Your part editor must be able to read and write any parts whose data formats 
  8821. (part kinds) it recognizes. You are not required to read the entire contents of 
  8822. your part into memory at once, and you need not write it all to storage at 
  8823. once. However, reading must put your part in a state in which it can accept 
  8824. events and handle requests, and writing it must ensure that changes made by the 
  8825. user are not lost. 
  8826.  
  8827. Your part editor should never change the part kind of any part you handle 
  8828. except as a result of an explicit user request. Any translations required to 
  8829. make a part readable, whether performed by OpenDoc or by your part editor, are 
  8830. first selected by the user. See Binding and Translation for more information. 
  8831.  
  8832.  
  8833. ΓòÉΓòÉΓòÉ 9.2.1. Initializing and Reading a Part from Storage ΓòÉΓòÉΓòÉ
  8834.  
  8835. A part must be able to read itself (reconstruct itself in memory by reading its 
  8836. stored data). Whenever a document in which your part is visible is opened, or 
  8837. whenever your part is added to a document, your part must be read into memory. 
  8838. Note that OpenDoc parts should always be ready to work from an empty storage 
  8839. unit as well. The two fundamental methods that your part must implement for 
  8840. initializing itself are InitPart and InitPartFromStorage. 
  8841.  
  8842.  
  8843. ΓòÉΓòÉΓòÉ 9.2.1.1. The somInit Method ΓòÉΓòÉΓòÉ
  8844.  
  8845. When your part object is first created (or recreated from storage), and before 
  8846. receiving a call to its InitPart or InitPartFromStorage method, your part 
  8847. receives a call to its SOM object constructor somInit. The somInit method is 
  8848. inherited from the somObject class of SOM; when you subclass ODPart, you must 
  8849. override somInit. 
  8850.  
  8851. Your somInit method should initialize (clear) your part object's instance 
  8852. variables. You must not perform any tasks in this method that might fail. You 
  8853. can set pointer variables to null and assign appropriate values to numeric 
  8854. variables. If you have any initialization code that can potentially fail, your 
  8855. part's InitPart or InitPartFromStorage method must handle it. 
  8856.  
  8857.  
  8858. ΓòÉΓòÉΓòÉ 9.2.1.2. The InitPart Method ΓòÉΓòÉΓòÉ
  8859.  
  8860. The InitPart method is called only once in your part's lifetime, by your 
  8861. draft's CreatePart method, when your part is first created and has no 
  8862. previously stored data to read. (If your part is created from stationery, this 
  8863. method is never called). This is its interface: 
  8864.  
  8865. void InitPart(in ODStorageUnit storageUnit,
  8866.               in ODPart partWrapper);
  8867.  
  8868. In the simplest case, you could take these steps: Call your inherited InitPart 
  8869. method, which in turn calls its inherited InitPersistentObject method to 
  8870. initialize the information your part needs as a persistent object. (Your 
  8871. classes' initialization methods should always call their superclasses' 
  8872. initialization methods). 
  8873.  
  8874.    1. If your part stores its data in multiple part kinds, add a contents 
  8875.       property (type kODPropContents) and a value (of your highest-fidelity 
  8876.       part kind) to the storage unit passed to you, thus preparing your part 
  8877.       for eventual writing of its data. Add values for other part kinds also, 
  8878.       if appropriate. Initialize the values if necessary. 
  8879.  
  8880.    2. If your part stores more than one part kind, add a preferred-kind 
  8881.       property (type kODPropPreferredKind) to the storage unit passed to you, 
  8882.       and write into a value of that property an ISO string representing your 
  8883.       editor's highest-fidelity part kind. Normally, that part kind should 
  8884.       equal the type of the first value in your contents property. 
  8885.  
  8886.    3. Save, in a field (such as fSelf) of your part, the contents of the 
  8887.       partWrapper parameter passed to this method. It represents an object 
  8888.       reference through which OpenDoc interacts with your part. It represents 
  8889.       an object reference (pointer) through which OpenDoc calls back to your 
  8890.       part. See Part-Wrapper Object for more information. 
  8891.  
  8892.    4. Initialize any data pointers or size values that your part maintains. At 
  8893.       this point you might mark your part as clean (unchanged). You could use a 
  8894.       "dirty flag" for this purpose, which you initialize as cleared, and then 
  8895.       set whenever you change your part's content. 
  8896.  
  8897.  
  8898. ΓòÉΓòÉΓòÉ 9.2.1.3. The InitPartFromStorage Method ΓòÉΓòÉΓòÉ
  8899.  
  8900. The InitPartFromStorage is similar to InitPart, except that InitPartFromStorage 
  8901. also reads in data. Your draft's AcquirePart method calls your 
  8902. InitPartFromStorage method and supplies a storage unit from which the part 
  8903. reads itself. Your part retrieves, from the kODPropContents property of the 
  8904. storage unit, the value (specified by part kind) that represents the data 
  8905. stream you wish to read. This is its interface: 
  8906.  
  8907. void InitPartFromStorage(in ODStorageUnit storage unit,
  8908.                          in ODPart partWrapper);
  8909. In your InitPartFromStorage method, take steps like these: 
  8910.  
  8911.    1. Call your inherited InitPartFromStorage method, which in turn calls its 
  8912.       inherited InitPersistentObject method to initialize the information your 
  8913.       part needs as a previously stored persistent object. 
  8914.  
  8915.    2. Determine the appropriate part kind of data to read in: 
  8916.  
  8917.           Your editor may be reading in a part that was created or previously 
  8918.            edited by a different editor (see Binding Process). Focus on the 
  8919.            kODPropPreferredKind of the storage unit passed to you, and retrieve 
  8920.            the part's preferred kind (the part kind you should consider to be 
  8921.            the highest-fidelity). This part kind may or may not equal the type 
  8922.            of the first value in the part's contents property. 
  8923.  
  8924.           If the kODPropPreferredKind property does not exist, assume that the 
  8925.            first value within the contents property is the preferred kind. Save 
  8926.            the preferred-kind designation for use later (when you write to 
  8927.            storage). 
  8928.  
  8929.       If this is dropped non-OpenDoc file data that you have just been bound to 
  8930.       (see Accepting Non-OpenDoc Data), you can take these steps: 
  8931.  
  8932.           OpenDoc will have provided, in the contents property, a value type 
  8933.            representing the file type. If the item is a text file, for example, 
  8934.            the value type is "kODKindOS2Text". 
  8935.  
  8936.           Assuming your part can read data of that file type, you can then 
  8937.            obtain the file type and file name from the kODFileTypeEA and 
  8938.            kODFileType values. 
  8939.  
  8940.           Using this information (such as the file specification), you can 
  8941.            then make file-system-specific calls to open the file and process 
  8942.            its contents into a buffer in memory. If you must store it 
  8943.            immediately and the draft permissions allow you to, write it into an 
  8944.            appropriate value or values in your part's contents property. 
  8945.            Otherwise, you can wait until your Externalize method is called 
  8946.            before writing it to your storage unit. 
  8947.  
  8948.            Skip to Step 7. 
  8949.  
  8950.    3. Focus the storage unit on its contents property and on the value 
  8951.       containing the part's preferred kind, if you can read that kind. If you 
  8952.       cannot read the preferred kind, focus on the highest-fidelity part kind 
  8953.       that you can read. (Even if you do not read in the preferred kind at this 
  8954.       stage, do not yet change the value in the kODPropPreferredKind property). 
  8955.  
  8956.    4. Read the data into your part's buffer, using the GetValue method. 
  8957.  
  8958.    5. Read in additional objects as needed, as persistent references within 
  8959.       your main storage unit's kODPropContents property lead you to information 
  8960.       stored elsewhere. See, for example, Creating Additional Storage Units, 
  8961.       Storing and Retrieving Embedded Frames, and Reading Linked Content from 
  8962.       Storage. 
  8963.  
  8964.    6. If your part's display frames have been stored, read them in as discussed 
  8965.       in Storing and Retrieving Display Frames. 
  8966.  
  8967.    7. Call your draft's GetPermissions method and save the results in a field 
  8968.       of your part. Respect the permissions in later attempts to write to the 
  8969.       draft. See Drafts for more information. 
  8970.  
  8971.    8. Save, in a field (such as fSelf) of your part, the contents of the 
  8972.       partWrapper parameter passed to this method. It represents a reference 
  8973.       (pointer) through which OpenDoc calls back to your part. See Part-Wrapper 
  8974.       Object for more information. 
  8975.  
  8976.    9. Initialize any data pointers or size values that your part maintains. At 
  8977.       this time you might, if you maintain a dirty flag, mark your part as 
  8978.       clean (unchanged). 
  8979.  
  8980.  
  8981. ΓòÉΓòÉΓòÉ 9.2.2. Writing a Part to Storage ΓòÉΓòÉΓòÉ
  8982.  
  8983. Your part must be able to write itself (write its data to persistent storage, 
  8984. typically external storage such as a disk) when instructed to do so. This 
  8985. instruction may come at any time, not just when the user saves or closes your 
  8986. document. 
  8987.  
  8988. This section discusses the Externalize and ExternalizeKinds methods of your 
  8989. part editor. Another method that involves writing your part data to storage is 
  8990. the CloneInto method, described in CloneInto Method of your Part Editor. 
  8991.  
  8992.  
  8993. ΓòÉΓòÉΓòÉ 9.2.2.1. The Externalize Method ΓòÉΓòÉΓòÉ
  8994.  
  8995. A caller instructs your part to write its data to storage by calling your 
  8996. part's override of its inherited Externalize method. Your part then writes its 
  8997. data into its storage unit. 
  8998.  
  8999. As a minimum, your part must write one property: kODPropContents. The 
  9000. kODPropContents property contains your part's intrinsic data. You can write 
  9001. your part's data in multiple part kinds, representing multiple data formats, in 
  9002. the kODPropContents property. Each format is a separate stream, defined as a 
  9003. separate value in the property, and each value must be a complete 
  9004. representation of your part's contents. 
  9005.  
  9006. You can add other properties and values as annotations to your part's storage 
  9007. unit, and you can access them for your own purposes. However, remember that the 
  9008. OpenDoc binding process looks only at the value types of kODPropContents when 
  9009. assigning an editor to a part. 
  9010.  
  9011. The fundamental method that your part must override for writing its data to 
  9012. storage is the Externalize method, inherited from the class ODPersistentObject. 
  9013. This is its interface: 
  9014.  
  9015. void Externalize ();
  9016.  
  9017. In a simple Externalize method, you might take these basic steps: 
  9018.  
  9019.    1. Call the inherited Externalize method to make sure that the appropriate 
  9020.       persistent-object information for your part is  written to storage. 
  9021.  
  9022.    2. Examine your part to see whether it is dirty-that is, whether the content 
  9023.       has been changed since the last write. If it is clean (unchanged), take 
  9024.       no further action. 
  9025.  
  9026.    3. Get a reference to your main storage unit by calling your part's 
  9027.       inherited GetStorageUnit method. 
  9028.  
  9029.    4. Your editor may be writing a part that was created or previously edited 
  9030.       by a different editor (see Binding Process). If so, you need to prepare 
  9031.       the contents property of the part to match the part kinds and fidelity 
  9032.       order that your part editor uses. (This step is required only the first 
  9033.       time you write a part after having been first bound to it). 
  9034.  
  9035.           Remove any values in the storage unit that represent kinds that your 
  9036.            part editor does not support or does not intend to save. 
  9037.  
  9038.           Add values if necessary, so that values for all part kinds that your 
  9039.            part editor intends to include are present. Make sure the values are 
  9040.            in fidelity order, and make sure that the preferred part kind, 
  9041.            determined when you read the part in, is one of the values that you 
  9042.            write. 
  9043.  
  9044.    5. Focus the storage unit on the contents property and on each of the part 
  9045.       kinds of the data you are writing in turn. Write your data to the storage 
  9046.       unit, using its SetValue method. Write one value for each part kind of 
  9047.       data you store. 
  9048.  
  9049.       If your part is a container part, you write persistent references to your 
  9050.       embedded frames as part of writing your content. See Storing and 
  9051.       Retrieving Embedded Frames. 
  9052.  
  9053.    6. Store references to your display frames, as described in Storing and 
  9054.       Retrieving Display Frames. 
  9055.  
  9056.    7. Mark your part as clean (unchanged). 
  9057.  
  9058.  Typically, in writing your content you might write out just two values: one in 
  9059.  the preferred part kind, and another in a standard, widely recognized part 
  9060.  kind useful for data interchange. If your part editor supports many kinds, you 
  9061.  might allow the user to select a single default kind, to avoid the creation of 
  9062.  very large files full of redundant data. 
  9063.  
  9064.  Note:  Do not change the preferred kind from what it was when you read the 
  9065.         part, even if you can easily convert the data to a higher-fidelity part 
  9066.         kind. (You can, however, store a higher-fidelity part kind in addition 
  9067.         to the preferred kind, if you wish). Such a change is implicit 
  9068.         translation, and translation should always be controlled by the user. 
  9069.         Maintain the preferred kind until the user instructs you to change it, 
  9070.         as in the examples described in Binding with Translation. 
  9071.  
  9072.  Your part can write its contents to its storage unit at any time, not just in 
  9073.  response to a call to its Externalize method. However, changes to any parts in 
  9074.  a document are actually made persistent only when the user performs an 
  9075.  explicit save, and thus only when Externalize is called. If your part updates 
  9076.  its storage unit but the user never saves the document, your changes are lost. 
  9077.  
  9078.  
  9079. ΓòÉΓòÉΓòÉ 9.2.2.2. The ExternalizeKinds Method ΓòÉΓòÉΓòÉ
  9080.  
  9081. Your part's ExternalizeKinds method can be called whenever your part is 
  9082. expected to save its data with a specific set of formats. For example, OpenDoc 
  9083. calls ExternalizeKinds when the user saves a copy of your part's document in 
  9084. multiple formats . A document-interchange utility or service might call the 
  9085. ExternalizeKinds method of all parts in a document to create a version of the 
  9086. document in which all parts are written in one or more common standard part 
  9087. kinds. 
  9088.  
  9089. When your part's ExternalizeKinds method is called, it is passed a list of part 
  9090. kinds. This is the method's interface: 
  9091.  
  9092. void ExternalizeKinds (in ODTypeList kindSet);
  9093.  
  9094. The method should write as many of the specified part kinds as it supports, as 
  9095. well as your part's preferred kind. The method should ignore part kinds on the 
  9096. list that it does not support, and it should remove values (other than the 
  9097. preferred kind) from its storage unit that are not on the list. Just like 
  9098. Externalize, the ExternalizeKinds method should make sure to write the part 
  9099. kinds in proper fidelity order, and not change the preferred kind. 
  9100.  
  9101.  
  9102. ΓòÉΓòÉΓòÉ 9.2.3. Creating Additional Storage Units ΓòÉΓòÉΓòÉ
  9103.  
  9104. Your part can use persistent references to create an auxiliary storage unit for 
  9105. keeping additional data. The auxiliary unit must be referenced from your part's 
  9106. main storage unit, using a strong persistent reference. In brief, you can 
  9107. follow these steps: 
  9108.  
  9109.    1. Call the CreateStorageUnit method of your part's draft to create the 
  9110.       storage unit to hold the data. 
  9111.  
  9112.    2. Focus your part's main storage unit on the value in your contents 
  9113.       property that is to contain the persistent reference. (It is not 
  9114.       necessary to create a separate value to hold the reference). 
  9115.  
  9116.    3. Create the persistent reference, by calling the GetStrongStorageUnitRef 
  9117.       method of your main storage unit. 
  9118.  
  9119.    4. Store the reference anywhere in the value; the only requirement is that 
  9120.       you be able to recognize and retrieve the reference later. Write the 
  9121.       value to persistent storage, by calling the SetValue method of your main 
  9122.       storage unit. 
  9123.  
  9124.  Your part can later retrieve the auxiliary storage unit from the main storage 
  9125.  unit, in this way: 
  9126.  
  9127.    1. Focus the main storage unit on the value that contains the persistent 
  9128.       reference. 
  9129.  
  9130.    2. Read the value, using the GetValue method of your main storage unit. 
  9131.       Retrieve the persistent reference from the value's data. 
  9132.  
  9133.    3. Get the storage unit ID of your auxiliary storage unit from the 
  9134.       persistent reference, by calling the GetIDFromStorageUnitRef method of 
  9135.       your main storage unit. 
  9136.  
  9137.    4. Get the storage unit itself by passing its ID to the AcquireStorageUnit 
  9138.       method of your draft. 
  9139.  
  9140.  How you store the data in your auxiliary storage unit is completely up to you. 
  9141.  You can define your own properties, or you can keep the kinds of properties 
  9142.  (such as kODPropContents) used in your main storage unit. If you define your 
  9143.  own property names, avoid using constants for them that start with kOD; only 
  9144.  OpenDoc-defined constants should use those characters. 
  9145.  
  9146.  
  9147. ΓòÉΓòÉΓòÉ 9.2.4. Storing and Retrieving Display Frames ΓòÉΓòÉΓòÉ
  9148.  
  9149. As noted in Working with your Display Frames and Facets, your part should keep 
  9150. a private list of its display frames. It is further recommended that your part 
  9151. persistently store those display frames when it writes itself to storage, and 
  9152. retrieve them when it reads itself from storage. Your part may need information 
  9153. on currently nonvisible, uninstantiated display frames in order to perform 
  9154. frame synchronization (see Synchronizing Display Frames) or frame negotiation 
  9155. (see Frame Negotiation). 
  9156.  
  9157. If your part object includes a field that is a list of display-frame objects, 
  9158. your InitPart method can first create the field, and your DisplayFrameAdded, 
  9159. DisplayFrameRemoved, DisplayFrameConnected, and DisplayFrameClosed methods can 
  9160. add or delete elements of the list, as appropriate. 
  9161.  
  9162. You can keep additional information about the frames in this field, such as 
  9163. what portion of your content (like a page number) each displays. That way, you 
  9164. can instantiate only those frames that you currently need to manipulate, using 
  9165. the techniques described in Lazy Instantiation. 
  9166.  
  9167. You should store your list of frames in an annotation property in your part's 
  9168. storage unit. Your Externalize method should create a property with the name 
  9169. kODPropDisplayFrames in your storage unit, and write the frame list as weak 
  9170. storage unit references into a value of that property. 
  9171.  
  9172. When reading your part from storage, your InitPartFromStorage method can focus 
  9173. on the kODPropDisplayFrames property and value, and read the list of stored 
  9174. display frames back into your display-frame field. (Be sure your ReleaseAll 
  9175. method releases any remaining display frames in that field; see The ReleaseAll 
  9176. Method). 
  9177.  
  9178.  
  9179. ΓòÉΓòÉΓòÉ 9.2.5. Storing and Retrieving Embedded Frames ΓòÉΓòÉΓòÉ
  9180.  
  9181. Your part does not explicitly store the data of embedded parts; their own part 
  9182. editors take care of that. You do not even explicitly store the frame objects 
  9183. that you use; OpenDoc takes care of that. You do, however, store persistent 
  9184. references to the frames that are embedded in your part. 
  9185.  
  9186. The process of storing an embedded frame for your part is simple. All you need 
  9187. to do is store a strong persistent reference to the embedded frame object; 
  9188. OpenDoc takes care of storing the frame itself. You follow the same steps that 
  9189. you take when creating and storing a reference to any storage unit (described 
  9190. in Creating Additional Storage Units): 
  9191.  
  9192.    1. Focus your storage unit on your contents property and the value that is 
  9193.       to contain the persistent reference to the embedded frame. 
  9194.  
  9195.    2. Create the persistent reference and place it in your contents data. 
  9196.  
  9197.    3. Write the data back into the value. 
  9198.  
  9199.  When recreated at a later time, your part can then retrieve the frame this 
  9200.  way: 
  9201.  
  9202.    1. Focus the storage unit on the value containing the persistent reference. 
  9203.  
  9204.    2. Retrieve the reference. 
  9205.  
  9206.    3. Get the storage-unit ID of the frame. 
  9207.  
  9208.    4. Recreate the frame itself, by calling your draft's AcquireFrame method. 
  9209.  
  9210.  For efficient memory use, you can instantiate only those embedded frames that 
  9211.  you currently need to manipulate or display, using the techniques described in 
  9212.  Lazy Instantiation. 
  9213.  
  9214.  
  9215. ΓòÉΓòÉΓòÉ 9.2.6. Reading and Writing Part Info ΓòÉΓòÉΓòÉ
  9216.  
  9217. As noted in Part Info, you can use the part info field of a frame or facet to 
  9218. store any display-related information you want associated with that particular 
  9219. frame or facet. Because frames are persistent objects and facets are not, a 
  9220. frame's part info can be stored persistently, whereas a facet's part info 
  9221. cannot. 
  9222.  
  9223. Just as you store multiple representations of your part's data, you should 
  9224. store multiple representations of your frames' part info, so that other editors 
  9225. can potentially read your part info as well as your part content. In that case, 
  9226. you should give your part info formats names equivalent to the part kinds they 
  9227. are associated with. For example, if you write part data whose part kind is 
  9228. "SurfCorp:SurfWriter:StyledText", your associated part info data should be 
  9229. written in a value whose type is "SurfCorp::SurfWriter:StyledText:PartInfo". 
  9230.  
  9231. If you also write your part data in a standard format such as PICT or RTF or 
  9232. JPEG, you would not write associated part info for those formats, because they 
  9233. have no associated part info format. 
  9234.  
  9235. As with other changes to the contents of your part's draft, any time you place 
  9236. or modify information in your display frame's part info field, you should 
  9237. follow the procedures listed in Making Content Changes Known. (If your frame is 
  9238. a nonpersistent frame, however, you do not need to make changes to it known). 
  9239.  
  9240. Whenever your document is saved, your part's WritePartInfo method is called for 
  9241. each of your part's display frames. Here is its interface: 
  9242.  
  9243. void WritePartInfo(in ODPointer partInfo,
  9244.                    in ODStorageUnitView storageUnitView);
  9245.  
  9246. On receiving this call, you could first examine your part's own part-info dirty 
  9247. flag (if you have defined one) to see if this frame's part info has changed 
  9248. since it was read in from storage. If it has, focus on as many values in the 
  9249. provided storage unit view as is appropriate and write your current part info 
  9250. into them. (And then clear the dirty flag). 
  9251.  
  9252. Conversely, whenever a display frame of your part is read into memory, your 
  9253. part's ReadPartInfo method is called. Here is its interface: 
  9254.  
  9255. ODPtr ReadPartInfo(in ODFrame frame,
  9256.                    in ODStorageUnitViewstorageUnitView);
  9257.  
  9258. On receiving this call, you should allocate a structure to hold the part info, 
  9259. focus on the appropriate value in the provided storage-unit view, and read the 
  9260. data into your part-info structure. (And initialize your part-info dirty flag 
  9261. to clean). 
  9262.  
  9263. Your part also writes part info data when its display frames are cloned; see 
  9264. ClonePartInfo Method of your Part Editor for more information. 
  9265.  
  9266.  
  9267. ΓòÉΓòÉΓòÉ 9.3. Changing your Part's Content ΓòÉΓòÉΓòÉ
  9268.  
  9269. Users can change the content of your part through a variety of standard editing 
  9270. actions involving keyboard input, menu commands, scripting, and so on. How you 
  9271. can support those tasks is described throughout this book, with additional 
  9272. information and other programming texts. 
  9273.  
  9274. What this section describes is what you must (or need not) inform OpenDoc of 
  9275. when you do make content changes, and what it fundamentally means to embed 
  9276. parts within your part and remove embedded parts from it. 
  9277.  
  9278.  
  9279. ΓòÉΓòÉΓòÉ 9.3.1. Adding an Embedded Part ΓòÉΓòÉΓòÉ
  9280.  
  9281. Embedding is essentially a process of data transfer. Your part embeds a new or 
  9282. preexisting frame into its content; that embedded frame displays the content of 
  9283. a new or preexisting part. You create a new embedded frame by calling your 
  9284. draft's CreateFrame method; you embed a preexisting frame by calling your 
  9285. draft's AcquireFrame method. 
  9286.  
  9287. The data-transfer procedures for embedding a part within your part are 
  9288. described in detail in Pasting from the Clipboard, Dropping, and Using a Tool 
  9289. Palette to Embed Parts. See those sections for more information. In summary, 
  9290. however, you perform these tasks when you embed: 
  9291.  
  9292.    1. You decide, based on your own part's content model and on information 
  9293.       accompanying the transferred data, what area is to be given to the 
  9294.       embedded part for display: 
  9295.  
  9296.           You retrieve or define a frame shape for the embedded frame. (The 
  9297.            part may or may not arrive with a suggested frame or frame shape). 
  9298.  
  9299.           You decide where to position the embedded frame in your part's 
  9300.            content; based on that position, you will eventually create an 
  9301.            external transform to use for positioning the facets of the embedded 
  9302.            frame. 
  9303.  
  9304.    2. For each of your own part's display frames that is to show the embedded 
  9305.       part, you create or recreate a frame object, and you either explicitly or 
  9306.       implicitly create or recreate a part object: 
  9307.  
  9308.           If the frame you are embedding is not already attached to its part, 
  9309.            you either retrieve the part object (as when embedding pasted 
  9310.            content that has no preexisting frame or adding a new frame to an 
  9311.            existing embedded part) or you create a new part object (as when 
  9312.            creating a new part from a palette), so that you can attach it to 
  9313.            its frame. The embedded part is stored in your part's draft, but not 
  9314.            within your part itself. 
  9315.  
  9316.           You either retrieve the supplied frame object (as when embedding 
  9317.            pasted content that comes with a display frame) or create a new 
  9318.            frame object (as when adding a new frame to an existing embedded 
  9319.            part or creating a new part from a palette). You store a reference 
  9320.            to the frame somewhere in your part's content. The frame object 
  9321.            itself is stored in your part's draft, but not in your part. 
  9322.  
  9323.    3. If the embedded part's frame is presently visible, you create a new facet 
  9324.       (or facets) to display the embedded part. 
  9325.  
  9326.    4. As necessary or appropriate, you perform other tasks related to 
  9327.       embedding, such as those described in the rest of this section. Finally, 
  9328.       you notify OpenDoc and your own containing part that you have changed 
  9329.       your part's content. 
  9330.  
  9331.  When one of your embedded parts is removed, your part is responsible for 
  9332.  releasing the embedded frame, removing all the facets of that frame, and 
  9333.  redisplaying its own content. 
  9334.  
  9335.  
  9336. ΓòÉΓòÉΓòÉ 9.3.2. Removing an Embedded Part ΓòÉΓòÉΓòÉ
  9337.  
  9338. To remove an embedded part from your part, follow the instructions for removing 
  9339. its frame, described in Removing an Embedded Frame. 
  9340.  
  9341. This illustrates the fact that your part is not actually concerned with 
  9342. removing embedded parts themselves. Under user instruction or for other 
  9343. reasons, your part may have reason to remove one or more embedded frames; once 
  9344. the last display frame of a given embedded part is removed from your part, that 
  9345. part is no longer embedded in your part. 
  9346.  
  9347.  
  9348. ΓòÉΓòÉΓòÉ 9.3.3. Making Content Changes Known ΓòÉΓòÉΓòÉ
  9349.  
  9350. Whenever you make any significant change to your part's content, whether it 
  9351. involves adding, deleting, moving, or otherwise modifying your intrinsic 
  9352. content or your embedded frames, you must make those changes known to OpenDoc 
  9353. and to all containing parts of your part. 
  9354.  
  9355.      Call the ContentUpdated method of each of your part's display frames in 
  9356.       which the change occurred, passing it an identifying update ID obtained 
  9357.       from the session object's UniqueChangeID method (or propagated from a 
  9358.       link source, as described in Link Update ID, or from 
  9359.       EmbeddedFrameUpdated, described in The EmbeddedFrameUpdated Method of 
  9360.       your Part Editor This call notifies your containing parts (and their 
  9361.       containing parts, and so on) that your content has changed. The 
  9362.       notification is necessary to enable all containing parts to update any 
  9363.       link sources that they maintain. 
  9364.  
  9365.      Call your draft's SetChangedFromPrev method. This marks the draft as 
  9366.       dirty, giving your part the opportunity to write itself to storage when 
  9367.       the draft is closed. 
  9368.  
  9369.  You should call these methods as soon as is appropriate after making any 
  9370.  content changes. You may not have to make the calls immediately after every 
  9371.  single change; it may be more efficient to wait for a pause in user input, for 
  9372.  example, or until the active frame changes. In addition to sending these 
  9373.  notifications, you must of course also update your part's display if 
  9374.  appropriate; this may involve adding or removing facets, adjusting intrinsic 
  9375.  content, and invalidating areas that need to be redrawn. 
  9376.  
  9377.  
  9378. ΓòÉΓòÉΓòÉ 9.4. Closing your Part ΓòÉΓòÉΓòÉ
  9379.  
  9380. When the user closes the document containing your part, or when your part is 
  9381. deleted from its containing part, OpenDoc calls your part's ReleaseAll method, 
  9382. followed by its somUninit method. 
  9383.  
  9384.  
  9385. ΓòÉΓòÉΓòÉ 9.4.1. The ReleaseAll Method ΓòÉΓòÉΓòÉ
  9386.  
  9387. The ReleaseAll method is inherited from ODPersistentObject. Its purpose is to 
  9388. ensure that all your part's references to other objects and ownership of shared 
  9389. resources are relinquished before your part is itself deleted from memory. Your 
  9390. override of the ReleaseAll method should perform at least these tasks: 
  9391.  
  9392.      It should call the Release methods of all reference-counted objects it 
  9393.       has references to, including iterating through its private lists of 
  9394.       embedded frames and display frames and releasing each one. 
  9395.  
  9396.      It should call the BaseRemoved method of any of its own extensions. 
  9397.  
  9398.      It should remove any link specifications it has written to the Clipboard. 
  9399.  
  9400.      It should fulfill any promises it has written to the clipboard. 
  9401.  
  9402.      It should relinquish all foci that it owns. 
  9403.  
  9404.      It should clear the undo stack if it has written any undo actions to it. 
  9405.  
  9406.      It should call the PartRemoved method of any embedded-frames iterators it 
  9407.       has created. 
  9408.  
  9409.  Your part should not write itself to storage from within its ReleaseAll 
  9410.  method. Your part's Release method, inherited from ODRefCntObject, is called 
  9411.  under different circumstances from ReleaseAll. For information on implementing 
  9412.  a Release method, see Reference-Counted Objects. 
  9413.  
  9414.  
  9415. ΓòÉΓòÉΓòÉ 9.4.2. The somUninit Method ΓòÉΓòÉΓòÉ
  9416.  
  9417. After it completes ReleaseAll, your part receives no subsequent method calls 
  9418. except to its SOM object destructor somUninit. The somUninit method is 
  9419. inherited from the somObject class of SOM; when you subclass ODPart, you must 
  9420. override somUninit. 
  9421.  
  9422. Your somUninit method should dispose of any storage created for your part 
  9423. object by the somInit method and any other storage related to additional 
  9424. instance variables of your part initialized during execution. Do not perform 
  9425. any tasks in this method that could fail. 
  9426.  
  9427.  
  9428. ΓòÉΓòÉΓòÉ 10. Data Transfer ΓòÉΓòÉΓòÉ
  9429.  
  9430. This is the sixth of eight chapters that discuss the OpenDoc programming 
  9431. interface in detail. It describes how OpenDoc provides support for 
  9432. data-transfer operations. 
  9433.  
  9434. Before reading this chapter, you should be familiar with the concepts presented 
  9435. in Introduction and Development Overview. You should also be familiar with 
  9436. OpenDoc storage concepts, as presented in the previous chapter. For additional 
  9437. concepts related to your part editor's run-time environment, see OpenDoc 
  9438. Run-Time Features. 
  9439.  
  9440. This chapter describes general issues common to all data-transfer methods, and 
  9441. then describes how your part can support 
  9442.  
  9443.      Clipboard data transfer 
  9444.  
  9445.      Drag and drop data transfer 
  9446.  
  9447.      Linking 
  9448.  
  9449.  
  9450. ΓòÉΓòÉΓòÉ 10.1. Storage Issues for Data Transfer ΓòÉΓòÉΓòÉ
  9451.  
  9452. This section introduces some of the storage-related concepts used in clipboard 
  9453. transfer, drag and drop, and linking, which are described in detail later in 
  9454. this chapter. 
  9455.  
  9456. For the purposes of this section, the term data-transfer object means any of 
  9457. the following: the clipboard or drag and drop object (when reading or writing 
  9458. data), a link-source object (when writing linked data), or a link object (when 
  9459. reading linked data). 
  9460.  
  9461.  
  9462. ΓòÉΓòÉΓòÉ 10.1.1. Data Configuration ΓòÉΓòÉΓòÉ
  9463.  
  9464. When a part places data on the clipboard or other data-transfer object, the 
  9465. part writes a portion or all of its intrinsic content, and the part can also 
  9466. cause the contents of one or more embedded parts to be written. 
  9467.  
  9468. Whatever the nature of the data, it can be considered an independent part once 
  9469. it is written to the data-transfer object. The transferred part has its own 
  9470. intrinsic content and it may contain embedded parts. In writing or reading the 
  9471. data, your part is directly concerned only with the characteristics (such as 
  9472. part kind) of the intrinsic content of the transferred part. Any embedded parts 
  9473. are transferred unchanged-as imbedded parts-during the process. 
  9474.  
  9475. The storage unit for the data-transfer object's intrinsic content is called its 
  9476. content storage unit. It is the main storage unit for the content of the 
  9477. data-transfer object, equivalent to a part's main storage unit (see Main and 
  9478. Auxiliary Storage Units). Any embedded parts in the transferred data, and any 
  9479. other OpenDoc objects, have their own storage units. 
  9480.  
  9481. Note:  A link object or a link-source object is a persistent object, and as 
  9482.        such has its own main storage unit. That storage unit is not the same as 
  9483.        its content storage unit. Always access the content of a data-transfer 
  9484.        object by calling its GetContentStorageUnit method. 
  9485.  
  9486.  The intrinsic content is stored, as expected for any part, in the contents 
  9487.  property (type kODPropContents) of the content storage unit. When writing to a 
  9488.  data-transfer object, your part can store data in multiple formats in 
  9489.  different values of the contents property. Just as with a part, each value in 
  9490.  the contents property must be complete; it must not depend on other properties 
  9491.  or other values of the property. 
  9492.  
  9493.  The contents property is not the only property you access in writing to or 
  9494.  reading from a data-transfer object. When your part writes all or part of its 
  9495.  intrinsic data to a data-transfer object, it does not write a display frame 
  9496.  for the data, but it does write a suggested frame shape for the destination 
  9497.  part to use as a guide when constructing a display frame. Likewise, if your 
  9498.  part places a single embedded frame in a data-transfer object, it also writes 
  9499.  the frame object into a property of the content storage unit. See Annotations 
  9500.  for more information. 
  9501.  
  9502.  In-memory objects take precedence over their stored versions in data transfer. 
  9503.  If the user cuts or copies a part's frame to the clipboard or other 
  9504.  data-transfer object, the moved data represents the current state of the part, 
  9505.  including any edits that have not yet been saved to disk. 
  9506.  
  9507.  
  9508. ΓòÉΓòÉΓòÉ 10.1.2. Annotations ΓòÉΓòÉΓòÉ
  9509.  
  9510. This section discusses the items, in addition to part content, that you can 
  9511. write to or read from the storage unit of a data-transfer object. 
  9512.  
  9513.  
  9514. ΓòÉΓòÉΓòÉ 10.1.2.1. Link Specification ΓòÉΓòÉΓòÉ
  9515.  
  9516. A part copying content to the clipboard or drag and drop object advertises the 
  9517. ability to create a link by writing a link specification in addition to 
  9518. content. When you copy data to the clipboard or drag and drop object, you 
  9519. should create a link specification-using your draft's CreateLinkSpec method-in 
  9520. case the user chooses to link to the data when pasting or dropping it in the 
  9521. destination. Writing Intrinsic Content. illustrate when to write a link 
  9522. specification. 
  9523.  
  9524. Write the link specification onto the content storage unit of the clipboard or 
  9525. drag and drop object as a property with the name kODPropLinkSpec. The data in a 
  9526. link specification is private to the part writing it. The data you place in 
  9527. your link specification is returned to your part if and when its CreateLink 
  9528. method is called to create the link. All that your part needs from the link 
  9529. specification data is sufficient information to identify the selected content. 
  9530.  
  9531. Because the link specification is valid only for the duration of the current 
  9532. instantiation of your part, the link specification can contain pointers to 
  9533. information that you maintain. 
  9534.  
  9535. Link specifications are not necessary in the following situations: 
  9536.  
  9537.      Do not write a link specification when you place content on the clipboard 
  9538.       as a result of a cut operation; you cannot link data that is no longer in 
  9539.       your part. (Because you cannot know at the start whether a drag will be a 
  9540.       move or a copy, you should always write a link specification when you 
  9541.       write data to the drag and drop object.) 
  9542.  
  9543.      Do not write a link specification when you write all or a portion of a 
  9544.       link destination (or any of your part's content, if your part itself is 
  9545.       in a link destination) to the clipboard or drag and drop object; that 
  9546.       could make your link destination a source of another link, which is 
  9547.       technically possible but generally a bad practice. (see the second table 
  9548.       in Creating a Link that Includes Already-Linked Content for an 
  9549.       explanation). 
  9550.  
  9551.      Do not write a link specification when your draft permissions (see 
  9552.       Drafts) are read-only. You would not be able to establish links to other 
  9553.       parts of the same (read-only) document, and any links to other documents 
  9554.       would be broken when your draft closed. 
  9555.  
  9556.      Do not write a link specification into a link-source object. Link 
  9557.       specifications are for the clipboard or drag and drop object only. Link 
  9558.       specifications are transitory, whereas links are persistent. 
  9559.  
  9560.  When you write a link specification to the clipboard, obtain and save the 
  9561.  clipboard update ID (see Clipboard Update ID). You must remove a link 
  9562.  specification from the clipboard if your source data changes so that the 
  9563.  clipboard data no longer reflects it, and you need the update ID to do that. 
  9564.  See Removing a Link Specification from the Clipboard. 
  9565.  
  9566.  (You never need to remove a link specification from the drag and drop object, 
  9567.  because it is valid only during the course of a single drag operation.) 
  9568.  
  9569.  Note:  The kODPropLinkSpec property is not copied when the storage unit 
  9570.         containing it is cloned. 
  9571.  
  9572.  
  9573. ΓòÉΓòÉΓòÉ 10.1.2.2. Frame Shape or Frame Annotation ΓòÉΓòÉΓòÉ
  9574.  
  9575. When you place intrinsic content (with or without embedded frames) on the 
  9576. clipboard or other data-transfer object, there is no frame associated with that 
  9577. content. You should, nevertheless, write a frame shape to the data-transfer 
  9578. object to accompany the content; the shape is a suggestion to any part that 
  9579. reads the data and must embed it as a separate part. You write the frame shape 
  9580. into a property named kODPropSuggestedFrameShape in the data-transfer object's 
  9581. content storage unit. 
  9582.  
  9583. Likewise, if your part is receiving a paste or drop and copies intrinsic data 
  9584. from the data-transfer object that it must embed, you should examine the 
  9585. kODPropSuggestedFrameShape property to get the source part's suggested frame 
  9586. shape for the data. If the kODPropFrameShape property does not exist, use your 
  9587. own part-specific default shape. 
  9588.  
  9589. If you place a part (in the form of a single embedded frame) on the clipboard 
  9590. or other data-transfer object, you must place the frame object there also. You 
  9591. write the frame into a property with the name kODPropContentFrame in a storage 
  9592. unit of the data-transfer object's draft. 
  9593.  
  9594. Likewise, if your part is receiving a paste or drop and copies the single 
  9595. embedded part, you can note from the presence of the kODPropContentFrame 
  9596. property that the data represents a single frame that should be embedded, and 
  9597. you can retrieve the frame from the property. 
  9598.  
  9599. When you transfer a single embedded frame, you can specify the frame location 
  9600. relative to your part's content (that is, the offset specified in the external 
  9601. transform of the frame's facet) by incorporating the offset into the frame 
  9602. shape that you write. Then, the receiving part of the paste or drop can, if 
  9603. appropriate to its content model, use that offset to construct an external 
  9604. transform. 
  9605.  
  9606. Note:  The kODPropSuggestedFrameShape and kODPropContentFrame properties are 
  9607.        not copied when the storage unit containing it is cloned. 
  9608.  
  9609.  
  9610. ΓòÉΓòÉΓòÉ 10.1.2.3. Proxy Content ΓòÉΓòÉΓòÉ
  9611.  
  9612. When you write a single embedded frame to a data-transfer object, you can 
  9613. optionally write any intrinsic data that you want to be associated with the 
  9614. frame. The intrinsic data might be a drop shadow or other visual adornment for 
  9615. the frame, or it might be information needed to reconstruct the frame as a link 
  9616. source or link destination. 
  9617.  
  9618. This information is called proxy content; to write it, you add a the 
  9619. kODPropProxyContents property to the data-transfer object, and write your data 
  9620. into it as a value that your part recognizes. If the transferred part is 
  9621. subsequently embedded into a part that also recognizes that value and knows how 
  9622. to interpret it, the added frame characteristics can be duplicated. 
  9623.  
  9624. Likewise, if your part is the receiving part of a paste or drop and copies the 
  9625. single embedded part, you can note from the presence of the 
  9626. kODPropProxyContents property that proxy content for that frame exists. If your 
  9627. part understands the format of the proxy content-which you should be able to 
  9628. determine by examining the value types in the property-you can read it and 
  9629. duplicate the frame characteristics. 
  9630.  
  9631. Note:  The kODPropProxyContents property is not copied when the storage unit 
  9632.        containing it is cloned. 
  9633.  
  9634.  
  9635. ΓòÉΓòÉΓòÉ 10.1.2.4. Part Name or Category Annotation ΓòÉΓòÉΓòÉ
  9636.  
  9637. Whenever you write any of your part's intrinsic content to the clipboard or 
  9638. other data-transfer object, write also a name for the data. The name should be 
  9639. the name of your part or-if your part has no name-its part category. Write the 
  9640. name into a property with the name kODPropName in the data-transfer object's 
  9641. storage unit. A name property is user-visible text, so you should write it in 
  9642. international-text format, as described in User Strings. 
  9643.  
  9644.  
  9645. ΓòÉΓòÉΓòÉ 10.1.2.5. Mouse-Down Offset Annotation ΓòÉΓòÉΓòÉ
  9646.  
  9647. If your part initiates a drag operation (see Initiating a Drag), you need to 
  9648. create a property named kODPropMouseDownOffset in the drag and drop object's 
  9649. storage unit. Write into that property a value that specifies the location of 
  9650. the mouse-down event that triggered the drag. The value should be of type 
  9651. ODPoint and should contain the offset from the origin of the content being 
  9652. dragged. 
  9653.  
  9654. If your part receives a drop, it should likewise check for the presence of the 
  9655. kODPropMouseDownOffset property. If the property exists, and if taking it into 
  9656. account is consistent with your part's content model, use it to locate the 
  9657. dropped content in relation to the mouse-up event that marks the drop. 
  9658.  
  9659. Note:  The kODPropMouseDownOffset property is not copied when the storage unit 
  9660.        containing it is cloned. 
  9661.  
  9662.  
  9663. ΓòÉΓòÉΓòÉ 10.1.2.6. Drag and Drop Annotations (OS/2) ΓòÉΓòÉΓòÉ
  9664.  
  9665. Each content storage unit of the drag and drop object contains a PM DRAGITEM 
  9666. structure corresponding to a drag item in the current drag and drop operation. 
  9667. It is written by the drag and drop object under the kODDragitem value of the 
  9668. kODPropContents property. Usually parts don't have to interact with this value 
  9669. other than in their Drop method, when they have to create a storage unit view 
  9670. for it and pass it to the GetDataFromDragManager method of the drag and drop 
  9671. object to perform data rendering. 
  9672.  
  9673. The drag and drop object supports data rendering for two mechanisms: 
  9674. DRM_SHAREDMEM and DRM_OS2FILE. If either one of these mechanisms has been 
  9675. selected (RMF selection is done by calling drag and drop CanEmbed or 
  9676. CanIncorporate methods from within the part's DragEnter method), the storage 
  9677. unit rendered by GetDataFromDragManager will contain the rendered data with no 
  9678. kODDragitem value. If the selected rendering mechanism is DRM_OS2FILE and this 
  9679. is not an OPENDOC initiated drag, the rendered storage unit will contain the 
  9680. following values for its kODPropContents property: 
  9681.  
  9682.  Selected kind         Part kind that the selected RMF was mapped to; no value 
  9683.                        is set for this kind. The actual data has to be read 
  9684.                        from the dropped file. 
  9685.  
  9686.  kODFileType           Name of the dropped file; value type is ODISOStr. 
  9687.  
  9688.  kODFileTypeEA         Any extended attributes that are associated with the 
  9689.                        file; value type is ODISOStr. 
  9690.  
  9691.  If the selected rendering mechanism is not handled by the drag and drop 
  9692.  object, the target part has to perform the data rendering. In this case, the 
  9693.  kODPropContents in the storage unit rendered by GetDataFromDragManager will 
  9694.  contain a set of values necessary for the part to carry out the rendering 
  9695.  conversation: 
  9696.  
  9697.  kODDragitem           DRAGITEM structure; value type is DRAGITEM. 
  9698.  
  9699.  kODSelectedRMF        Selected rendering mechanism and format pair; value type 
  9700.                        is ODISOStr. 
  9701.  
  9702.  kODSelectedKind       Part kind that the selected RMF was mapped to; value 
  9703.                        type is ODISOStr. 
  9704.  
  9705.  kODDragOperation      PM drag operation from the DRAGINFO structure associated 
  9706.                        with this drag; value type is ODUShort. 
  9707.  
  9708.  
  9709. ΓòÉΓòÉΓòÉ 10.1.2.7. Clonable Data Annotation Prefix ΓòÉΓòÉΓòÉ
  9710.  
  9711. When objects are cloned (see Cloning), the in-memory version of an object is 
  9712. given preference over its storage unit, so that recent, unsaved changes to the 
  9713. object are included in the cloning operation. This means, however, that any of 
  9714. its properties that the object itself is unaware of are not cloned, because it 
  9715. does not write them into the destination storage unit. 
  9716.  
  9717. There are situations in which an object can store properties in the storage 
  9718. unit of a part, without the knowledge or cooperation of the part itself. For 
  9719. example, a service such as a spell checker might store a dictionary of 
  9720. exceptions as a property of a part's storage unit. The part is unaware of the 
  9721. existence of that property, but the spell checker would want the dictionary 
  9722. cloned whenever the part is cloned. 
  9723.  
  9724. To support this capability, OpenDoc defines the property prefix constant 
  9725. kODPropPreAnnotation, whose value is OpenDoc:Annotation:. When that prefix is 
  9726. part of a property name (for example, OpenDoc:Annotation:Exceptions) in an 
  9727. object's storage unit, OpenDoc always copies that property when the object is 
  9728. cloned, regardless of whether the object being cloned is aware of the existence 
  9729. of the property. Therefore, if your part stores data in another object that the 
  9730. object itself does not use but that you want to be cloned along with the 
  9731. object, make sure you store it in a property whose name starts with 
  9732. OpenDoc:Annotation:. 
  9733.  
  9734.  
  9735. ΓòÉΓòÉΓòÉ 10.1.3. Cloning ΓòÉΓòÉΓòÉ
  9736.  
  9737. You should always transfer data to and from the clipboard or other 
  9738. data-transfer object in the context of cloning. This section describes how 
  9739. cloning works, what the scope of a cloning operation is, and how to implement 
  9740. your part editor's CloneInto method. 
  9741.  
  9742. To clone an object is to copy the object itself as well as all objects that it 
  9743. references, plus any objects that those objects reference, and so on. 
  9744. Typically, copies are made of all storage units-or their equivalent, 
  9745. instantiated persistent objects-that are referenced with strong persistent 
  9746. references, starting with the object being cloned. Storage units referenced 
  9747. only with weak persistent references are not copied. For more information on 
  9748. how strong and weak persistent references affect cloning, see Persistent 
  9749. References and the figure in section Persistent References and Cloning. 
  9750.  
  9751. Actually, each object that is cloned during the operation decides-if it is in 
  9752. memory at the time-which of its own storage-unit's properties and which of its 
  9753. referenced objects should be included. If the object is not currently 
  9754. instantiated, all of its storage unit's properties and all of its strongly 
  9755. referenced objects are copied. 
  9756.  
  9757.  
  9758. ΓòÉΓòÉΓòÉ 10.1.3.1. Cloning Process ΓòÉΓòÉΓòÉ
  9759.  
  9760. All persistent objects have a CloneInto method by which they clone themselves, 
  9761. but your part editor should not call the CloneInto method of any object 
  9762. directly. Instead, you clone an object by calling the Clone (or WeakClone) 
  9763. method of its draft object. The Clone method in turn calls the CloneInto method 
  9764. of the object involved. 
  9765.  
  9766. Cloning is a multistep transaction, designed so that it can be terminated 
  9767. cleanly if it fails at any point. You perform a clone by calling three methods, 
  9768. in this order: 
  9769.  
  9770.    1. Call the BeginClone method of the draft object of the data to be cloned. 
  9771.       If you are transferring data from your part, call your part's draft 
  9772.       object; if you are transferring data from a data-transfer object, call 
  9773.       that object's draft object. BeginClone sets up the cloning transaction. 
  9774.       (If you are cloning as a result of pasting or dropping data into your 
  9775.       part, you must also specify the destination frame, the display frame of 
  9776.       your part that is receiving the paste or drop.) 
  9777.  
  9778.    2. For each object that you are cloning, call the draft's Clone method. 
  9779.       Clone allows the draft object to specify and recursively locate all 
  9780.       objects that are to be cloned. It calls the CloneInto method of the 
  9781.       object to be copied, which results in calls to the CloneInto methods of 
  9782.       all referenced objects, and so on. For example, when Clone calls the 
  9783.       CloneInto method of a part, the part clones its embedded frames; the 
  9784.       embedded frames, in turn, clone the parts they display, and so on. 
  9785.  
  9786.       (When you are cloning within the context of your own CloneInto method, 
  9787.       you sometimes call the draft's WeakClone method instead of Clone. See 
  9788.       CloneInto Method of your Part Editor for more information.) When you call 
  9789.       Clone, it is important to make sure that the object you are cloning is 
  9790.       valid. Take these steps: 
  9791.  
  9792.         a. Starting with the persistent reference that specifies the object to 
  9793.            be cloned, first call the IsValidStorageUnitRef method of the 
  9794.            storage unit or storage unit view that contains the persistent 
  9795.            reference. You can never automatically assume that a persistent 
  9796.            reference is valid. 
  9797.  
  9798.         b. Get the object's ID (See Storage-Unit IDs) from the persistent 
  9799.            reference by calling the GetIDFromStorageUnitRef method of the 
  9800.            storage unit. 
  9801.  
  9802.         c. Pass the object ID to the Clone method. 
  9803.  
  9804.         d. Save the resultant object ID that Clone returns, along with the IDs 
  9805.            returned from other calls to Clone, until cloning is complete and 
  9806.            you have called EndClone. 
  9807.  
  9808.       If you are not actually cloning objects but simply reading or writing 
  9809.       intrinsic data, this is the point at which to do that (instead of calling 
  9810.       Clone). 
  9811.  
  9812.    3. Call the draft's EndClone method. EndClone commits to and actually 
  9813.       performs the cloning operation. 
  9814.  
  9815.       If, at any time after calling BeginClone, the operation cannot be 
  9816.       completed, you can terminate the transaction by calling the AbortClone 
  9817.       method instead of EndClone. 
  9818.  
  9819.  Note:  You cannot instantiate and use any cloned object until after the entire 
  9820.         cloning operation is complete. If you are cloning several parts and 
  9821.         link objects, for example, you cannot call AcquirePart or AcquireLink 
  9822.         until after you have cloned all of the objects and EndClone has 
  9823.         successfully returned. 
  9824.  
  9825.  When you call BeginClone, you are returned a draft key, a number that 
  9826.  identifies that specific cloning transaction. You pass that key to the other 
  9827.  cloning methods that you call during the transaction. You also specify in the 
  9828.  kind parameter to the BeginClone method the kind of cloning operation that is 
  9829.  to be performed, so that OpenDoc can maintain the proper behavior for linked 
  9830.  data that is being transferred. The following table lists the kinds of cloning 
  9831.  transactions that OpenDoc recognizes. Cloning explains how these different 
  9832.  types of transactions result in different behavior for links. The following 
  9833.  table lists the kinds of cloning operations recognized by OpenDoc. 
  9834.  
  9835.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9836.   Γöékind parameter                ΓöéMeaning                       Γöé
  9837.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9838.   ΓöékODCloneCopy                  ΓöéCopy object from source to    Γöé
  9839.   Γöé                              Γöédata-transfer object          Γöé
  9840.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9841.   ΓöékODCloneCut                   ΓöéCut object from source to     Γöé
  9842.   Γöé                              Γöédata-transfer object          Γöé
  9843.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9844.   ΓöékODClonePaste                 ΓöéPaste object from             Γöé
  9845.   Γöé                              Γöédata-transfer object to       Γöé
  9846.   Γöé                              Γöédestination                   Γöé
  9847.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9848.   ΓöékODCloneDropCopy              ΓöéCopy object to the destinationΓöé
  9849.   Γöé                              Γöéof a drop                     Γöé
  9850.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9851.   ΓöékODCloneDropMove              ΓöéMove object to the destinationΓöé
  9852.   Γöé                              Γöéof a drop                     Γöé
  9853.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9854.   ΓöékODCloneToLink                ΓöéCopy object from source to    Γöé
  9855.   Γöé                              Γöéupdate a link source          Γöé
  9856.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9857.   ΓöékODCloneFromLink              ΓöéCopy object from link to      Γöé
  9858.   Γöé                              Γöéupdate a destination          Γöé
  9859.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9860.   ΓöékODCloneAll                   ΓöéClone all objects (your part  Γöé
  9861.   Γöé                              Γöéshould not use this)          Γöé
  9862.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9863.  
  9864.  Even when transferring only intrinsic content (and not actually cloning any 
  9865.  objects), you should still bracket your transfer with calls to BeginClone and 
  9866.  EndClone. That way, you notify OpenDoc of the kind of operation (such as cut 
  9867.  or copy) that is being performed and you ensure that the right actions occur 
  9868.  at both the source and destination of the transfer. 
  9869.  
  9870.  In cloning, the in-memory version of an object takes precedence over its 
  9871.  stored version. For this reason, an object does not need to be written to 
  9872.  storage prior to being cloned.  If the object is in memory, its CloneInto 
  9873.  method is called to perform the clone; if the object is not in memory, its 
  9874.  storage unit performs the clone. This also means, however, that, if an object 
  9875.  is in memory, properties attached to its storage unit that the object itself 
  9876.  does not know about might not be copied, unless they are specially named; see 
  9877.  Clonable Data Annotation Prefix for an explanation. 
  9878.  
  9879.  Note that your parts, as persistent objects, must provide a CloneInto method. 
  9880.  See CloneInto Method of your Part Editor for more information. 
  9881.  
  9882.  Null IDs when cloning links 
  9883.  The Clone method returns a value of kODNullID if the desired object cannot be 
  9884.  cloned. For example, if you attempt to clone a link object or link-source 
  9885.  object into a link, Clone does not permit it and returns kODNullID. In such an 
  9886.  instance, you cannot clone the object so you should delete any data associated 
  9887.  with it that you have written into the data-transfer object. However, in the 
  9888.  case of a link or link source you should still write the content formerly 
  9889.  associated with the object, but as unlinked content. 
  9890.  
  9891.  Annotation properties not cloned 
  9892.  When data is cloned from a data-transfer object, most of the annotation 
  9893.  properties that the source part may have added to the content storage unit are 
  9894.  not transferred, because they make no sense as properties outside of the 
  9895.  data-transfer object. Specifically, the properties kODPropLinkSpec, 
  9896.  kODPropSuggestedFrameShape, kODPropContentFrame, kODPropProxyContents, and 
  9897.  kODPropMouseDownOffset are never copied during a clone. 
  9898.  
  9899.  
  9900. ΓòÉΓòÉΓòÉ 10.1.3.2. Scope of a Clone Operation ΓòÉΓòÉΓòÉ
  9901.  
  9902. For cloning, the scope defines the set of objects that are to be included in 
  9903. the cloning operation. Scope is expressed in terms of a frame object or its 
  9904. storage unit. 
  9905.  
  9906. Because a part can have more than one display frame, and because each frame can 
  9907. include a separate set of embedded frames and parts, it is important to specify 
  9908. the frame whose enclosed objects are to be cloned. Otherwise, extra embedded 
  9909. parts or other objects not needed by the copy may be included unnecessarily.. 
  9910.  
  9911. In the example shown in the following figure, the user has selected some 
  9912. content in the root part that includes display frame 1 of embedded part A. The 
  9913. root part writes its intrinsic content and then clones part A, passing it a 
  9914. scope of frame A1. Any content that belongs only to frame A2 (such as part C) 
  9915. is not included in the clone. 
  9916.  
  9917. Scope changes during the course of a clone. Continuing the same example as that 
  9918. shown in the previous figure, the next figure shows how part A clones itself in 
  9919. the context of the scope (frame A1) specified by the root part. Part A writes 
  9920. the intrinsic content of its display frame A1 and then clones part B twice, 
  9921. first passing it a scope of frame B1 and then a scope of frame B2. Part B thus 
  9922. gets called to clone itself twice, with different scopes. Any content of B 
  9923. within frames B1 and B2 is included, but any content that belongs only to frame 
  9924. B3 is not. 
  9925.  
  9926. You can specify null for the scope of a clone if you want all objects copied, 
  9927. regardless of what display frame they are associated with. 
  9928.  
  9929.  
  9930. ΓòÉΓòÉΓòÉ 10.1.3.3. CloneInto Method of your Part Editor ΓòÉΓòÉΓòÉ
  9931.  
  9932. If your part is an embedded part that is written to the clipboard (or other 
  9933. data-transfer object), your part's override of its inherited CloneInto method 
  9934. is called by your draft's Clone method. This is the interface to CloneInto: 
  9935.  
  9936. void CloneInto(in ODDraftKey key,
  9937.                 in ODStorageUnit toSU,
  9938.                 in ODFrame scope);
  9939.  
  9940. Your CloneInto method is passed a draft key for the clone operation and a frame 
  9941. that defines the scope of the cloning. The method should write your part's 
  9942. intrinsic content to the provided storage unit, and it should clone in turn any 
  9943. objects (such as embedded frames or auxiliary storage units) that it 
  9944. references. It needn't clone any objects or write any data that is outside of 
  9945. the scope. 
  9946.  
  9947. Note:  Do not implement your CloneInto method by writing your part to storage 
  9948.        and then cloning your storage unit. Such a method would have performance 
  9949.        penalties because of the extra time needed to store your data, and might 
  9950.        copy unneeded objects because the scope of the clone would be ignored. 
  9951.  
  9952.  To support efficient data transfer, your part should, if possible, write a 
  9953.  promise (see next section) instead of writing its actual intrinsic data when 
  9954.  CloneInto is called. It is possible to write a promise only when your part is 
  9955.  placed into the data-transfer object as a single, standalone frame with no 
  9956.  surrounding intrinsic content of its containing part. In any other situation, 
  9957.  your CloneInto method might have been called to help fulfill a promise, in 
  9958.  which case writing a promise would be inappropriate. You can determine whether 
  9959.  you can write a promise by examining the provided storage unit. If it contains 
  9960.  a property with the name kODPropContentFrame, your part is the sole content of 
  9961.  the storage unit's contents property, and you can write a promise instead of 
  9962.  actual data. 
  9963.  
  9964.  When you write a promise, be sure to identify (to yourself) the display frame 
  9965.  or frames of your part that are within the scope of the clone operation, so 
  9966.  that your FulfillPromise method can write the proper content when it is 
  9967.  called. 
  9968.  
  9969.  Take these general steps in your CloneInto method: 
  9970.  
  9971.    1. Check to see if your part has already been cloned in this operation. 
  9972.       Because an object can be referenced more than once, its CloneInto method 
  9973.       can be called more than once in a single cloning. In general, if a 
  9974.       contents property already exists in the storage unit passed in the 
  9975.       method, your part has already been cloned and there is no need to repeat 
  9976.       the process. 
  9977.  
  9978.       An exception to this rule occurs when scope is significant. If your part 
  9979.       is called to clone itself with different scopes during the same operation 
  9980.       (see, for example, the previous figure), it may have to write additional 
  9981.       data each time its CloneInto method is called. 
  9982.  
  9983.    2. Call your inherited CloneInto method. 
  9984.  
  9985.    3. If it does not already exist, add a property named kODPropContents to the 
  9986.       provided storage unit. (You do not have to call BeginClone; that method 
  9987.       will already have been called. Also, you do not have to add properties 
  9988.       other than the contents property; OpenDoc will add your part's name and 
  9989.       any other needed annotations.) 
  9990.  
  9991.    4. Check to see if you can write a promise. Look for a property with the 
  9992.       name kODPropContentFrame in the storage unit. Don't look for a value in 
  9993.       the property; it may be written later. 
  9994.  
  9995.    5. Focus on the contents property, and write a value for each part kind you 
  9996.       support. Either write a promise or the data of your part itself, using 
  9997.       either the storage unit's SetPromiseValue or SetValue method, 
  9998.       respectively. 
  9999.  
  10000.       (For data transfer, it is especially important to write a standard format 
  10001.       in addition to your own native part kind, because the ultimate 
  10002.       destination of the transferred data is unknown.) 
  10003.  
  10004.    6. Clone all objects that your part references (that are within the scope of 
  10005.       the cloning operation) as follows: 
  10006.  
  10007.           For each object to which your part has a strong persistent 
  10008.            reference, call your draft's Clone method to clone the object, 
  10009.            passing the same draft key that was passed to your CloneInto method. 
  10010.            Pass a new scope, if appropriate; for example, if you are cloning an 
  10011.            embedded part, its frame is the new scope. 
  10012.  
  10013.           For each object to which your part has a weak persistent reference, 
  10014.            call your draft's WeakClone method, passing the appropriate draft 
  10015.            key and scope. 
  10016.  
  10017.            (Calling WeakClone does not by itself cause an object to be copied; 
  10018.            it only ensures that, if the object ends up being copied because of 
  10019.            an existing strong persistent reference to it, your part's weak 
  10020.            persistent reference will be maintained across the cloning 
  10021.            operation.) 
  10022.  
  10023.  
  10024. ΓòÉΓòÉΓòÉ 10.1.3.4. ClonePartInfo Method of your Part Editor ΓòÉΓòÉΓòÉ
  10025.  
  10026. Whenever your part's display frame is cloned during data transfer, the frame 
  10027. calls your part's ClonePartInfo method: 
  10028.  
  10029. void ClonePartInfo(in ODDraftKey key,
  10030.                            in ODType partInfo,
  10031.                            in ODStorageUnitView,
  10032.                            in ODFrame scope);
  10033.  
  10034. You should respond to this method call by writing your part info into the 
  10035. provided storage unit view (regardless of the state of your part-info dirty 
  10036. flag), and cloning any objects referenced in your part info data. 
  10037.  
  10038.  
  10039. ΓòÉΓòÉΓòÉ 10.1.4. Promises ΓòÉΓòÉΓòÉ
  10040.  
  10041. Clipboard transfer, drag and drop, and linking can make use of promises. A 
  10042. promise is a specification of data to be transferred at a future time. If a 
  10043. data transfer involves a very large amount of data, the source part can choose 
  10044. to write a promise instead of actually writing the data to a storage unit. When 
  10045. another part retrieves the data, the source part must then fulfill the promise 
  10046. it wrote. The destination part does not even know that a promise is being 
  10047. fulfilled; it simply accepts the data as usual. 
  10048.  
  10049. The format of a promise is completely determined by the source part. The only 
  10050. restriction is that the promise must be able to be written to a storage-unit 
  10051. value. 
  10052.  
  10053. You are encouraged to write promises in place of actual data in most cases; it 
  10054. minimizes memory requirements and increases performance. 
  10055.  
  10056.  
  10057. ΓòÉΓòÉΓòÉ 10.1.4.1. Writing a Promise ΓòÉΓòÉΓòÉ
  10058.  
  10059. Your part can follow these steps to write a promise when it is the source of a 
  10060. data transfer-that is, when it responds to a mouse-down event that initiates a 
  10061. drag or when it copies data to the clipboard: 
  10062.  
  10063.    1. Gain access to the storage unit of the data-transfer object. See 
  10064.       Initiating a Drag for drag and drop; see, for example, Writing Intrinsic 
  10065.       Content for clipboard transfer. Focus the storage unit to the contents 
  10066.       property (kODPropContents). 
  10067.  
  10068.    2. Prepare your promise. It can have any content and format you decide; you 
  10069.       must be able to read it later and reconstruct the exact data that is to 
  10070.       be transferred. 
  10071.  
  10072.    3. Write the promise into a single value of the storage unit, using the 
  10073.       storage unit's SetPromiseValue method. Your promise must include at least 
  10074.       this information: 
  10075.  
  10076.           A specification of the actual content that is to be delivered later. 
  10077.  
  10078.           A specification of the display frame or frames of your part involved 
  10079.            in the data transfer (if your part can have more than one display 
  10080.            frame). When you fulfill the promise, you can then supply the proper 
  10081.            scope for the cloning operation. 
  10082.  
  10083.           A specification of the proper kind of cloning transaction (such as 
  10084.            kODCloneCopy or kODCloneCut) to apply when you fulfill the promise. 
  10085.  
  10086.    4. Initiate the drag or complete the transfer of information to the 
  10087.       clipboard. You need not, at this stage, clone any frames or create a link 
  10088.       specification or read the update ID; you handle all those issues when you 
  10089.       fulfill the promise. You should, however, write a name and a suggested 
  10090.       frame shape if you are promising intrinsic content. 
  10091.  
  10092.  Each promise you write is for a single part kind. You can write several 
  10093.  promises representing data of several kinds, so that the destination part has 
  10094.  a better chance of being able to incorporate the data instead of embedding it. 
  10095.  (Because promises are private data, the actual content of all your promises 
  10096.  can be the same, regardless of the part kind being promised. When you are 
  10097.  called to fulfill the promise, you can inspect the provided storage-unit view 
  10098.  object to find out which part kind is needed.) 
  10099.  
  10100.  Because a promise is valid only for the duration of the current instantiation 
  10101.  of your part, the promise can contain pointers to information that you 
  10102.  maintain. 
  10103.  
  10104.  Note:  Never write a link specification into a promise. Promise data is 
  10105.         private and any link specification within it would never be seen by a 
  10106.         destination part. Likewise, never write a promise into a link 
  10107.         specification. Link specifications are described in Link Specification. 
  10108.  
  10109.  If your part is closing, your ReleaseAll method needs to fulfill any promises 
  10110.  that you have written but not yet fulfilled. See The ReleaseAll Method. 
  10111.  
  10112.  
  10113. ΓòÉΓòÉΓòÉ 10.1.4.2. Getting Data from a Value Containing a Promise ΓòÉΓòÉΓòÉ
  10114.  
  10115. When the Drop method of a destination part retrieves the data from a drop, or 
  10116. when a destination part reads data from the clipboard (using the GetValue or 
  10117. GetSize methods of the dragged data's or clipboard's storage unit), the source 
  10118. part is called to fulfill the promise. The destination part does not even know 
  10119. that a promise is being fulfilled; it follows the procedures described in 
  10120. Reading from a Data-Transfer Object and uses the same code whether the value 
  10121. contains a promise or not. 
  10122.  
  10123.  
  10124. ΓòÉΓòÉΓòÉ 10.1.4.3. Fulfilling a Promise ΓòÉΓòÉΓòÉ
  10125.  
  10126. OpenDoc calls your source part's FulfillPromise method when a promise must be 
  10127. fulfilled, passing it a storage-unit view object that contains the data of the 
  10128. promise. This is its interface: 
  10129.  
  10130. void FulfillPromise(in ODStorageUnitView promiseSUView);
  10131.  
  10132. In your implementation of the method, take steps similar to the following: 
  10133.  
  10134.    1. Using the private information that you wrote into the promise earlier, 
  10135.       retrieve the actual data that the promise represents. You can clone 
  10136.       frames and other objects as usual at this time. 
  10137.  
  10138.    2. Set up the actual data as a byte array, and write it into the 
  10139.       storage-unit view object. 
  10140.  
  10141.  When your FulfillPromise method completes, the destination part receives the 
  10142.  data. 
  10143.  
  10144.  When you fulfill a promise, you must be sure to supply the source content that 
  10145.  was selected at the time the promise was written, even if that content no 
  10146.  longer exists in your part. 
  10147.  
  10148.  If fulfilling your promise requires cloning, you must specify the scope and 
  10149.  the appropriate kind of cloning transaction. If you have saved that 
  10150.  information in the promise itself, extract it and pass it to your draft's 
  10151.  BeginClone and Clone methods, respectively. 
  10152.  
  10153.  There are times when you may have to fulfill a promise on your own, without a 
  10154.  call to your part's FulfillPromise method. For example, when your part closes, 
  10155.  your part's ReleaseAll method (see Closing your Part) must fulfill all 
  10156.  outstanding promises. To fulfill a promise in that manner, your part needs to 
  10157.  have kept a record of the promises (and their update IDs) that it has written. 
  10158.  Then, in ReleaseAll, it can: 
  10159.  
  10160.      Access the clipboard content storage unit and verify the clipboard update 
  10161.       ID against the part's stored update ID 
  10162.  
  10163.      Access each value that it has written and verify that it is a promise by 
  10164.       calling the storage unit's IsPromiseValue method 
  10165.  
  10166.      Extract the promise from the value, fulfill it, and write the fulfilled 
  10167.       data back into the value. 
  10168.  
  10169.  
  10170. ΓòÉΓòÉΓòÉ 10.1.5. Translation ΓòÉΓòÉΓòÉ
  10171.  
  10172. The OpenDoc translation object, implemented on each platform as a subclass of 
  10173. ODTranslation, is a wrapper for platform-specific translation services. OpenDoc 
  10174. and part editors can use the translation object to convert part data from one 
  10175. format (part kind) to another. 
  10176.  
  10177. Through the translation object, OpenDoc maintains information on what kinds of 
  10178. translations are available on the user's system. OpenDoc and part editors can 
  10179. then use the translation object to perform any requested translations, rather 
  10180. than directly calling the platform-specific translation service itself. 
  10181.  
  10182. In all cases, translation should occur only with explicit user approval and 
  10183. instruction. OpenDoc initiates translation in the situations described in 
  10184. Binding with Translation. Your part editor can initiate translation in the 
  10185. following situations: 
  10186.  
  10187.      When embedding or incorporating parts through clipboard paste or through 
  10188.       drag and drop, your part editor performs translation if the user 
  10189.       specifies-in the Paste As dialog box-a part kind that requires 
  10190.       translation. See Handling the Paste As Dialog Box for more information. 
  10191.  
  10192.      Your part editor performs translation when updating a link destination 
  10193.       for which the user specified translation in the Paste As dialog box when 
  10194.       originally creating the link. 
  10195.  
  10196.  The user specifies the specific translation to perform by selecting a new part 
  10197.  kind for the part in the kind pop-up menu of the Paste As dialog box. The kind 
  10198.  pop-up menu allows the user to select a part kind to translate to. 
  10199.  
  10200.  To set up the information in the pop-up menu, OpenDoc examines each part kind 
  10201.  in the part and determines from the translation object what new part kinds 
  10202.  (supported by available editors) the original part kind can be translated to. 
  10203.  OpenDoc then presents those choices to the user in the kind pop-up menu. 
  10204.  
  10205.  Once the user picks a translated part kind, your part editor calls the 
  10206.  translation object to perform the translation. Note that it is possible during 
  10207.  data transfer for the user to request translation to a part kind that your 
  10208.  part editor cannot read, meaning that you will perform the translation but 
  10209.  another editor will be bound to the data that you have translated. 
  10210.  
  10211.  The translation object allows only one-step translation; conversion can be 
  10212.  only from the existing part kind directly to the part kind selected by the 
  10213.  user. Note also that translation applies only to the outermost (intrinsic) 
  10214.  portion of the data; parts embedded within it are not translated. 
  10215.  
  10216.  For detailed procedures to follow in translating transferred data, see 
  10217.  Translating Before Incorporating or Embedding. 
  10218.  
  10219.  
  10220. ΓòÉΓòÉΓòÉ 10.1.6. Handling Cut Data ΓòÉΓòÉΓòÉ
  10221.  
  10222. If the user selects the Cut command to remove data from your part and place it 
  10223. on the clipboard, or if the user employs drag and drop to move (rather than 
  10224. copy) data from your part into another part, there are certain steps you should 
  10225. take to account for the fact that the data is still valid but is no longer in 
  10226. your part. Keep these points in mind: 
  10227.  
  10228.      Cutting must be an undoable action. If the data you cut from your part 
  10229.       includes references to objects such as embedded frames or link objects, 
  10230.       you should retain those references in an undo action (see Adding an 
  10231.       Action to the Undo History, but your part's content should release its 
  10232.       references to the objects. Once the objects are no longer needed for undo 
  10233.       support, OpenDoc calls your DisposeActionState method and you should 
  10234.       release them entirely. Do not, however, remove them from your draft; 
  10235.       other, valid references to them may remain. See also Undo for Clipboard 
  10236.       and Undo for Drag and Drop for related information. 
  10237.  
  10238.      Remove the facets of the cut frame. To access the facets of a frame that 
  10239.       has been drag-moved out of your part, don't use the moved frame's facet 
  10240.       iterator; the frame may have other facets in its new destination. Use the 
  10241.       embedded-facet iterator of your own display facet instead. 
  10242.  
  10243.      If you have more than one frame displaying an embedded part, remember 
  10244.       that removing the embedded part from one of your display frames does not 
  10245.       automatically remove it from the others. If the removed frame is 
  10246.       synchronized with embedded frames in your other display frames, for 
  10247.       example, you must remove those embedded frames also. 
  10248.  
  10249.      Do not create a link specification for the data you have cut; the data no 
  10250.       longer belongs to your part. 
  10251.  
  10252.      If the data you cut to the data-transfer object includes a link source, 
  10253.       you must call the SetSourcePart method of the link source object in your 
  10254.       own draft, passing it a null value, in order to relinquish your part's 
  10255.       ownership of the link source. Even if you write a promise instead of 
  10256.       actual data, call SetSourcePart at this time; don't wait until the 
  10257.       promise must be fulfilled. 
  10258.  
  10259.      When you cut an embedded frame to a data-transfer object, you must call 
  10260.       the SetContainingFrame method of the frame you have cut, setting its 
  10261.       containing frame to null and severing it from your part's embedding 
  10262.       hierarchy. You must also delete any facets displaying that frame. First 
  10263.       call the containing facet's RemoveFacet method and then delete the facet 
  10264.       object itself, as described in Removing a Facet. 
  10265.  
  10266.      If you write promises to the clipboard when cutting data from your part, 
  10267.       you can later fulfill that promise using either a kODCloneCut or 
  10268.       kODCloneCopy transaction, because the same promise may need to be 
  10269.       fulfilled during a paste immediately following the cut, or to subsequent 
  10270.       pastes that do not follow the cut. Therefore, you must take all 
  10271.       cut-specific actions at the time you write the promise (or, if the cut is 
  10272.       undone, when you handle the undo action.) 
  10273.  
  10274.      If you have cut data from your part and cloned it to the clipboard or 
  10275.       drag and drop object, OpenDoc may use the actual objects that were cut 
  10276.       from your part-not clones of them-when providing the data to be pasted or 
  10277.       dropped into a destination. Therefore, it is important to release, rather 
  10278.       than delete, objects (embedded frames, links, and so on) that you cut 
  10279.       from your part. Likewise, if you paste data into your part and then the 
  10280.       user selects Undo, make sure that you release rather than delete the 
  10281.       objects that you remove in the course of reversing the paste operation. 
  10282.  
  10283.       If the cut data includes a reference to a link-source object, your part 
  10284.       can retain that reference rather than releasing the object, but it should 
  10285.       not reassume ownership of the link source (through SetSourcePart) unless 
  10286.       and until the operation is undone. 
  10287.  
  10288.  
  10289. ΓòÉΓòÉΓòÉ 10.1.7. Handling Pasted or Dropped Data ΓòÉΓòÉΓòÉ
  10290.  
  10291. When data is pasted or dropped into a part, the part receiving the data can 
  10292. either embed the data as a separate or incorporate the data as intrinsic 
  10293. content. The part may also, in some circumstances, translate the data, or it 
  10294. might even refuse to accept the pasted data. 
  10295.  
  10296. This section discusses how OpenDoc and your part editor make these decisions, 
  10297. both with and without explicit user intervention. It also discusses when your 
  10298. part editor might explicitly translate data. 
  10299.  
  10300.  
  10301. ΓòÉΓòÉΓòÉ 10.1.7.1. Default Conventions ΓòÉΓòÉΓòÉ
  10302.  
  10303. In the absence of other instructions, OpenDoc expects your part to follow these 
  10304. specific conventions when pasting data from the clipboard or when accepting 
  10305. dropped data during a drag and drop operation. 
  10306.  
  10307.      If the transferred data consists of an arbitrary portion of the source 
  10308.       part's intrinsic content-plus possibly one or more embedded parts-the 
  10309.       destination part either incorporates or embeds that outer intrinsic 
  10310.       content, according to these rules: 
  10311.  
  10312.         -  If any of the representations of the outer data are of a part kind 
  10313.            directly readable by the destination part editor, the editor should 
  10314.            incorporate the outer data into the intrinsic content of the 
  10315.            destination part, and embed any parts that were embedded in the 
  10316.            outer data. 
  10317.  
  10318.         -  If none of the representations of the outer data is readable by the 
  10319.            destination part editor, the editor should create a new part, insert 
  10320.            all of the transferred data (including embedded parts) into the new 
  10321.            part, and embed the new part in a frame in the destination. 
  10322.  
  10323.      If the transferred data represents a single embedded frame that was cut 
  10324.       or copied (or dragged), the destination part editor should embed the data 
  10325.       as a separate part into the destination part, regardless of whether its 
  10326.       part kind is different from or identical to that of the destination. 
  10327.  
  10328.  The destination part should place clipboard data at the insertion point; it 
  10329.  should place dropped data at the point where the user releases the mouse 
  10330.  button. Note also that a pasted or dropped part takes on the view type that 
  10331.  its containing part prefers it to have. 
  10332.  
  10333.  
  10334. ΓòÉΓòÉΓòÉ 10.1.7.2. Handling the Paste As Dialog Box ΓòÉΓòÉΓòÉ
  10335.  
  10336. The Paste As dialog box allows the user to override OpenDoc and specify whether 
  10337. transferred data is to be embedded, incorporated, or translated and then 
  10338. embedded or incorporated. It also allows the user to create a link to the 
  10339. source of the transferred data. 
  10340.  
  10341. When the user chooses the Paste as command in the Edit menu (see Edit Menu), 
  10342. the active part calls the clipboard's ShowPasteAsDialog method to display the 
  10343. Paste As dialog box, shown in the following figure. Also, when the user presses 
  10344. Alt in a drag and drop operation, the active part calls the ODDragAndDrop 
  10345. ShowPasteAsDialog method. 
  10346.  
  10347. A part at the destination of a drop also displays this dialog box if the user 
  10348. holds down the Command key while performing a drop; see Dropping. 
  10349.  
  10350. The user can select the following options from the dialog box: 
  10351.  
  10352.      Paste with link. The user can request that a link be created between the 
  10353.       source and destination data. This option is not available to the user 
  10354.       unless the source document is open. Disable this option if your part does 
  10355.       not support linking. 
  10356.  
  10357.      Get Updates (of a link) Automatically/Manually. If the user creates a 
  10358.       link, updates can be either automatic or manual; this choice sets which 
  10359.       method the user wants. See Automatic and Manual Propagation of Updates 
  10360.       for more information. 
  10361.  
  10362.      Merge with contents. If the user chooses this option, the destination 
  10363.       part editor is expected to incorporate the data, if at all possible, even 
  10364.       if it requires translation and even if it means great loss of information 
  10365.       (such as converting text to a bitmap). 
  10366.  
  10367.       When you invoke the dialog box, you can check the part kinds available in 
  10368.       the data-transfer object and specify whether this option is enabled and 
  10369.       whether it is checked by default. Disable this option if your part cannot 
  10370.       incorporate the data, even after translation. 
  10371.  
  10372.      Embed As. If the user chooses this option, the source data must be 
  10373.       embedded in the destination as a separate part, even if incorporation is 
  10374.       possible. 
  10375.  
  10376.       When you invoke the dialog box, you can check the part kinds available in 
  10377.       the data-transfer object and specify whether this option is enabled and 
  10378.       whether it is checked by default. Disable this option if your part does 
  10379.       not support embedding. 
  10380.  
  10381.       With Embed As, the user can make the following selections: 
  10382.  
  10383.         -  Kind (of pasted data). With this option, the user can override 
  10384.            OpenDoc's default pasting decision and explicitly specify a 
  10385.            destination part kind from a pop-up menu. The user specifies the 
  10386.            specific translation to perform by selecting a new part kind for the 
  10387.            part in the kind pop-up menu. of the Paste As dialog box. The kind 
  10388.            pop-up menu allows the user to select a part kind to translate to. 
  10389.  
  10390.            This option (choosing part kind) is not available if the transferred 
  10391.            data consists of a single frame that is being moved (not copied) 
  10392.            from its original source. The moved frame may not be the only frame 
  10393.            displaying its part, and changing its kind would then affect the 
  10394.            display in the other parts, which may not be what the user intended. 
  10395.  
  10396.         -  View type. From the Embed As pop-up menu, the user can choose the 
  10397.            view type the embedded part is to have: frame, large icon, small 
  10398.            icon, or thumbnail. 
  10399.  
  10400.  The ShowPasteAsDialog method returns the results of the user's choices to your 
  10401.  part in an ODPasteAsResult structure: 
  10402.  
  10403.   struct ODPasteAsResult
  10404.   {
  10405.           ODBoolean           pasteLinkSetting;
  10406.           ODBoolean           autoUpdateSetting;
  10407.           ODBoolean           mergeSetting;
  10408.           ODTypeToken         selectedView;
  10409.           ODType              selectedKind;
  10410.           ODType              translateKind;
  10411.           ODEditor            editor;
  10412.   };
  10413.  
  10414.  Based on the contents of the returned structure, your part either embeds or 
  10415.  incorporates the transferred data, either accepts it as it is or translates 
  10416.  it, and either creates a link to its source or does not. 
  10417.  
  10418.      If the user has chosen to create a link, respond as described in Creating 
  10419.       a Link at the Destination. If you create a link, take into account the 
  10420.       automatic/manual update setting, as well as the other Paste As settings 
  10421.       chosen by the user. 
  10422.  
  10423.      If the user has chosen to translate the data but is not creating a link, 
  10424.       respond as described in Translating Before Incorporating or Embedding. If 
  10425.       the user is not creating a link or translating, read the transferred data 
  10426.       in either of two ways: 
  10427.  
  10428.         -  If your part can directly read any of the part kinds in the 
  10429.            data-transfer object's contents storage unit, and if the user has 
  10430.            not selected "Embed As", you incorporate the data. Follow the 
  10431.            instructions in Incorporating Intrinsic Content. 
  10432.  
  10433.         -  If your part cannot directly read any of the part kinds in the 
  10434.            storage unit, or if the user has selected "Embed As", follow the 
  10435.            instructions in Embedding a Single Part. 
  10436.  
  10437.  For more on translation, see Binding with Translation. 
  10438.  
  10439.  
  10440. ΓòÉΓòÉΓòÉ 10.2. Writing to a Data-Transfer Object ΓòÉΓòÉΓòÉ
  10441.  
  10442. You write data to a data-transfer object when the user cuts, copies, or drags 
  10443. data from your part or when you create or update the source of a link. This 
  10444. section discusses how to place that data into the data-transfer object. 
  10445.  
  10446. This section does not discuss how your part handles cutting (or moving) 
  10447. differently from copying. Cutting involves removing data from your part, 
  10448. including possibly one or more frames of embedded parts. Removing an embedded 
  10449. part is discussed in Removing an Embedded Part; other issues related to cutting 
  10450. operations are discussed in Handling Cut Data. 
  10451.  
  10452.  
  10453. ΓòÉΓòÉΓòÉ 10.2.1. Writing Intrinsic Content ΓòÉΓòÉΓòÉ
  10454.  
  10455. Intrinsic content plus possibly one or more embedded parts is the most general 
  10456. configuration of data that you put into a data-transfer object. If the data to 
  10457. be written consists of a combination of your part's intrinsic content plus 
  10458. embedded parts, you need to write your own intrinsic content, and you need to 
  10459. clone the embedded frames as well. These are the basic steps to take, 
  10460. regardless of whether or not your intrinsic content is accompanied by embedded 
  10461. frames: 
  10462.  
  10463.    1. Gain access to the data-transfer object and prepare to write to it. (See, 
  10464.       for example, the initial steps under Copying or Cutting to the Clipboard, 
  10465.       Initiating a Drag, Creating a Link at the Source, and Updating a Link at 
  10466.       the Source.) 
  10467.  
  10468.    2. Start the cloning operation, as described under Cloning. Specify the 
  10469.       appropriate kind of cloning operation, using one of the constants listed 
  10470.       in the table shown in Cloning Process. 
  10471.  
  10472.    3. Clone the embedded part into the data-transfer object by calling your 
  10473.       draft's Clone method. Unlike writing intrinsic content, you do not add a 
  10474.       kODPropContents property (the embedded part itself does that), a 
  10475.       kODPropName property (OpenDoc does that), or a kODPropSuggestedFrame 
  10476.       property (you instead add a kODPropContentFrame property). 
  10477.  
  10478.       Be sure to perform the cloning operation in this order: 
  10479.  
  10480.         a. Add a property of type kODPropContentFrame to the data-transfer 
  10481.            object's content storage unit. The presence of this property tells a 
  10482.            destination part that the data being transferred is a frame without 
  10483.            surrounding intrinsic content, and also signals to the embedded part 
  10484.            (the part being cloned) that it can write a promise instead of its 
  10485.            actual content. 
  10486.  
  10487.            It is important not to clone the frame yet. Wait until step 4, or 
  10488.            else the embedded part itself will be cloned into the wrong storage 
  10489.            unit. 
  10490.  
  10491.         b. Clone the embedded part into the data-transfer object's content 
  10492.            storage unit. 
  10493.  
  10494.         c. Clone the embedded part's frame into the data-transfer object's 
  10495.            draft (into any storage unit other than the content storage unit). 
  10496.            This cloning operation must occur after the embedded part is cloned. 
  10497.  
  10498.         d. Add a value of type kODWeakStorageUnitRef to the kODPropContentFrame 
  10499.            property of the data-transfer object's content storage unit. Create 
  10500.            a weak persistent reference from that value to the cloned frame. 
  10501.            This allows a destination part, upon recognizing the 
  10502.            kODPropContentFrame property, to locate the frame for the part in 
  10503.            the data-transfer object. 
  10504.  
  10505.    4. Optionally, write any intrinsic data you want associated with the frame 
  10506.       (such as a drop shadow or other visual adornment) as proxy content. Add a 
  10507.       property (of type kODPropProxyContents) to the data-transfer object, and 
  10508.       write your data into it as a value that you recognize. If the transferred 
  10509.       part is subsequently pasted into a part that also recognizes that value 
  10510.       and knows how to interpret it, the added frame characteristics can be 
  10511.       duplicated. 
  10512.  
  10513.    5. If the embedded part is the entire source or destination of a link, you 
  10514.       need to write additional proxy content, as described in Writing Linked 
  10515.       Content to Storage. follow the instructions in the note Writing Links for 
  10516.       Data Transfer. 
  10517.  
  10518.    6. If appropriate, write a link specification into the data-transfer object, 
  10519.       as described in Link Specification. 
  10520.  
  10521.    7. Perform any closing tasks specific to the individual kind of 
  10522.       data-transfer object you are writing to. (See, for example, the final 
  10523.       steps under Copying or Cutting to the Clipboard, Initiating a Drag, 
  10524.       Creating a Link at the Source, and Updating a Link at the Source.) 
  10525.  
  10526.  If this operation is a cut rather than a copy, note the additional 
  10527.  considerations listed in Handling Cut Data. 
  10528.  
  10529.  
  10530. ΓòÉΓòÉΓòÉ 10.3. Reading from a Data-Transfer Object ΓòÉΓòÉΓòÉ
  10531.  
  10532. You read from a data-transfer object when the user pastes or drops data into 
  10533. your part or when you create or update the destination of a link. This section 
  10534. discusses how to extract that data from the data-transfer object. 
  10535.  
  10536. When placing transferred data into your part, what you do with the data depends 
  10537. on how the part kinds within the transferred data relate to the part kind of 
  10538. your part (the destination part). 
  10539.  
  10540.  
  10541. ΓòÉΓòÉΓòÉ 10.3.1. Incorporating Intrinsic Content ΓòÉΓòÉΓòÉ
  10542.  
  10543. As the destination of a data transfer, your part incorporates the intrinsic 
  10544. content of the data-transfer object into your own part's intrinsic content (and 
  10545. embeds whatever embedded parts the transferred content contains) if all of 
  10546. these conditions apply: 
  10547.  
  10548.      The intrinsic content of the transferred data is stored in at least one 
  10549.       part kind that you can incorporate into your part. 
  10550.  
  10551.      The user has not specified Embed As in the Paste As dialog box. 
  10552.  
  10553.      The data-transfer object's content storage unit does not contain a 
  10554.       property named kODPropContentFrame. (If it does, the transferred data 
  10555.       consists of a single embedded frame without surrounding intrinsic 
  10556.       content, and must be embedded; see Frame Shape or Frame Annotation.) 
  10557.  
  10558.  When incorporating transferred data, you should generally read the 
  10559.  highest-fidelity part kind that your part editor understands. If the 
  10560.  transferred data includes a kODPropPreferredKind property, you should consider 
  10561.  that kind to be the highest-fidelity kind; otherwise, consider the first value 
  10562.  in the contents property to be the highest-fidelity kind. 
  10563.  
  10564.  Incorporating involves reading intrinsic content plus possibly cloning 
  10565.  embedded frames, links, and other objects. The following figure summarizes the 
  10566.  steps involved. 
  10567.  
  10568.  Here, in more detail, are the basic steps to take when incorporating: 
  10569.  
  10570.    1. Gain access to the data-transfer object and prepare to read from it. 
  10571.       (See, for example, the initial steps under Pasting from the Clipboard, 
  10572.       Dropping, Creating a Link at the Destination, and Updating a Link at the 
  10573.       Destination.) If you are incorporating translated data, you already will 
  10574.       have cloned the data into a temporary storage unit in your draft, and you 
  10575.       already will have translated it. Take these steps: 
  10576.  
  10577.           In the kODPropContents property of that storage unit, focus on the 
  10578.            value that corresponds to the translated part kind. Read the data 
  10579.            into your part, following your own content model. 
  10580.  
  10581.           Skip to step 5. 
  10582.  
  10583.    2. Start the cloning operation, as described under Cloning. Specify the 
  10584.       appropriate kind of cloning operation, using one of the constants listed 
  10585.       in the table shown in Cloning Process. 
  10586.  
  10587.    3. In the kODPropContents property of the data-transfer object's content 
  10588.       storage unit, focus on the value that corresponds to the highest-fidelity 
  10589.       part kind that you can incorporate into your part. (Note that this may 
  10590.       not be the highest-fidelity value present in the property.) Read the data 
  10591.       into your part, following your own content model. 
  10592.  
  10593.       As you encounter persistent references to objects (embedded frames, 
  10594.       link-source objects, link objects, auxiliary storage units, and so on), 
  10595.       clone each object into your draft, by calling the Clone method of the 
  10596.       data-transfer object's draft. Adjust your persistent references to point 
  10597.       to the newly cloned objects. 
  10598.  
  10599.    4. End the cloning operation. 
  10600.  
  10601.    5. If you are incorporating as a result of a drop, there may be a 
  10602.       kODPropMouseDownOffset property in the data-transfer object's content 
  10603.       storage unit. If so, focus on that property, read its value, and-if 
  10604.       appropriate for your content model-use the value to position the 
  10605.       incorporated data in relation to the drop location. 
  10606.  
  10607.       (If you are incorporating translated data, you must read this property 
  10608.       from the original data-transfer object, not the cloned storage unit.) 
  10609.  
  10610.    6. If the cloning was successful, instantiate each cloned embedded frame 
  10611.       into memory (with your draft's AcquireFrame method) and call the frame's 
  10612.       SetContainingFrame method, to make your part's display frame (the frame 
  10613.       that received the paste) the containing frame of the new embedded frame. 
  10614.  
  10615.       Create additional embedded frames as necessary, if your part's content 
  10616.       model specifies that the new part is to appear in more than one of your 
  10617.       display frames. If you do create new frames, synchronize them with the 
  10618.       first (source) frame; see Synchronizing Display Frames for more 
  10619.       information. 
  10620.  
  10621.    7. Change each new frame's link status to reflect its current location. If 
  10622.       your part does not support linking, you must nevertheless change your 
  10623.       cloned embedded frames' link status (to kODNotInLink). 
  10624.  
  10625.    8. If any of the objects that you have cloned into your part is a 
  10626.       link-source object or link object, follow the procedures described in 
  10627.       Reading Linked Content from Storage to make sure that the objects are 
  10628.       valid. 
  10629.  
  10630.    9. If any newly embedded frame is visible, assign a facet or facets to it, 
  10631.       as described in Adding a Facet. 
  10632.  
  10633.   10. Notify OpenDoc and your containing part that there has been a change to 
  10634.       your part's content; see Making Content Changes Known. 
  10635.  
  10636.   11. Perform any closing tasks specific to the individual kind of 
  10637.       data-transfer object you are reading from. (See, for example, the final 
  10638.       steps under Pasting from the Clipboard, Dropping, Creating a Link at the 
  10639.       Destination, and Updating a Link at the Destination.) (If you are 
  10640.       incorporating translated data, you can at this time remove the cloned 
  10641.       temporary storage unit from your draft.) 
  10642.  
  10643.  
  10644. ΓòÉΓòÉΓòÉ 10.3.2. Embedding a Single Part ΓòÉΓòÉΓòÉ
  10645.  
  10646. As the destination of a data transfer, your part embeds the entire contents of 
  10647. the data-transfer object as a single part (plus whatever embedded parts it 
  10648. contains) if any of these conditions apply: 
  10649.  
  10650.      The intrinsic content is of a part kind that you cannot incorporate. 
  10651.  
  10652.      The user has specified Embed As in the Past As dialog box. 
  10653.  
  10654.      The transferred data consists of a single embedded frame, without 
  10655.       surrounding intrinsic content (regardless of its part kind). In this case 
  10656.       the data-transfer object's content storage unit contains a property named 
  10657.       kODPropContentFrame, that is a signal that the data consists of a single 
  10658.       frame and must be embedded, even if it is of a part kind that you can 
  10659.       incorporate. See Frame Shape or Frame Annotation. 
  10660.  
  10661.  Embedding data from a data-transfer object as a single part involves, 
  10662.  basically, cloning the content storage unit into your draft and then providing 
  10663.  for a frame and facets for the new part. The steps involved are summarized in 
  10664.  the following figure. 
  10665.  
  10666.  Here, in more detail, are the basic steps to take when embedding: 
  10667.  
  10668.    1. Gain access to the data-transfer object and prepare to read from it. 
  10669.       (See, for example, the initial steps under Pasting from the Clipboard, 
  10670.       Dropping, Creating a Link at the Destination, and Updating a Link at the 
  10671.       Destination.) 
  10672.  
  10673.       If you are embedding translated data, you already will have cloned the 
  10674.       data into a new storage unit in your draft, and you already will have 
  10675.       translated it. Skip to step 6. 
  10676.  
  10677.    2. Start the cloning operation, as described under Cloning. Specify the 
  10678.       appropriate kind of cloning operation, using one of the constants listed 
  10679.       in the table shown in Cloning Process. 
  10680.  
  10681.    3. Clone the data-transfer object's content storage unit into a new storage 
  10682.       unit in your draft, using the Clone method of the data-transfer object's 
  10683.       draft. 
  10684.  
  10685.    4. If there is a property named kODPropContentFrame in the cloned storage 
  10686.       unit, read the storage-unit reference it contains and use that reference 
  10687.       to clone the new part's frame into your draft. (Cloning the data-transfer 
  10688.       object's content storage unit alone does not copy the frame, because the 
  10689.       reference is a weak persistent reference.) 
  10690.  
  10691.    5. End the cloning operation. 
  10692.  
  10693.    6. If the data has been translated, or if this embedding occurs as a result 
  10694.       of the Paste As dialog box and the user has chosen a part kind that is 
  10695.       not the preferred kind, or if a preferred kind property does not exist 
  10696.       and the user has chosen a part kind that is not the highest-fidelity 
  10697.       (=first) value stored in the transferred storage unit's contents 
  10698.       property, you need to notify the future part editor of that part that a 
  10699.       different part kind should be used. Create a property with the name 
  10700.       kODPropPreferredKind in the cloned storage unit (if the property does not 
  10701.       already exist) and write into it a value that specifies the part kind the 
  10702.       editor should use. 
  10703.  
  10704.    7. If this embedding occurs as a result of the Paste As dialog box and the 
  10705.       user has chosen a specific part editor to edit the part, add a property 
  10706.       with the name kODPropPreferredEditor to the cloned storage unit, and 
  10707.       write into it the editor ID (returned in the editor field of the 
  10708.       ODPasteAsResult structure) of the preferred editor. 
  10709.  
  10710.    8. If the cloned storage unit contains a property named kODPropProxyContent, 
  10711.       that property contains any proxy content that the part's original 
  10712.       containing part wanted associated with the frame, such as a drop shadow 
  10713.       or other visual adornment. (Note that this property is absent if the 
  10714.       transferred data includes any intrinsic content in addition to the 
  10715.       embedded frame.) 
  10716.  
  10717.       Focus the cloned storage unit on the kODPropProxyContent property and 
  10718.       read in the information from the data-transfer object (not from the 
  10719.       cloned storage unit). Note that you must understand the format of the 
  10720.       proxy content in order to use it, and it becomes part of your own part's 
  10721.       intrinsic content to be associated with the frame. If you do not 
  10722.       understand the format, ignore the data. 
  10723.  
  10724.    9. If you are embedding as a result of a drop, there may be a property named 
  10725.       kODPropMouseDownOffset in the content storage unit of the data-transfer 
  10726.       object (not the cloned storage unit). If so, focus on that property, read 
  10727.       its value, and-if appropriate for your content model-use the value to 
  10728.       position the embedded data in relation to the drop location. 
  10729.  
  10730.   10. Recreate the new part's frame-if it has been provided in the 
  10731.       kODPropContentFrame property-using your draft's AcquireFrame method, and 
  10732.       call its SetContainingFrame method to assign your part's display frame 
  10733.       (the frame that received the paste) as the containing frame. If no frame 
  10734.       was provided, you need to create one: 
  10735.  
  10736.           Obtain the suggested frame shape-if it exists-from the data-transfer 
  10737.            object (not from the cloned storage unit). It is in a property named 
  10738.            kODPropSuggestedFrameShape. If it is not there, use a default frame 
  10739.            shape. 
  10740.  
  10741.           Recreate the new part; pass the cloned storage unit's ID to your 
  10742.            draft's AcquirePart method. 
  10743.  
  10744.           Create the frame for the part, using your draft's CreateFrame 
  10745.            method. 
  10746.  
  10747.   11. Change the link status of the new frame to reflect its current location. 
  10748.       If your part does not support linking, you must nevertheless change your 
  10749.       new embedded frame's link status (to kODNotInLink). 
  10750.  
  10751.   12. If the newly embedded frame is visible, assign facets to it, as described 
  10752.       in Adding a Facet. 
  10753.  
  10754.   13. Notify OpenDoc and your containing part that there has been a change to 
  10755.       your part's content; see Making Content Changes Known. 
  10756.  
  10757.   14. Perform any closing tasks specific to the individual kind of 
  10758.       data-transfer object you are reading from. (See, for example, the final 
  10759.       steps under Pasting from the Clipboard, Dropping, Creating a Link at the 
  10760.       Destination, and Updating a Link at the Destination.) 
  10761.  
  10762.  
  10763. ΓòÉΓòÉΓòÉ 10.3.3. Translating Before Incorporating or Embedding ΓòÉΓòÉΓòÉ
  10764.  
  10765. If you must translate transferred data before incorporating or embedding it in 
  10766. your part, follow the steps listed here before following those in Incorporating 
  10767. Intrinsic Content and Embedding a Single Part. The OpenDoc translation service 
  10768. is described in general in Translation. Basically, you translate by first 
  10769. cloning the data into a storage unit in your own draft, then modifying it, and 
  10770. then completing the data transfer. When you perform translation on transferred 
  10771. data, you always write the translated data into a storage unit in your own 
  10772. draft; do not write it back into the original data-transfer object. Subsequent 
  10773. readers of the data cannot tell a translated value from a value written by the 
  10774. data's original part editor. 
  10775.  
  10776. These are the general steps you might follow: 
  10777.  
  10778.    1. Gain access to the data-transfer object that contains the untranslated 
  10779.       data and prepare to read from it. (See, for example, the initial steps 
  10780.       under Pasting from the Clipboard, Dropping, and Updating a Link at the 
  10781.       Source. 
  10782.  
  10783.       (If you are creating a link, remember that you read the data from the 
  10784.       newly created link object, not the clipboard or drag and drop that 
  10785.       contained the link specification.) 
  10786.  
  10787.    2. Start the cloning operation, as described under Cloning. Specify the 
  10788.       appropriate kind of cloning transaction, using one of the constants 
  10789.       listed in the table in Cloning Process. 
  10790.  
  10791.    3. Clone the data-transfer object's content storage unit into a new storage 
  10792.       unit in your draft, using the Clone method of the data-transfer object's 
  10793.       draft. 
  10794.  
  10795.    4. If there is a property named kODPropContentFrame in the cloned storage 
  10796.       unit, you must embed the data. Read the storage-unit reference the 
  10797.       property contains and use that reference to clone the new part's frame 
  10798.       from the data-transfer object's storage unit into your draft. (Cloning 
  10799.       the data-transfer object's content storage unit alone does not copy the 
  10800.       frame, because the reference is a weak persistent reference.) 
  10801.  
  10802.    5. Access the storage unit of the cloned-but-untranslated data, and focus on 
  10803.       its contents property. Add a value whose value type is the part kind you 
  10804.       are translating to. 
  10805.  
  10806.    6. Create two storage-unit views: one focused on the original untranslated 
  10807.       value, and the other focused on the translated value you have just 
  10808.       created. 
  10809.  
  10810.    7. Gain access to the translation object (by calling the session object's 
  10811.       GetTranslation method), and then call the translation object's 
  10812.       TranslateView method, passing it the two storage-unit views. The 
  10813.       translation object performs the translation and writes the new data into 
  10814.       the new value. 
  10815.  
  10816.    8. If the translation is successful, delete the storage-unit views. 
  10817.  
  10818.  Complete the transfer of the translated data in either of two ways, depending 
  10819.  on whether you are incorporating or embedding, or whether you are creating or 
  10820.  updating a link: 
  10821.  
  10822.      If your part can directly read the part kind of the translated data (and 
  10823.       if the user has not selected "Embed As" from the Paste As dialog box), 
  10824.       incorporate it. Follow the steps in the section Incorporating Intrinsic 
  10825.       Content. 
  10826.  
  10827.       The following figure summarizes the steps involved. Note that you read 
  10828.       the content into your part from the cloned temporary storage unit, not 
  10829.       the original data-transfer object, and that you remove the temporary 
  10830.       storage from your draft when the transfer is complete. 
  10831.  
  10832.      If your part cannot directly read the part kind of the translated data 
  10833.       (or if the user has selected "Embed As" from the Paste As dialog box), 
  10834.       follow the instructions in Embedding a Single Part. 
  10835.  
  10836.       The following figure summarizes the steps involved. Note that the cloned 
  10837.       storage unit is not temporary, but becomes the new embedded part's 
  10838.       storage unit. Note also that you must read proxy content from the 
  10839.       original data-transfer storage unit, not the cloned one. 
  10840.  
  10841.  
  10842. ΓòÉΓòÉΓòÉ 10.4. Clipboard Transfer ΓòÉΓòÉΓòÉ
  10843.  
  10844. The clipboard commands Cut, Copy, and Paste constitute a common mechanism for 
  10845. transferring data within and across conventional documents, even documents of 
  10846. different data formats. For OpenDoc documents, these commands perform the same 
  10847. tasks, but with added capabilities: 
  10848.  
  10849.      The commands operate on embedded parts as well as intrinsic content. The 
  10850.       data copied to or pasted from the clipboard can contain any number of 
  10851.       parts, of any part kinds. The parts may be displayed in frames or 
  10852.       represented as icons. 
  10853.  
  10854.      The Paste and Paste As commands can either embed parts or incorporate 
  10855.       data as intrinsic content. 
  10856.  
  10857.      The Paste and Paste As commands can create a new part when it embeds 
  10858.       intrinsic content of one part kind into a part of a different part kind. 
  10859.  
  10860.      The Paste As command can create a persistent link to the source of the 
  10861.       data being pasted. 
  10862.  
  10863.      The Paste As command also allows the user to override decisions on 
  10864.       incorporating vs. embedding that would normally be made by OpenDoc. 
  10865.  
  10866.  As with data placed in a conventional clipboard, if your part editor stores 
  10867.  multiple formats on the clipboard-including standard formats-the user has a 
  10868.  greater chance of being able to incorporate (rather than embed) the data into 
  10869.  more kinds of parts. 
  10870.  
  10871.  
  10872. ΓòÉΓòÉΓòÉ 10.4.1. Clipboard Concepts ΓòÉΓòÉΓòÉ
  10873.  
  10874. This section discusses some basic clipboard operations common to both reading 
  10875. and writing, such as acquiring the clipboard focus and using the clipboard 
  10876. update ID. It also presents some special considerations related to updating the 
  10877. clipboard and cutting data from your part. 
  10878.  
  10879. Enabling the Cut and Paste menu items 
  10880. OpenDoc does not permit changes to your draft (and therefore your part's 
  10881. content) if the draft permissions are read-only. You should check your draft 
  10882. permissions (see Drafts) before enabling the Cut, Paste, or Paste As items in 
  10883. the Edit menu and before allowing the user to perform a cut or paste operation. 
  10884.  
  10885. The OS/2 implementation of the clipboard object provides two extra methods to 
  10886. help parts in determining whether or not they can enable the Paste menu items; 
  10887. they are called CanEmbed and CanIncorporate. CanEmbed queries the registration 
  10888. manager for a part editor capable of handling the content of the clipboard 
  10889. storage unit. It is intended for use by container parts. CanIncorporate 
  10890. determines if a specific type of content is present on the clipboard. Parts 
  10891. should call this method for the kinds they support. 
  10892.  
  10893.  
  10894. ΓòÉΓòÉΓòÉ 10.4.1.1. Acquiring and Relinquishing the Clipboard Focus ΓòÉΓòÉΓòÉ
  10895.  
  10896. Your part can access the clipboard only when your part is in the foreground 
  10897. process; access from a background process is meaningless. Furthermore, to be 
  10898. thread-safe, you must always acquire the clipboard focus before writing or 
  10899. reading clipboard data. As long as you hold the clipboard focus, no other part 
  10900. can access or modify the data. 
  10901.  
  10902. Typically, your part needs to inspect the contents of the clipboard before 
  10903. deciding whether to enable Edit menu items, so your AdjustMenus method can 
  10904. include a call to the arbitrator's RequestFocus method to acquire the clipboard 
  10905. focus. 
  10906.  
  10907. After acquiring the clipboard focus, you can access the clipboard when 
  10908. responding to a menu command (or its keyboard equivalent) with your HandleEvent 
  10909. method by calling the session object's GetClipboard method. You should then 
  10910. unilaterally relinquish the clipboard focus in your HandleEvent method, after 
  10911. having handled the clipboard command. 
  10912.  
  10913. These are the steps you take to acquire the clipboard focus and prepare to 
  10914. write to it or read from it: 
  10915.  
  10916.    1. Acquire the clipboard focus, using the Arbitrator's RequestFocus method 
  10917.       (as described in Requesting Foci). 
  10918.  
  10919.    2. Get access to the clipboard object, using the session object's 
  10920.       GetClipboard method. 
  10921.  
  10922.    3. Acquire the clipboard focus, using the Arbitrator's RequestFocus method 
  10923.       (as described in Requesting Foci). 
  10924.  
  10925.    4. If you are writing to the clipboard, remove any existing data on the 
  10926.       clipboard with the clipboard's Clear method. (Do not take this step if 
  10927.       you are reading from the clipboard.) 
  10928.  
  10929.    5. Get access to the clipboard's content storage unit, using the clipboard's 
  10930.       GetContentStorageUnit method. 
  10931.  
  10932.  You relinquish the Clipboard focus by calling the arbitrator's RelinquishFocus 
  10933.  method. If you receive a deactivate event because your window is being 
  10934.  deactivated and your frame holds the Clipboard focus, your HandleEvent method 
  10935.  should call RelinquishFocus. Also, during the normal process of negotiated 
  10936.  focus transfer (see Relinquishing Foci), your part should also be prepared to 
  10937.  temporarily relinquish the clipboard focus, so that inactive parts can inspect 
  10938.  the clipboard when necessary. 
  10939.  
  10940.  
  10941. ΓòÉΓòÉΓòÉ 10.4.1.2. Clipboard Update ID ΓòÉΓòÉΓòÉ
  10942.  
  10943. Whenever you copy data to the clipboard, you should get and save the 
  10944. clipboard's current update ID, a number used to identify this particular 
  10945. instance of clipboard contents. You obtain the update ID by calling the 
  10946. clipboard's GetUpdateID method. 
  10947.  
  10948. If a link specification that you have written to the clipboard becomes invalid 
  10949. because of changes to your content that was copied to the clipboard, you must 
  10950. remove the link specification from the clipboard, as described in Removing a 
  10951. Link Specification from the Clipboard. You can examine the clipboard's current 
  10952. update ID at any time and compare it with your saved update ID; if they are 
  10953. identical, the clipboard has not changed. 
  10954.  
  10955.  
  10956. ΓòÉΓòÉΓòÉ 10.4.1.3. Removing a Link Specification from the Clipboard ΓòÉΓòÉΓòÉ
  10957.  
  10958. If your part copies some of its content to the clipboard and the user then 
  10959. modifies the equivalent content in your part (without copying anything else to 
  10960. the clipboard), the clipboard data no longer exactly matches the source data in 
  10961. your part. The potential link represented by the link specification you wrote 
  10962. in the clipboard therefore no longer reflects the content at the source of the 
  10963. link. Small changes may not matter, but if your source content has changed to 
  10964. the extent that creating a link is no longer feasible, your part must remove 
  10965. the link specification. 
  10966.  
  10967. By saving the update ID of the clipboard whenever you copy data to it, you can 
  10968. check that ID against the current update ID of the clipboard whenever your 
  10969. source data changes. If the IDs match, the clipboard still contains the data 
  10970. that you placed in it, and you should remove the link specification. 
  10971.  
  10972. You can follow these steps to remove a link specification: 
  10973.  
  10974.    1. Acquire the clipboard focus as described in Acquiring and Relinquishing 
  10975.       the Clipboard Focus. 
  10976.  
  10977.    2. Get the clipboard's update ID and compare it to your stored update ID. If 
  10978.       they do not match, skip to step 5. 
  10979.  
  10980.    3. Access the clipboard's content storage unit. (Unlike when writing to the 
  10981.       clipboard, do not clear the clipboard data.) 
  10982.  
  10983.    4. Focus the storage unit on the link-specification property (type 
  10984.       kODLinkSpec), and remove that property, using the storage unit's Remove 
  10985.       method. 
  10986.  
  10987.    5. Call the clipboard object's ExportClipboard method (OS/2 implementation 
  10988.       only). 
  10989.  
  10990.    6. Relinquish the clipboard focus. 
  10991.  
  10992.  
  10993. ΓòÉΓòÉΓòÉ 10.4.1.4. Undo for Clipboard ΓòÉΓòÉΓòÉ
  10994.  
  10995. If your part supports cutting, copying, or pasting, it must also support 
  10996. undoing those operations. (Note that data transfer between parts is undoable 
  10997. only if both parts involved have undo support.) Undo support in general is 
  10998. described in Undo. 
  10999.  
  11000. Whenever your part performs a cut, copy, or paste operation, it should call the 
  11001. clipboard's ActionDone method, to notify the clipboard of the kind of cloning 
  11002. transaction that was used. When your part cuts an object to the clipboard, it 
  11003. should relinquish ownership of the object (as in the sense of ownership of a 
  11004. link source) but not release the object, instead saving a reference to the 
  11005. object in an undo action. Then, if the user chooses the Undo command and your 
  11006. part's UndoAction method is called, your part should: 
  11007.  
  11008.      Reassume ownership of the object, reinstating the object's relationship 
  11009.       to the part's content 
  11010.  
  11011.      Notify the clipboard that the cut was undone, by calling the clipboard's 
  11012.       ActionUndone method, passing it the update ID you saved when you wrote 
  11013.       the data to the clipboard If the user subsequently chooses the Redo 
  11014.       command and your part's RedoAction method is called, your part should 
  11015.  
  11016.      Once again relinquish ownership of the object 
  11017.  
  11018.      Notify the clipboard that the cut was redone, by calling the clipboard's 
  11019.       ActionRedone method, passing it the same update ID 
  11020.  
  11021.  Calling ActionDone, ActionUndone, and ActionRedone allows the clipboard to 
  11022.  know whether it is involved in a cut or a copy or the restoration of a cut or 
  11023.  a copy; the clipboard's internal handling of its objects differs in each case. 
  11024.  
  11025.  If and when your part's DisposeActionState method is called, you can at that 
  11026.  point release (not remove from your draft) the object referenced in your undo 
  11027.  action. 
  11028.  
  11029.  To undo a cut, copy, or paste operation requires the restoration of the 
  11030.  previous state of the document involved, but it does not require the 
  11031.  restoration of the previous state of the clipboard. Therefore, if you redo a 
  11032.  paste operation that has been undone, you cannot assume that the clipboard 
  11033.  once again contains the original data that had been pasted. You must implement 
  11034.  the redo from your own data, which means that you should retain a copy of 
  11035.  pasted data in a private cache. 
  11036.  
  11037.  
  11038. ΓòÉΓòÉΓòÉ 10.4.2. Copying or Cutting to the Clipboard ΓòÉΓòÉΓòÉ
  11039.  
  11040. You write data to the clipboard as a result of the user selecting the Cut 
  11041. command or the Copy command from the Edit menu (or their keyboard equivalents). 
  11042. These are the basic steps to take: 
  11043.  
  11044.    1. Acquire the clipboard focus and access the clipboard's content storage 
  11045.       unit, as described in Acquiring and Relinquishing the Clipboard Focus. 
  11046.  
  11047.    2. Write the data to the clipboard: 
  11048.  
  11049.           If the selection consists of a combination of your part's intrinsic 
  11050.            content plus zero or more embedded parts, you need to write or 
  11051.            promise your own intrinsic content to the clipboard, and you need to 
  11052.            clone the embedded frames and parts as well. Follow the steps listed 
  11053.            in Writing Intrinsic Content. 
  11054.  
  11055.           If the selection consists of a single frame of an embedded part, 
  11056.            with no surrounding intrinsic content, you need to clone the part 
  11057.            and provide a frame for it. 
  11058.  
  11059.       In either case, when you call the BeginClone method, specify either 
  11060.       kODCloneCopy or kODCloneCut, depending on whether you are copying or 
  11061.       cutting the data to the clipboard. 
  11062.  
  11063.    3. When you have finished, if you have written either a link specification 
  11064.       or a promise to the clipboard, get the clipboard's current update ID and 
  11065.       save it (see Clipboard Update ID), in case you later have to remove the 
  11066.       link specification or fulfill the promise. 
  11067.  
  11068.    4. Call the clipboard's ActionDone method, specifying either kODCloneCopy or 
  11069.       kODCloneCut. 
  11070.  
  11071.    5. If this operation was a cut rather than a copy, it must be undoable. Add 
  11072.       a single action to the action history, as described in Adding an Action 
  11073.       to the Undo History. Be sure to follow the special instructions in 
  11074.       Handling Cut Data. Delete the cut selection from your part. 
  11075.  
  11076.    6. Call the clipboard object's ExportClipboard method (OS/2 implementation 
  11077.       only). 
  11078.  
  11079.    7. Relinquish the clipboard focus (see Acquiring and Relinquishing the 
  11080.       Clipboard Focus). Alternatively, you can wait until asked to relinquish 
  11081.       the focus by the next requester of the clipboard focus. 
  11082.  
  11083.  
  11084. ΓòÉΓòÉΓòÉ 10.4.3. Pasting from the Clipboard ΓòÉΓòÉΓòÉ
  11085.  
  11086. You read data from the clipboard as a result of the user selecting the Paste 
  11087. command or the Paste As command from the Edit menu. These are the basic steps 
  11088. to take: 
  11089.  
  11090.    1. Acquire the clipboard focus and access the clipboard's content storage 
  11091.       unit, as described in Acquiring and Relinquishing the Clipboard Focus. 
  11092.       (Do not clear the clipboard data, of course). 
  11093.  
  11094.    2. Read the data from the clipboard: 
  11095.  
  11096.           If the data consists of intrinsic content plus zero or more embedded 
  11097.            frames, and if the intrinsic content is of a part kind that you can 
  11098.            incorporate into your part, you need to read the intrinsic content 
  11099.            and possibly clone embedded parts, links, or other objects. Follow 
  11100.            the steps listed in Incorporating Intrinsic Content. 
  11101.  
  11102.           If you need to embed the data as a single part with no surrounding 
  11103.            intrinsic content, you need to clone the part and either extract its 
  11104.            frame or create a frame for it. Follow the steps listed in Embedding 
  11105.            a Single Part. That section lists the conditions under which you 
  11106.            must embed rather than incorporate clipboard data. 
  11107.  
  11108.       In either case, when you call the BeginClone method, specify 
  11109.       kODClonePaste. 
  11110.  
  11111.    3. Pasting must be an undoable operation. Get the update ID of the clipboard 
  11112.       data and save it in a single undo action (see Adding an Action to the 
  11113.       Undo History, so that you can undo the paste operation if necessary. 
  11114.  
  11115.    4. Call the clipboard's ActionDone method, specifying kODClonePaste. 
  11116.  
  11117.    5. Relinquish the clipboard focus (see Acquiring and Relinquishing the 
  11118.       Clipboard Focus). 
  11119.  
  11120.  
  11121. ΓòÉΓòÉΓòÉ 10.5. Drag and Drop ΓòÉΓòÉΓòÉ
  11122.  
  11123. The OpenDoc drag and drop facility allows users to apply direct manipulation to 
  11124. move or copy data. Users can drag items from one location in a part or document 
  11125. (or the desktop) to another location in the same or different part or document 
  11126. (or to the desktop). 
  11127.  
  11128.  
  11129. ΓòÉΓòÉΓòÉ 10.5.1. Drag and Drop Concepts ΓòÉΓòÉΓòÉ
  11130.  
  11131. Drag and drop provides a direct-manipulation alternative to the clipboard. The 
  11132. fundamental user-level operations-copying and moving-are similar in drag and 
  11133. drop and in clipboard transfer, and are similar across all platforms. 
  11134.  
  11135.  
  11136. ΓòÉΓòÉΓòÉ 10.5.1.1. User Interaction ΓòÉΓòÉΓòÉ
  11137.  
  11138. The user typically initiates a drag by positioning the mouse pointer over some 
  11139. selected (or single-click-selectable) content, pressing and holding down the 
  11140. mouse button, and then moving the pointer. The user can press a modifier key 
  11141. before pressing the mouse button, or at any time before releasing the mouse 
  11142. button, to force a drag to be a copy (called a drag-copy) or a move (called a 
  11143. drag-move). 
  11144.  
  11145. As the user moves the mouse pointer, an outline of the selected item (provided 
  11146. by the source part, drawn by OpenDoc) is dragged to the new location. When the 
  11147. user releases the mouse button, the item is placed (dropped) at the pointer 
  11148. location. The part beneath the pointer is notified that something has been 
  11149. dropped on it. At this point, the destination part behaves essentially as it 
  11150. does when pasting from the clipboard; it makes the same decisions regarding 
  11151. embedding versus incorporating data and handling links. The source part may 
  11152. have to delete the items if it was a move operation or do nothing if it was a 
  11153. copy. 
  11154.  
  11155. Drag and drop allows parts to restrict the dropped content they will accept to 
  11156. specific part kinds. To indicate that it can accept a drop, a part provides 
  11157. appropriate feedback to the user once the mouse pointer enters its facet. 
  11158.  
  11159. For frames and icons that are being dragged, OpenDoc provides specific behavior 
  11160. and appearance for the item being dragged. For intrinsic content that is being 
  11161. dragged, your part editor is responsible for defining behavior and providing 
  11162. user feedback. 
  11163.  
  11164. The user can move an active frame by dragging its border. The user moves the 
  11165. pointer to the active frame border and presses the mouse button; this causes 
  11166. the frame to become selected so the user can start dragging it. 
  11167.  
  11168. The user can move a selected frame by moving the pointer anywhere within it and 
  11169. pressing the button to start a drag. Also, if a frame is bundled, the user can 
  11170. drag it by pressing the mouse button while the pointer is anywhere in the 
  11171. interior of the frame, whether or not the frame is already active or selected. 
  11172.  
  11173. When the user releases the mouse button, the frame and its part are dropped at 
  11174. the new location. After a frame is dropped, it becomes selected. The 
  11175. destination may adjust the drop location of a frame based on constraints such 
  11176. as gridding (in a graphics part) or text position (in a text part). 
  11177.  
  11178.  
  11179. ΓòÉΓòÉΓòÉ 10.5.1.2. Move Versus Copy ΓòÉΓòÉΓòÉ
  11180.  
  11181. OpenDoc follows these conventions for drag and drop: 
  11182.  
  11183.      When a user drags an item within a document, the item is moved, not 
  11184.       copied. Note that a window boundary is not always a document boundary; 
  11185.       dragging an item to or from a part window, but still within the same 
  11186.       document, results in a move. 
  11187.  
  11188.      When the user drags an item across a document boundary, the item is 
  11189.       copied, not moved. 
  11190.  
  11191.      When the user employs drag and drop to move a frame, the moved frame 
  11192.       displays the original part if the destination is in the same document. 
  11193.       However, if the destination is in a different document, the source frame 
  11194.       is deleted and a new part (and new frame displaying the contents) is 
  11195.       created at the destination. (In contrast, clipboard pasting always 
  11196.       creates a new part and frame.) 
  11197.  
  11198.  OpenDoc supports a mechanism for you to allow the user to force a copy or move 
  11199.  operation by pressing modifier keys. 
  11200.  
  11201.  Dragging stationery 
  11202.  Stationery parts may be copied exactly like any other part. However, if you 
  11203.  drag-move stationery into a part whose preferred view type for embedded parts 
  11204.  is frame view, a copy is "torn off" the stationery pad and displayed in a 
  11205.  frame. The stationery part remains in its original location, unchanged. 
  11206.  
  11207.  
  11208. ΓòÉΓòÉΓòÉ 10.5.1.3. Droppable Frames ΓòÉΓòÉΓòÉ
  11209.  
  11210. Each frame has a SetDroppable method, through which the part displayed in the 
  11211. frame controls whether or not the frame can (in general) accept dropped data. 
  11212. When a display frame is added or reconnected to your part, you can call 
  11213. SetDroppable and pass either kODTrue or kODFalse to allow or disallow, 
  11214. respectively, dropping. (Frames are initially created as non-droppable.) You 
  11215. can call SetDroppable again at any time to change the state of the frame. 
  11216.  
  11217. OpenDoc calls the IsDroppable method of the frame before making the 
  11218. drag-related method calls DragEnter, DragWithin, DragLeave, or Drop to your 
  11219. part. If your display frame is non-droppable, your part does not receive any of 
  11220. these calls. 
  11221.  
  11222. Your part's display frame does not have to be droppable for you to initiate a 
  11223. drag from it. 
  11224.  
  11225.  
  11226. ΓòÉΓòÉΓòÉ 10.5.1.4. Undo for Drag and Drop ΓòÉΓòÉΓòÉ
  11227.  
  11228. If your part supports dragging and dropping data, it must also support undoing 
  11229. that operation. (Note that data transfer between parts is undoable only if both 
  11230. parts involved have undo support.) Undo support in general is described in 
  11231. Undo. 
  11232.  
  11233. For drag and drop, undo involves a two-stage action. The part initiating the 
  11234. drag begins the two-stage action, the part receiving the drop adds a 
  11235. single-stage action, and the initiating part completes the two-stage action 
  11236. when the drop completes. See Adding Two-Stage Actions for more details. 
  11237.  
  11238.  
  11239. ΓòÉΓòÉΓòÉ 10.5.2. Initiating a Drag ΓòÉΓòÉΓòÉ
  11240.  
  11241. In response to a mouse-down event at the appropriate location, the part 
  11242. receiving the mouse event (the source part) has the choice of initiating a 
  11243. drag. You should follow the guidelines listed under Mouse Events, Activation, 
  11244. and Dragging in deciding whether to initiate a drag operation. 
  11245.  
  11246. To initiate a drag, you (the source part) should follow these steps: 
  11247.  
  11248.    1. Call the GetDragAndDrop method of the session object to get access to the 
  11249.       ODDragAndDrop object. Then call the Clear method and the 
  11250.       GetContentStorageUnit method of the drag and drop object to get an empty 
  11251.       storage unit into which to copy the dragged data. 
  11252.  
  11253.       Note that there is no drag and drop focus or lock to be acquired. Only 
  11254.       one part at a time can initiate and complete a drag. 
  11255.  
  11256.    2. Write or promise the dragged data into the drag and drop storage unit: 
  11257.  
  11258.           If the data is intrinsic content-with or without one or more 
  11259.            embedded parts-follow the procedure given in Writing Intrinsic 
  11260.            Content. 
  11261.  
  11262.       In either case, when you call the Begin Clone method, specify 
  11263.       kODCloneCopy, even if you are initiating a drag-move. (The user can 
  11264.       override the move-versus-copy conventions when dropping the data.) 
  11265.  
  11266.    3. Create a property with the name kODPropMouseDownOffset in the drag and 
  11267.       drop storage unit, and write into it a value (of type kODPoint) that 
  11268.       specifies the offset of the mouse from the origin of the selection or 
  11269.       item that is being dragged. This allows the destination part to correctly 
  11270.       locate the item in relation the mouse-up event when it is dropped. 
  11271.  
  11272.    4. If there are frames that should not accept a drop from this drag-such as 
  11273.       any frames that are themselves being dragged-call the frames' SetDragging 
  11274.       method and pass a value of kODTrue to notify OpenDoc that it should not 
  11275.       allow them to be drop targets. 
  11276.  
  11277.    5. Initiate the drag by calling the drag and drop object's StartDrag method. 
  11278.       When you call StartDrag, you are responsible for providing OpenDoc an 
  11279.       image, such as an outline, for it to display to the user as dragging 
  11280.       feedback. 
  11281.  
  11282.    6. Add a begin action to the undo action history (see Adding Two-Stage 
  11283.       Actions), to allow the user to undo the drag if necessary. 
  11284.  
  11285.  The StartDrag method completes when the drop occurs; see Completion of 
  11286.  StartDrag. 
  11287.  
  11288.  
  11289. ΓòÉΓòÉΓòÉ 10.5.3. Operations while a Drag Is in Progress ΓòÉΓòÉΓòÉ
  11290.  
  11291. As long as the mouse button remains pressed, the drag is in progress. Potential 
  11292. destination parts need to perform certain actions during dragging, when the 
  11293. mouse pointer is within their facets. 
  11294.  
  11295.  
  11296. ΓòÉΓòÉΓòÉ 10.5.3.1. On Entering a Part's Facet ΓòÉΓòÉΓòÉ
  11297.  
  11298. Any facet the mouse pointer passes over during a drag represents a potential 
  11299. drop destination, if the facet's frame is droppable. OpenDoc calls a part's 
  11300. DragEnter method when the pointer enters one of its droppable frames' facets 
  11301. during a drag: 
  11302.  
  11303. ODDragResult DragEnter (in ODDragItemIterator dragInfo,
  11304.                                     in ODFacet facet,
  11305.                                     in ODPoint where);
  11306.  
  11307. On receiving a call to its DragEnter method, your part (the potential 
  11308. destination part) should take these steps: 
  11309.  
  11310.    1. Examine the part kinds of the dragged data, using a drag-item iterator 
  11311.       (class ODDragItemIterator) passed to it. Inspect the part kinds in each 
  11312.       item's storage unit and determine whether or not you can accept the 
  11313.       dragged data. 
  11314.  
  11315.       Note:  As for the clipboard object,the OS/2 implementation of the 
  11316.              ODDragAndDrop object provides two extra methods to help parts in 
  11317.              determining whether or not they can accept the dragged data; they 
  11318.              are called CanEmbed and CanIncorporate. 
  11319.  
  11320.       CanEmbed queries the registration manager for a part editor capable of 
  11321.       handling the content of the drag item. If a match is found, the 
  11322.       corresponding rendering mechanism and format pair will be saved in the 
  11323.       drag item storage unit (under the the kODSelectedRMF value of the 
  11324.       kODPropContents property) to be used later for rendering in the event a 
  11325.       drop ocurrs in this facet. This method should be used by container parts. 
  11326.  
  11327.       CanIncorporate determines if the drag item content matches a specific 
  11328.       kind. Parts should call this method for the kinds they support. As for 
  11329.       CanEmbed, if a match is found, the corresponding rendering mechanism and 
  11330.       format pair will be saved in the drag item storage unit. 
  11331.  
  11332.       If your part cannot accept all the dragged items, you should not accept a 
  11333.       drop at all. 
  11334.  
  11335.    2. If your part can accept a drop, provide the appropriate feedback to the 
  11336.       user, such as adorning its frame border or changing the cursor 
  11337.       appearance; Otherwise, take no action. 
  11338.  
  11339.       When the user initiates a drag from within your frame, you should not 
  11340.       display destination feedback as long as the mouse pointer has not yet 
  11341.       left your frame, although you should provide feedback if the mouse 
  11342.       pointer returns to your frame after having left it. 
  11343.  
  11344.       You can draw the drag feedback on your own, or with the help of 
  11345.       platform-specific services. 
  11346.  
  11347.    3. Examine the current state of the user's system, if desired, to obtain 
  11348.       information such as whether or not a modifier key has been pressed since 
  11349.       a drag was initiated. If you return kODFalse from this method, OpenDoc 
  11350.       assumes you cannot accept a drop and will not subsequently call your 
  11351.       DragWithin or Drop methods as long as the mouse pointer remains in this 
  11352.       facet. 
  11353.  
  11354.  
  11355. ΓòÉΓòÉΓòÉ 10.5.3.2. While within a Part's Facet ΓòÉΓòÉΓòÉ
  11356.  
  11357. OpenDoc calls the potential destination part's DragWithin method continuously 
  11358. while the mouse pointer remains inside the facet: 
  11359.  
  11360. ODDragResult DragWithin(in ODDragItemIterator dragInfo,
  11361.                                     in ODFacet facet,
  11362.                                     in ODPoint where);
  11363.  
  11364. In response, the part can do any desired processing inside of its display. For 
  11365. example, if a part allows objects to be dropped only in individual hot spots, 
  11366. it may change its feedback based on mouse-pointer location. 
  11367.  
  11368. Calls to a part's DragWithin method also give the part an additional chance to 
  11369. examine the state of the user's system. For example, the part may want to find 
  11370. out whether or not a modifier key has been pressed while a drag is in progress. 
  11371. If you return kODFalse from this method, OpenDoc assumes you no longer wish to 
  11372. accept a drop in this facet. It will not make additional calls to your 
  11373. DragWithin method, and will not call your Drop method, as long as the mouse 
  11374. pointer remains in this facet. 
  11375.  
  11376.  
  11377. ΓòÉΓòÉΓòÉ 10.5.3.3. On Leaving a Part's Facet ΓòÉΓòÉΓòÉ
  11378.  
  11379. OpenDoc calls the DragLeave method of a potential destination part when the 
  11380. mouse pointer leaves a droppable facet: 
  11381.  
  11382. ODDragResult DragLeave (in ODFacet facet,
  11383.                         in ODPoint where);
  11384.  
  11385. In response, the part might remove the adornment on its frame or restore the 
  11386. cursor appearance to its original form. 
  11387.  
  11388.  
  11389. ΓòÉΓòÉΓòÉ 10.5.4. Dropping ΓòÉΓòÉΓòÉ
  11390.  
  11391. If the user releases the mouse button while the pointer is within a facet, 
  11392. OpenDoc calls the Drop method of the facet's part. This is the interface to the 
  11393. Drop method: 
  11394.  
  11395. ODDragResult Drop (in ODDragItemIterator dropInfo,
  11396.                    in ODFacet facet,
  11397.                    in ODPoint where);
  11398.  
  11399. The potential destination part then decides whether it can receive the dragged 
  11400. object. If it accepts the data, it either incorporates it (see Incorporating 
  11401. Intrinsic Content) or embeds it (see Embedding a Single Part). 
  11402.  
  11403.  
  11404. ΓòÉΓòÉΓòÉ 10.5.4.1. Drag Attributes and the Drop Method ΓòÉΓòÉΓòÉ
  11405.  
  11406. The OpenDoc human interface guidelines specify when a drop should be considered 
  11407. a move, and when it should be a copy. The destination part can inspect the drag 
  11408. attributes (by calling the GetDragAttributes method of the drag and drop 
  11409. object) to determine how to handle the drop. Drag attributes are bit flags, and 
  11410. more than one can be set at a time. These are the possible drag attributes for 
  11411. a drop: 
  11412.  
  11413.  Constant                      Description 
  11414.  
  11415.  koDDragIsInSourceFrame        The item being dragged has not yet left the 
  11416.                                source frame of the drag. 
  11417.  
  11418.  koDDragIsInSourcePart         The item being dragged has not yet left the 
  11419.                                source part of the drag. 
  11420.  
  11421.  kODDropIsInSourceFrame        The drop is occurring in the source frame of the 
  11422.                                drag. 
  11423.  
  11424.  kODDropIsInSourcePart         The drop is occurring in the part displayed in 
  11425.                                the source frame of the drag (though not 
  11426.                                necessarily in the source frame itself). 
  11427.  
  11428.  kODDropIsMove                 This drag and drop operation is a move. 
  11429.  
  11430.  kODDropIsCopy                 This drag and drop operation is a copy. 
  11431.  
  11432.  kODDropIsLink                 This drag and drop operation is a link (OS/2 
  11433.                                implementation only). 
  11434.  
  11435.  kODDropIsPasteAs              The destination part should display the Paste As 
  11436.                                dialog box (the user has held down the Command 
  11437.                                key while dropping). 
  11438.  
  11439.  Your Drop method might follow steps similar to these: 
  11440.  
  11441.    1. Use the ODDragItemIterator passed to you to determine whether you can 
  11442.       handle the drop, as described in On Entering a Part's Facet. (Or you 
  11443.       could set a "can-drop" flag in DragEnter or DragWithin that you inspect 
  11444.       at this point.) 
  11445.  
  11446.    2. Determine the drag attributes, to see, for example, whether this is a 
  11447.       move or a copy and whether or not to put up the Paste As dialog box. 
  11448.  
  11449.    3. (OS/2 implementation only) Focus the drag item storage unit on the 
  11450.       kODDragitem value of the kODPropContents property and create a storage 
  11451.       unit view. Then call the ODDragAndDrop object GetDataFromDragManager to 
  11452.       render the data. Upon successful completion,this method will place the 
  11453.       rendered data in the returned storage unit. 
  11454.  
  11455.    4. If the drag attribute kODDropIsPasteAs is set (that is, if the Command 
  11456.       key was held down when the drop occurred), take these steps before 
  11457.       reading from the drag and drop object: 
  11458.  
  11459.           Call the ShowPasteAsDialog method of the drag and drop object to 
  11460.            display a Paste As dialog box (see the figure in Handling the Paste 
  11461.            As Dialog Box). 
  11462.  
  11463.           If the ShowPasteAsDialog method returns a result of true, the user 
  11464.            has pressed the OK button; use the results of the interaction 
  11465.            (passed back as a structure of type ODPasteAsResult) to determine 
  11466.            what action to take. Handling the Paste As Dialog Box lists the 
  11467.            kinds of pasting that the user can specify. 
  11468.  
  11469.    5. Depending on the nature of the data and the user's instructions, you may 
  11470.       either incorporate the data or embed it, you may first translate it, and 
  11471.       you may create a link to its source. 
  11472.  
  11473.           If you are creating a link, follow the steps in Creating a Link at 
  11474.            the Destination. Take into account the automatic/manual update 
  11475.            setting, as well as the other Paste As settings chosen by the user. 
  11476.  
  11477.           If you are translating but not creating a link, follow the steps in 
  11478.            Translating Before Incorporating or Embedding. 
  11479.  
  11480.           If you are simply incorporating the data, follow the steps in 
  11481.            Incorporating Intrinsic Content. 
  11482.  
  11483.           If you are simply embedding the data, follow the steps in Embedding 
  11484.            a Single Part. 
  11485.  
  11486.       In all of these cases, you initially read the data from the drag and drop 
  11487.       object, and you specify the following kinds of clone transactions: 
  11488.  
  11489.           If it is a move (the drag attribute kODDropIsMove is set),  specify 
  11490.            a clone transaction of kODCloneDropMove. 
  11491.  
  11492.           If it is a copy (the drag attribute kODDropIsCopy is set), specify a 
  11493.            clone transaction of kODCloneDropCopy. Note that, as destination 
  11494.            part, you can override a drag that is a move and force it to be a 
  11495.            copy. You cannot, however, override a copy and force it to be a 
  11496.            move. 
  11497.  
  11498.    6. Add a single action to the action history (see Adding an Action to the 
  11499.       Undo History) so that the user can undo the drop. Adding Two-Stage 
  11500.       Actions describes why this action must be a single-stage action. 
  11501.  
  11502.    7. If it is not already active, activate the frame in which the drop 
  11503.       occurred, and select the dropped content. When it completes, your Drop 
  11504.       method should return an appropriate result (of type ODDropResult), such 
  11505.       as kODDropCopy, kODDropMove, or kODDropFail. OpenDoc in turn passes that 
  11506.       information on to the source part; see Completion of StartDrag. 
  11507.  
  11508.  
  11509. ΓòÉΓòÉΓòÉ 10.5.4.2. Accepting Non-OpenDoc Data ΓòÉΓòÉΓòÉ
  11510.  
  11511. When your part's Drop method is called, it is passed a drag-item iterator 
  11512. (class ODDragItemIterator), so that you can access all drag items in the drag 
  11513. and drop object. If OpenDoc data has been dragged, there is only one drag item 
  11514. in the object, but if the data comes from outside of OpenDoc, there may be more 
  11515. than one item. It is the responsibility of the destination part to iterate 
  11516. through all the drag items to find out whether it can accept the drop. 
  11517.  
  11518. You can examine the contents property of the storage unit of each dragged item 
  11519. to determine the kind of data it consists of. If you can read data of that 
  11520. type, you can incorporate it into your part. Otherwise, you may be able to 
  11521. embed it as a separate part. 
  11522.  
  11523.      To access a file whose data you intend to incorporate, you can obtain the 
  11524.       item's HFSFlavor structure from a a value in the contents property of the 
  11525.       item's storage unit. You can then use that information to make 
  11526.       file-system-specific calls to open the file and process its contents into 
  11527.       your part. 
  11528.  
  11529.      To embed dropped non-OpenDoc data as a part, you treat it just as you 
  11530.       would OpenDoc data. You follow the procedures described in Embedding a 
  11531.       Single Part, specifying a cloning operation of kODClonePaste or 
  11532.       kODCloneDropMove for the content storage unit of the dropped data. 
  11533.       OpenDoc locates and binds a part editor to the data. That part editor 
  11534.       itself then must obtain the item's HFSFlavor structure, access the file, 
  11535.       and incorporate its contents. 
  11536.  
  11537.  
  11538. ΓòÉΓòÉΓòÉ 10.5.4.3. Completion of StartDrag ΓòÉΓòÉΓòÉ
  11539.  
  11540. If your part is the source part of this drag, your call to the drag and drop 
  11541. object's StartDrag method completes after the destination's Drop method 
  11542. completes. You can now, based on the return value of StartDrag, confirm whether 
  11543. the operation was a move or a copy or whether it failed. If it was a move, take 
  11544. these steps: 
  11545.  
  11546.    1. Add an end action to the undo action history (see Adding Two-Stage 
  11547.       Actions), so that the user will be able to undo the entire transaction, 
  11548.       from initiating the drag to dropping the data. Note any applicable 
  11549.       special considerations given in Handling Cut Data. 
  11550.  
  11551.    2. Delete the dragged content from your part. Regardless of whether it was a 
  11552.       move or a copy, you should call your source frame's SetDragging method 
  11553.       once again, this time passing it a value of kODFalse to notify OpenDoc 
  11554.       that the frame can once more be a drop target. 
  11555.  
  11556.       Asynchronous drag and drop 
  11557.       For future compatibility, OpenDoc provides the ODPart method 
  11558.       DropCompleted, which is called to notify the source part of the 
  11559.       completion of a drag that it initiated, and provides the same drop 
  11560.       results that StartDrag returns for a synchronous drag. 
  11561.  
  11562.  
  11563. ΓòÉΓòÉΓòÉ 10.6. Linking ΓòÉΓòÉΓòÉ
  11564.  
  11565. Linking is a mechanism for placing information into a part and allowing that 
  11566. information to be updated, based on changes to source information in another 
  11567. part or document. 
  11568.  
  11569. Linking support in OpenDoc is a combination of event-handling code and storage 
  11570. code. It includes a set of notification calls that keep the transferred data 
  11571. synchronized with its source. 
  11572.  
  11573. Some aspects of linking are closely related to the other data-transfer objects. 
  11574. Link specifications, used in writing data to the clipboard or drag and drop 
  11575. object, are described in Link Specification. The interactions between cutting 
  11576. and pasting and the preservation of link-related objects are listed in Transfer 
  11577. Rules for Links and Link Sources. 
  11578.  
  11579.  
  11580. ΓòÉΓòÉΓòÉ 10.6.1. Link Concepts ΓòÉΓòÉΓòÉ
  11581.  
  11582. Linking requires the cooperation of one or two parts with several 
  11583. linking-related objects. The following figure is a schematic illustration of 
  11584. the objects and data involved in linking. The figure shows a link between two 
  11585. separate parts (which can be in the same document or in different documents), 
  11586. although links can also occur within a single part. 
  11587.  
  11588. The user creates a link by requesting it during a paste or drop operation. The 
  11589. part that contains the source of the information to be linked is called the 
  11590. source part. The content that is to be copied and sent to another part is 
  11591. called the source content or source. The source part creates an object, the 
  11592. link source, that contains a copy of the source data; that copy is stored in 
  11593. the same document as the source part. 
  11594.  
  11595. The part that contains the destination of the information to be linked is 
  11596. called the destination part. The content that is actually copied into the link 
  11597. destination is called the destination content or destination. The destination 
  11598. part's draft object creates an object, the link, that is stored in the same 
  11599. document as the destination part. 
  11600.  
  11601. The link-source object contains references to all link objects for which it is 
  11602. the source. The user is free to edit the source of a link; when a change occurs 
  11603. in the source part and the destination part needs to be updated, the source 
  11604. part copies the source content into the link-source object. The destination 
  11605. part then copies the content from the link object into the destination itself. 
  11606.  
  11607. OpenDoc links are unidirectional; changes are propagated from the source to the 
  11608. destination only. You should not permit users to edit any link destinations 
  11609. that you maintain; such edits would be overwritten when the link is updated. 
  11610.  
  11611. Whether it contains the source or the destination of a link, your part is 
  11612. responsible for defining the exact content that constitutes the linked data and 
  11613. for knowing what visual area it covers in your part's display. Linked data, 
  11614. whether source or destination, is part of your own content; you store and 
  11615. manipulate it according to your own content model and under your own control. 
  11616.  
  11617.  
  11618. ΓòÉΓòÉΓòÉ 10.6.1.1. Link Update ID ΓòÉΓòÉΓòÉ
  11619.  
  11620. Each piece of linked content-that is, every region of content at the source or 
  11621. at the destination of a link-must have an associated update ID. The source part 
  11622. determines the update ID associated with the link and updates the ID each time 
  11623. the source changes. The destination part stores the update ID of the link that 
  11624. was current at the time the destination was last updated through the link. 
  11625.  
  11626. Whenever the content in your part changes-for instance, in response to a series 
  11627. of keyboard events-you need to assign a new update ID to all link sources 
  11628. directly affected by that change. Note that all link sources affected by a 
  11629. given change must have the same update ID. You obtain a new update ID by 
  11630. calling the session object's UniqueChangeID method. 
  11631.  
  11632. When you update a link source, you can save the update ID in your source 
  11633. content and use it later to determine whether your source content and the 
  11634. content of the link-source object are identical. 
  11635.  
  11636. A circular link or recursive link can occur when changes to a link's 
  11637. destination directly or indirectly affect its source. To avoid endless 
  11638. recursive updates, it is important that your part take these steps: 
  11639.  
  11640.      Whenever your part updates a link destination that also is contained in a 
  11641.       link source for which automatic updating is specified, it must propagate 
  11642.       the update ID passed to it. Your part must update the affected source 
  11643.       with the update ID passed to the destination, rather than calling 
  11644.       UniqueChangeID. 
  11645.  
  11646.       It is possible that your part containing the link destination is embedded 
  11647.       in the link source content of another part. In that case, you must call 
  11648.       your frame's content updated method so that the part owning the link 
  11649.       source can be notified that your content has changed and be given the 
  11650.       update ID of the change. 
  11651.  
  11652.      Whenever your part updates a link source manually (on explicit user 
  11653.       instruction), it should not propagate an existing update ID. It should 
  11654.       always call UniqueChangeID to get a new update ID. 
  11655.  
  11656.  
  11657. ΓòÉΓòÉΓòÉ 10.6.1.2. Automatic and Manual Propagation of Updates ΓòÉΓòÉΓòÉ
  11658.  
  11659. OpenDoc informs destination parts when the sources of their links have been 
  11660. updated, either automatically or manually (when instructed to do so by the user 
  11661. or part). The user selects whether updating is to be automatic or manual, 
  11662. either in the Paste As dialog box when the link is first created or in the Link 
  11663. Destination Info dialog box after the link exists. 
  11664.  
  11665. The user initiates a manual update by pressing a button in Link Destination 
  11666. info dialog box. Pressing the Update Now button in the Link Destination Info 
  11667. dialog box updates only the link destination from the link object. 
  11668.  
  11669. To be notified automatically of changes to the source of a link, your 
  11670. destination part calls the link object's RegisterDependent method, supplying it 
  11671. with the update ID of the last content it read from the link. Each link object 
  11672. maintains a private registry of dependent parts and calls their LinkUpdated 
  11673. methods whenever the link source changes. Your part should respond to this 
  11674. method call by updating its destination content from the link object, as 
  11675. described in Updating a Link at the Destination. 
  11676.  
  11677. If updating is to be automatic, your part should register for update 
  11678. notification when it first creates the link (passing an update ID of 
  11679. kODUnknownUpdate), and whenever your part reads itself from storage. Be sure 
  11680. you are prepared to receive a notification when you call RegisterDependent, 
  11681. because your LinkUpdated method may be called before RegisterDependent returns. 
  11682. You can unregister and re-register as desired, but be careful not to register 
  11683. more than once at a time with the same link. 
  11684.  
  11685. If your draft permissions are read-only, you should not register for update 
  11686. notification . Even if you do register, you do not receive notifications. 
  11687.  
  11688.  
  11689. ΓòÉΓòÉΓòÉ 10.6.1.3. Automatic and Manual Updating of Link Source Content ΓòÉΓòÉΓòÉ
  11690.  
  11691. OpenDoc allows owners of source parts to either specify that changes to link 
  11692. source content become visible as soon as the content changes (automatic), or 
  11693. only when explicitly requested (manually) by the source part. The source part 
  11694. calls the IsAutoUpdate method to determine the update mode. In the automatic 
  11695. mode (default), the part should update the Link Source Content Storage Unit 
  11696. (CSU) as soon as possible after the editing operation, which changed the 
  11697. content completely. In the manual mode, the parts should suppress updating the 
  11698. Link Source Content Storage Unit until the part's UpdateFrameLinkSource method 
  11699. is called. 
  11700.  
  11701.  
  11702. ΓòÉΓòÉΓòÉ 10.6.1.4. Frame Link Status ΓòÉΓòÉΓòÉ
  11703.  
  11704. All frames have a link status that describes the frame's participation in 
  11705. links. Parts are responsible for setting the link status of all frames that 
  11706. they embed; the link status indicates whether the frame is in the source of a 
  11707. link, in the destination of a link, or not involved in any link, or both. Parts 
  11708. can use this information to decide whether to allow editing of linked data, and 
  11709. whether to allow creation of a link within an existing link; see the second 
  11710. table in Creating a Link that Includes Already-Linked Content for a list of the 
  11711. possible combinations. 
  11712.  
  11713.  
  11714. ΓòÉΓòÉΓòÉ 10.6.1.4.1. When to Change Link Status ΓòÉΓòÉΓòÉ
  11715.  
  11716.  
  11717. In general, any time that you create a link involving an embedded frame or add 
  11718. an embedded frame to your part, you should set the frame's link status. 
  11719.  
  11720.      When your part creates a link source, it should call the ChangeLinkStatus 
  11721.       method of each of the embedded frames within the content area of the link 
  11722.       source, passing it the value kODInLinkSource. 
  11723.  
  11724.      If you add embedded frames to a link source, call ChangeLinkStatus for 
  11725.       each new frame, passing it the value kODInLinkSource. 
  11726.  
  11727.      If pasting and creating a link destination in your part involves adding 
  11728.       embedded frames at the destination, call ChangeLinkStatus for each new 
  11729.       frame, passing it the value kODInLinkDestination. (This may occur either 
  11730.       while performing a paste-with-link on embedded frames, or while updating 
  11731.       a link destination that includes embedded frames.) 
  11732.  
  11733.      Any time you embed a frame outside of any link source or destination that 
  11734.       you maintain, set its status to kODNotInLink. 
  11735.  
  11736.      If you break a link but keep the embedded data at the source or 
  11737.       destination, set the status of each frame that was formerly linked to 
  11738.       kODNotInLink. 
  11739.  
  11740.      Destinations take precedence over sources. If you have an embedded frame 
  11741.       that is contained in a link destination that you maintain, and that 
  11742.       destination is itself contained in a link source that you maintain, set 
  11743.       the frame's status to kODInLinkDestination. If you later break that link 
  11744.       destination (but not its enclosing link source), set the frame's status 
  11745.       to kODInLinkSource rather than kODNotInLink. 
  11746.  
  11747.  The ChangeLinkStatus method changes the value of the frame's link status, if 
  11748.  necessary, and calls the LinkStatusChanged method of the frame's part, so that 
  11749.  the part can change the link status of any of its own embedded frames. 
  11750.  
  11751.  When you set the link status of a frame in any of these situations, you need 
  11752.  to take into account only the links that your part maintains; you can ignore 
  11753.  your own display frame's link status. OpenDoc automatically adjusts the link 
  11754.  status of frames that you embed to account for your display frame's status. 
  11755.  
  11756.  You can examine the link status of a frame by calling its GetLinkStatus 
  11757.  method. 
  11758.  
  11759.  
  11760. ΓòÉΓòÉΓòÉ 10.6.1.4.2. The LinkStatusChanged Method of your Part Editor ΓòÉΓòÉΓòÉ
  11761.  
  11762.  
  11763. Your own part's LinkStatusChanged method is called by the ChangeLinkStatus 
  11764. method of any of your display frames, whenever the display frame's link status 
  11765. is changed. This is its interface: 
  11766.  
  11767. void LinkStatusChanged (in ODFrame frame);
  11768.  
  11769. Your implementation of LinkStatusChanged should iterate through all of your 
  11770. part's embedded frames, calling each one's ChangeLinkStatus method: 
  11771.  
  11772.      The link status of embedded frames that are already part of links that 
  11773.       you maintain cannot change; sources will remain sources, and destinations 
  11774.       will remain destinations. Therefore, you do not need to call 
  11775.       ChangeLinkStatus for them. 
  11776.  
  11777.      For embedded frames not involved in links that you maintain, you can set 
  11778.       their link status according to your display frame's link status. However, 
  11779.       you can also just set their link status to kODNotInLink, and let OpenDoc 
  11780.       adjust their link status if necessary. 
  11781.  
  11782.  Making this call on all of your embedded frames allows them in turn to call 
  11783.  their parts' LinkStatusChanged method, to change the link status of more 
  11784.  deeply embedded frames, and so on. 
  11785.  
  11786.  Note that you do not need to call the ChangeLinkStatus method of any embedded 
  11787.  frames already involved in links that you manage, because their status will 
  11788.  not change. 
  11789.  
  11790.  
  11791. ΓòÉΓòÉΓòÉ 10.6.1.5. Content Changes in Embedded Frames ΓòÉΓòÉΓòÉ
  11792.  
  11793. Because linked content can contain embedded frames, there must be a way for an 
  11794. embedded part to inform its containing part that its content has changed, so 
  11795. that the link can be updated. 
  11796.  
  11797.  
  11798. ΓòÉΓòÉΓòÉ 10.6.1.5.1. The ContentUpdated Method ΓòÉΓòÉΓòÉ
  11799.  
  11800.  
  11801. Any time a content change occurs in one of your part's display frames, you 
  11802. should follow the procedures described in Making Content Changes Known Part of 
  11803. the procedure is to call the frame' ContentUpdated method. The ContentUpdated 
  11804. method then calls the EmbeddedFrameUpdated method of your part's containing 
  11805. part. The containing part then knows that the content of one of its embedded 
  11806. frames has changed. If your display frame is involved in a link source 
  11807. maintained by your part's containing part, the containing part can then choose 
  11808. to update the link-source object with the new data. 
  11809.  
  11810. (This ContentUpdated method is unrelated to the ContentUpdated method of 
  11811. ODLinkSource, discussed in Updating a Link at the Source). 
  11812.  
  11813.  
  11814. ΓòÉΓòÉΓòÉ 10.6.1.5.2. The EmbeddedFrameUpdated Method of your Part Editor ΓòÉΓòÉΓòÉ
  11815.  
  11816.  
  11817. Your part's EmbeddedFrameUpdated method is called by the ContentUpdated method 
  11818. of any of your embedded frames, whenever the content of the frame's part has 
  11819. changed. This is its interface: 
  11820.  
  11821. void EmbeddedFrameUpdated(in ODFrame frame,
  11822.                           in ODUpdateID change);
  11823.  
  11824. The method is passed a reference to the embedded frame and an update ID 
  11825. identifying the modification. You should respond by saving the Update ID and 
  11826. updating any link-source objects that you maintain that involve that frame (and 
  11827. whose updating is automatic). When updating the link source, pass it the Update 
  11828. ID that you received in the call to this method. 
  11829.  
  11830. Your EmbeddedFrameUpdated method should also call the ContentUpdated method of 
  11831. your own display frames that contain the embedded frame, so that the change is 
  11832. propagated upward throughout the embedding hierarchy. 
  11833.  
  11834.  
  11835. ΓòÉΓòÉΓòÉ 10.6.1.6. Link Borders ΓòÉΓòÉΓòÉ
  11836.  
  11837. If your part contains the source or destination of a link, you are responsible 
  11838. for drawing an appropriate border around the linked content area when requested 
  11839. to do so. 
  11840.  
  11841. Whenever you draw your part's content in a facet, first call the 
  11842. ShouldShowLinks method of the facet's window. If ShouldShowLinks returns 
  11843. kODTrue, draw borders around any link sources and destinations. 
  11844.  
  11845.  
  11846. ΓòÉΓòÉΓòÉ 10.6.1.7. Link Info ΓòÉΓòÉΓòÉ
  11847.  
  11848. The link info structure (type ODLinkInfo) contains fields that hold information 
  11849. about the nature of a link, such as the part kind of its intrinsic data, its 
  11850. creation date, and its update ID. Your part should allocate and maintain a link 
  11851. info structure for every link destination that it contains. 
  11852.  
  11853. Here is the structure's definition: 
  11854.  
  11855. struct ODLinkInfo
  11856. {
  11857.         ODType                          kind;
  11858.         ODTime                          creationTime;
  11859.         ODTime                          changeTime;
  11860.         ODUpdateID                      change;
  11861.         ODBoolean                       autoUpdate;
  11862. };
  11863.  
  11864.  
  11865. ΓòÉΓòÉΓòÉ 10.6.1.8. Linking and Undo ΓòÉΓòÉΓòÉ
  11866.  
  11867. Just as the basic data-transfer actions (cutting, pasting, and dropping) should 
  11868. be undoable, so should their variations that involve linked data. The user 
  11869. should be able to undo (and redo) any of these actions: 
  11870.  
  11871.      Pasting or dropping content and creating a link to its source. 
  11872.  
  11873.      Pasting or dropping content that contains existing linked data. 
  11874.  
  11875.      Deleting or cutting content that includes one or more link sources or 
  11876.       destinations. 
  11877.  
  11878.      Breaking a link at its source or its destination (through the Link Info 
  11879.       dialog boxes). 
  11880.  
  11881.  When a link is created, the part receiving the data and creating the link 
  11882.  destination adds a begin action and end action to the undo action history (see 
  11883.  Adding Two-Stage Actions), whereas the source part adds a single action to the 
  11884.  history when it creates the link source. 
  11885.  
  11886.  Edits to the source content of a link must also-like any edits to the content 
  11887.  of your part-be undoable. However, updating a link source object from its 
  11888.  source content does not need to be an undoable action: 
  11889.  
  11890.      If the link source is updated manually, undoing or redoing changes to 
  11891.       source content has no effect on the link source object. Whenever an 
  11892.       update occurs, the link source object simply reflects the current state 
  11893.       of the source content. 
  11894.  
  11895.      If the link source is updated automatically, changes to source content 
  11896.       accomplished through an undo or redo action should cause you to update 
  11897.       the link source as usual. (Be sure to use the update ID associated with 
  11898.       the restored or redone content when updating.) 
  11899.  
  11900.  Likewise, updating the destination content of a link from its link object does 
  11901.  not need to be an undoable action: 
  11902.  
  11903.      Editing the content at the destination of a link is not generally 
  11904.       permitted. Because undoing or redoing an update to a destination would 
  11905.       constitute editing the destination, you should never put the update 
  11906.       action in the Undo or Redo stacks. 
  11907.  
  11908.      You can, however, allow changes to the destination content that can be 
  11909.       maintained across a link update, such as a style applied to the entire 
  11910.       destination. Such non-editing changes can be undoable. 
  11911.  
  11912.  When you delete or cut content that includes a link source or destination, or 
  11913.  when you break a link, follow the procedures outlined in Breaking and Cutting 
  11914.  Links to make sure that you can undo the actions. 
  11915.  
  11916.  
  11917. ΓòÉΓòÉΓòÉ 10.6.2. Manipulating Links ΓòÉΓòÉΓòÉ
  11918.  
  11919. This section describes some of the basic procedures you follow in creating 
  11920. links, reading and writing linked data, and updating links. 
  11921.  
  11922. Related information is described as part of general data-transfer 
  11923. considerations earlier in this chapter. Creating and removing link 
  11924. specifications are described in Link Specification and Removing a Link 
  11925. Specification from the Clipboard. 
  11926.  
  11927. Both the source and destination parts of a link, or even separate destinations 
  11928. of a single source, may attempt to access linked data simultaneously. 
  11929. Therefore, many methods of the classes ODLinkSource and ODLink require that you 
  11930. provide a key in order to access the storage unit containing the content of a 
  11931. link. You obtain the key by first calling the Lock method of the link-source 
  11932. object or link object involved. 
  11933.  
  11934.  
  11935. ΓòÉΓòÉΓòÉ 10.6.2.1. Creating a Link at the Destination ΓòÉΓòÉΓòÉ
  11936.  
  11937. A link is created when the user decides-using the Paste As dialog box-to link 
  11938. rather than statically transfer data while performing a paste. The destination 
  11939. part-the part receiving the paste or drop-retrieves the link specification from 
  11940. the clipboard or drag and drop object and calls the part's destination draft's 
  11941. AcquireLink method. The source part's draft, in turn, calls the CreateLink 
  11942. method of the source part (the part that placed the data in the clipboard or 
  11943. drag and drop object). 
  11944.  
  11945. If your part is the destination part that creates a link to pasted data from 
  11946. the data's source, you can use the following steps. It is assumed that you have 
  11947. previously called the ShowPasteAsDialog method of the clipboard or drag and 
  11948. drop object (see Handling the Paste As Dialog Box), and are ready to act on the 
  11949. results of the Paste As dialog box. For clipboard transfer, this means that you 
  11950. have already acquired the clipboard focus (see Acquiring and Relinquishing the 
  11951. Clipboard Focus). 
  11952.  
  11953.    1. Focus the clipboard or drag and drop storage unit on the link 
  11954.       specification it contains. Use your draft's CreateLinkSpec method to 
  11955.       instantiate the link specification, with the destination part as the 
  11956.       part, and null for the data. Then call the link specification's 
  11957.       ReadLinkSpec method to have it read itself from the storage unit. 
  11958.  
  11959.    2. Pass the link specification to your draft's AcquireLink method to 
  11960.       construct the link object from the link specification with 0 as the ID. 
  11961.  
  11962.    3. Create a link-info structure (type ODLinkInfo) to associate with the link 
  11963.       destination, as described in Link Info. Initialize its update ID (to 
  11964.       kODUnknownUpdate), set its creation time to the current time, set its 
  11965.       modification time to the modification time of the link object, and give 
  11966.       it a part kind and auto-update setting based on the results of the Paste 
  11967.       As dialog box. 
  11968.  
  11969.    4. Add this link object to whatever private list of link destinations you 
  11970.       maintain. Store the information you need to associate this link object 
  11971.       with its link-info structure and with the link-destination content in 
  11972.       your part. If you have translated the data that now makes up your link 
  11973.       destination, you also need to record the part kind that it was translated 
  11974.       from. You will have to translate the data again for each subsequent 
  11975.       update to the link, and you will need to know which part kind in the data 
  11976.       to read and translate. 
  11977.  
  11978.    5. This link-creation procedure should be undoable. Do this: 
  11979.  
  11980.           If the data transfer for this link is a drop, add a single action to 
  11981.            the undo action history; if the user undoes the drop, this link will 
  11982.            be deleted also. 
  11983.  
  11984.           If the data transfer for this link is a paste from the clipboard, 
  11985.            add a begin action to start a two-stage transaction. That way, if 
  11986.            the user decides to reverse the paste, both the paste and this link 
  11987.            creation will be undone together. 
  11988.  
  11989.    6. If the user specified auto-updating in the Paste As dialog box, call the 
  11990.       link's RegisterDependent method. Otherwise, manually update the link at 
  11991.       this time by performing whatever actions your part's LinkUpdated method 
  11992.       would perform (see Updating a Link at the Destination). 
  11993.  
  11994.    7. If the data transfer for this link was a paste from the clipboard, add an 
  11995.       end action to the action history at this time, to complete the two-stage 
  11996.       action started in step 5. 
  11997.  
  11998.    8. Call the ChangeLinkStatus method of any of your part's newly embedded 
  11999.       frames that are within the linked content area, passing them the value 
  12000.       kODInLinkDestination. 
  12001.  
  12002.  Never read the link content from the storage unit of the clipboard or drag and 
  12003.  drop object when creating the link; always read link content from the link 
  12004.  object's storage unit. 
  12005.  
  12006.  Every time the link is updated, your part (the destination part) must discard 
  12007.  the data in the link destination and read it again from the link object. That 
  12008.  can mean discarding embedded parts and creating them anew from the updated 
  12009.  link content. See Updating a Link at the Destination for details. 
  12010.  
  12011.  Your destination part must be able to draw a border around the link content 
  12012.  area when asked to do so, as described in Link Borders. Parts embedded in 
  12013.  linked data are not involved in the maintenance of the link; even in the case 
  12014.  of a link destination that consists of a single embedded part, you draw the 
  12015.  link border around the embedded part's frame. 
  12016.  
  12017.  Note that only the draft should call CreateLink; if your part is a destination 
  12018.  part that needs a link to be created, you should call your draft's AcquireLink 
  12019.  method. 
  12020.  
  12021.  
  12022. ΓòÉΓòÉΓòÉ 10.6.2.2. Creating a Link at the Source ΓòÉΓòÉΓòÉ
  12023.  
  12024. When the user decides to create a link to data that your part placed on the 
  12025. clipboard or drag and drop object, the destination part's draft calls the 
  12026. CreateLink method of your part (the source part). The draft passes back the 
  12027. data of the link specification that your part originally wrote when it placed 
  12028. the data on the clipboard or drag and drop object. This is the interface to 
  12029. CreateLink: 
  12030.  
  12031. ODLinkSource CreateLink(in ODByteArray data);
  12032.  
  12033. When your source part's CreateLink method is called, the method should 
  12034. duplicate in a link-source object all of the content that your part originally 
  12035. wrote (or promised) to the clipboard or drag and drop object. 
  12036.  
  12037. In your source part's CreateLink method, you can follow these general steps: 
  12038.  
  12039.    1. Examine your own structures to see if the link source object already 
  12040.       exists. CreateLink may have been called as a consequence of another 
  12041.       destination being added to this link source, as described in Replacing 
  12042.       Link-Source Content in CreateLink. If the link source does exist, take 
  12043.       either of these steps: 
  12044.  
  12045.           If the link-source object contains data (or promises) for all part 
  12046.            kinds that you support, simply return the existing link source 
  12047.            object and take no further action. 
  12048.  
  12049.           If the link-source object does not contain a complete set of 
  12050.            promises or data, you need to write the remaining part kinds to it. 
  12051.            You can do that by updating the link source in a particular manner. 
  12052.            Skip to step 5. 
  12053.  
  12054.       If the link-source object does not yet exist, continue with step 2. 
  12055.  
  12056.    2. Create a link source object by calling your draft's CreateLinkSource 
  12057.       method. 
  12058.  
  12059.    3. Add this link-source object to whatever private list of link sources you 
  12060.       maintain. Store the update ID and any other information you need to 
  12061.       associate this link-source object with the link-source content in your 
  12062.       part. 
  12063.  
  12064.    4. Call the ChangeLinkStatus method of any of your part's embedded frames 
  12065.       that are within the linked content area, passing them the value 
  12066.       kODInLinkSource. 
  12067.  
  12068.    5. Update the link source. Follow the steps listed in Updating a Link at the 
  12069.       Source. 
  12070.  
  12071.    6. Creating a link source needs to be undoable. Add single action to the 
  12072.       undo action history so that you can remove the link source if the user 
  12073.       reverses its creation. 
  12074.  
  12075.    7. Unlock the link-source object. 
  12076.  
  12077.    8. Return a reference to the link-source object as the method result. 
  12078.  
  12079.  
  12080. ΓòÉΓòÉΓòÉ 10.6.2.2.1. Replacing Link-Source Content in CreateLink ΓòÉΓòÉΓòÉ
  12081.  
  12082.  
  12083. If your part's CreateLink method is called and the link-specification data 
  12084. provided describes an existing link source that you maintain, your part must 
  12085. ensure that all content kinds that you support are available at the 
  12086. destination. If your part writes promises to the link source, you can ensure 
  12087. that all kinds are promised by replacing the current content in your 
  12088. link-source object. The procedure for replacing is similar to the regular 
  12089. updating procedure, except that you pass an existing update ID to the 
  12090. link-source object's Clear method, and you do not call the link-source object's 
  12091. ContentUpdated method. See Updating a Link at the Source for details. 
  12092.  
  12093.  
  12094. ΓòÉΓòÉΓòÉ 10.6.2.3. Updating a Link at the Destination ΓòÉΓòÉΓòÉ
  12095.  
  12096. When a source part updates its link-source object and (either automatically or 
  12097. manually) calls the object's ContentUpdated method, the link-source object 
  12098. notifies its associated link objects. Then, either immediately (for registered 
  12099. destinations) or later (for unregistered destinations), the LinkUpdated method 
  12100. is called. This is the interface to LinkUpdated: 
  12101.  
  12102. void LinkUpdated(in ODLink updatedLink,
  12103.                  in ODUpdateID change);
  12104.  
  12105. If your part contains the destination of a link, you can update the destination 
  12106. in your part's LinkUpdated method. Your part will receive such a call in 
  12107. response to the user's request for an update in the Link Destination Info 
  12108. dialog box. 
  12109.  
  12110. It is not always necessary to update immediately, during execution of 
  12111. LinkUpdated. For example, if the destination has scrolled offscreen but is 
  12112. still registered as a dependent of the source, updating does not need to occur 
  12113. until (and if) the destination scrolls back into view. Your part editor can, if 
  12114. desired, generally perform link updates as a background task. 
  12115.  
  12116. You can take the steps shown here to read the contents of a link object when 
  12117. updating your link destinations. 
  12118.  
  12119.    1. Call the link object's Lock method. 
  12120.  
  12121.    2. Access the link object's storage unit by calling its 
  12122.       GetContentStorageUnit method. (If GetContentStorageUnit returns the error 
  12123.       kODErrNoLinkContent, the last source update failed; do not update you 
  12124.       destination at this time.) 
  12125.  
  12126.       Incorporate and/or embed the updated destination data into your part from 
  12127.       the link object's contents property: 
  12128.  
  12129.           If you are incorporating the linked data, follow the steps in 
  12130.            Incorporating Intrinsic Content. 
  12131.  
  12132.           If you are embedding the linked data as a single part, follow the 
  12133.            steps in Embedding a Single Part. 
  12134.  
  12135.           If you are translating the linked data before incorporating or 
  12136.            embedding it, follow the steps in Translating Before Incorporating 
  12137.            or Embedding Use information you recorded when you first created the 
  12138.            link to know which part kind to read for translation. 
  12139.  
  12140.       In any of these cases, the only differences from other data-transfer 
  12141.       operations are that you call the Clone method of the link object's 
  12142.       storage unit's draft, you specify a clone transaction of 
  12143.       kODCloneFromLink, and you read from the link object's content storage 
  12144.       unit. 
  12145.  
  12146.       Note that you must discard any previously embedded parts and frames, 
  12147.       replacing them with new ones cloned from the link. You must connect the 
  12148.       frames to your frame hierarchy, create facets for the currently visible 
  12149.       ones, and change their link status by calling their ChangeLinkStatus 
  12150.       method, passing the value kODInLinkDestination. 
  12151.  
  12152.    3. Update the link-info structure for the link, with a new update ID and new 
  12153.       change time, obtained by calling the link's GetUpdateID and GetChangeTime 
  12154.       methods. 
  12155.  
  12156.    4. Unlock the link. 
  12157.  
  12158.    5. Inspect your part's private structures to see if this change has affected 
  12159.       the data of any link source in your part. (It can if this destination is 
  12160.       within a source.) If it has, modify the source as shown in Updating a 
  12161.       Link at the Source. 
  12162.  
  12163.  Note that, if your part maintains the destination of a link whose source has 
  12164.  been transferred from one part to another, the new source part might not write 
  12165.  its data using all of the same part kinds as the original source part. Your 
  12166.  part, therefore, might not be able to obtain updates in the format that it 
  12167.  expects. If that situation occurs, your part should read whatever part kind it 
  12168.  can, or else break the link. 
  12169.  
  12170.  Note:  This function is not supported for the current release of OpenDoc. 
  12171.  
  12172.  
  12173. ΓòÉΓòÉΓòÉ 10.6.2.4. Updating a Link at the Source ΓòÉΓòÉΓòÉ
  12174.  
  12175. The part maintaining the source of a link can rewrite values into the 
  12176. link-source object as necessary to update the link. If your part is the source 
  12177. part, take the steps listed here to update the contents of your link source (or 
  12178. to write it for the first time). The recommended procedure for updating a link 
  12179. source is to first remove all content from the link source by calling its Clear 
  12180. method. If the content written to a link includes embedded frames, your part 
  12181. should always call Clear before updating the link. By calling Clear, you ensure 
  12182. that all unneeded storage units are removed from the link, thereby saving space 
  12183. in your draft. 
  12184.  
  12185. Note that the Clear method deletes the contents property of the link source 
  12186. storage unit and all its data. You need to add a contents property and values 
  12187. back into the storage unit after calling Clear, just as if creating the link 
  12188. source from scratch. 
  12189.  
  12190. In summary, follow these steps: 
  12191.  
  12192.    1. Call the link-source object's Lock method, and then call its Clear 
  12193.       method. (If you are making a simple change that does not involve embedded 
  12194.       frames, you do not have to call Clear.) 
  12195.  
  12196.           If you are updating the link source due to content changes in your 
  12197.            part, or if you are writing to the link source for the first time, 
  12198.            or if this is a manual update, obtain a unique update ID and pass it 
  12199.            to Clear. 
  12200.  
  12201.           If you are updating the link source because of an update to a link 
  12202.            destination within your source content, pass the link destination's 
  12203.            existing update ID (the one that was passed to your LinkUpdated 
  12204.            method) to Clear. 
  12205.  
  12206.           If you are just adding new part kinds to an unchanged existing link 
  12207.            source, pass the link source's existing update ID to Clear. (You 
  12208.            must update the link if a new destination has been added and if the 
  12209.            link source does not have a complete set of promises for all part 
  12210.            kinds that you support.) 
  12211.  
  12212.    2. Access the link-source object's storage unit, create the contents 
  12213.       property and the appropriate values, and write your updated source data. 
  12214.       Write either data or a promise for all part kinds that you support, 
  12215.       including standard part kinds. If the shape or extent of the source 
  12216.       content has changed, update the frame shape annotation also. 
  12217.  
  12218.           If the data is intrinsic content-with or without one or more 
  12219.            embedded parts-follow the procedure given in Writing Intrinsic 
  12220.            Content. 
  12221.  
  12222.       Either way, specify a clone operation of kODCloneToLink. (If you are 
  12223.       writing simple data that does not involve storage unit references, you 
  12224.       can just write in the change instead of cloning.) You are encouraged to 
  12225.       write one or more promises instead of writing the actual data, to avoid 
  12226.       placing unused content into the link source. 
  12227.  
  12228.    3. If the content change originated in your source part, or if this is the 
  12229.       first time you are writing to the link, or if this is a manual update, 
  12230.       call the link-source object's ContentUpdated method and pass it a new 
  12231.       update ID (obtained from the session object's UniqueChangeID method), so 
  12232.       that it can in turn send update notifications to all its link 
  12233.       destinations. 
  12234.  
  12235.    4. If the content change occurred in a link destination contained within 
  12236.       your link source, call the link-source object's ContentUpdated method and 
  12237.       pass it the link destination's existing update ID (the one that was 
  12238.       passed to your LinkUpdated method), to avoid indefinite updating of 
  12239.       circular links. 
  12240.  
  12241.    5. If you are just adding new part kinds to an unchanged existing link 
  12242.       source, do not call ContentUpdated at all. 
  12243.  
  12244.    6. Unlock the link source. 
  12245.  
  12246.  In general, it is not necessary and not always desirable to update link-source 
  12247.  objects immediately in response to every content change. When content is 
  12248.  changing rapidly, such as during text entry, it is reasonable to wait for a 
  12249.  pause before updating any affected links. 
  12250.  
  12251.  
  12252. ΓòÉΓòÉΓòÉ 10.6.2.5. Writing Linked Content to Storage ΓòÉΓòÉΓòÉ
  12253.  
  12254. When your part writes itself to storage (see Writing a Part to Storage), or 
  12255. when it writes all or a portion of itself to a data-transfer object (see 
  12256. Writing to a Data-Transfer Object), it writes any linked data-whether source or 
  12257. destination-just as it would write any other content. In addition, however, it 
  12258. needs to write information for reconstructing the link objects and link source 
  12259. objects involved. 
  12260.  
  12261.  
  12262. ΓòÉΓòÉΓòÉ 10.6.2.5.1. Writing Links in Externalize ΓòÉΓòÉΓòÉ
  12263.  
  12264.  
  12265. The information with which you associate the link-source object or link object 
  12266. with a specific region of your content is not standardized; it depends on the 
  12267. nature of your content. However, for all links your Externalize method and your 
  12268. methods that write to data-transfer objects need to write persistent references 
  12269. to the objects themselves plus additional information. You should write the 
  12270. information in a format that is standard to your part kind; that way, any part 
  12271. editor that reads your part kind can reconstruct links from the stored data. 
  12272.  
  12273. For the source of a link, you need to include, in addition to a persistent 
  12274. reference to the storage unit of the ODLinkSource object, the update ID 
  12275. associated with the linked content. 
  12276.  
  12277. For the destination of a link, you need to include a persistent reference to 
  12278. the storage unit of the ODLink object, plus the information in the fields of 
  12279. the ODLinkInfo structure: the part kind, creation time, modification time, 
  12280. update ID, and auto-update setting of the linked data. Also, if your part has 
  12281. translated the linked data at the destination, you need to store the original 
  12282. part kind of the data (the kind before you translated it). 
  12283.  
  12284. Your part may also store extra information for convenience. For example, 
  12285. because your part needs to be able to draw a border around linked data, it may 
  12286. store link-border shapes in a private structure. 
  12287.  
  12288.  
  12289. ΓòÉΓòÉΓòÉ 10.6.2.5.2. Writing Links for Data Transfer ΓòÉΓòÉΓòÉ
  12290.  
  12291.  
  12292. If your part writes a single embedded frame (without surrounding intrinsic 
  12293. content) that is a link source or link destination to the clipboard or drag and 
  12294. drop object. Clone the link or link source object into the data-transfer 
  12295. object's draft and add a property with the name kODPropProxyContents to the 
  12296. clipboard or drag and drop storage unit. In that property write a value that 
  12297. references the link or link source object, as well as the link info fields and 
  12298. other necessary information. Any destination part that understands the proxy 
  12299. format can then recover the link. Note that, if you write linked content to a 
  12300. data-transfer object and the destination part does not support linking, the 
  12301. content may be transferred but the links will be broken. 
  12302.  
  12303.  
  12304. ΓòÉΓòÉΓòÉ 10.6.2.6. Reading Linked Content from Storage ΓòÉΓòÉΓòÉ
  12305.  
  12306. When your part reads itself into memory (see The InitPartFromStorage Method), 
  12307. it may need to read in link-source objects and link objects as well. Likewise, 
  12308. if the user pastes or drops information into your part that contains linked 
  12309. data that you can incorporate (see Incorporating Intrinsic Content), you can 
  12310. read that data and redirect the context of the links to be your own part. 
  12311.  
  12312. Because OpenDoc can eliminate links during data transfer (see,for example, the 
  12313. first table under Moving and Copying Links and Link Sources), you must perform 
  12314. the following two tasks when reading in data that includes links: 
  12315.  
  12316.      Before you attempt to read in a link-related object, you must ensure that 
  12317.       your persistent reference to it is valid. 
  12318.  
  12319.      For every link-source object that you read in, you must ensure that your 
  12320.       part is assigned as its source. The original source of the link may have 
  12321.       been in another part, if the source content has been moved or copied. 
  12322.  
  12323.  
  12324. ΓòÉΓòÉΓòÉ 10.6.2.6.1. Reading Links in InitPartFromStorage ΓòÉΓòÉΓòÉ
  12325.  
  12326.  
  12327. Here are the steps you can take to handle linked data when reading your part 
  12328. (in InitPartFromStorage). The overall procedure is described in The 
  12329. InitPartFromStorage Method. 
  12330.  
  12331.    1. As you encounter a persistent reference to a link object or link-source 
  12332.       object in the content you are reading, ensure that the reference is 
  12333.       valid. Before trying to read in the referenced storage unit, pass the 
  12334.       persistent reference to the IsValidStorageUnitRef method of the storage 
  12335.       unit containing the content you are reading. 
  12336.  
  12337.           If IsValidStorageUnitRef returns true, Call your draft's 
  12338.            AcquireLinkSource or AcquireLink method to read in the object. 
  12339.  
  12340.           If IsValidStorageUnitRef returns false, the link-source object or 
  12341.            link object no longer exists, and your part should no longer 
  12342.            consider the associated portion of its own content as linked. This 
  12343.            is not an error situation, and you need not notify the user if it 
  12344.            occurs. 
  12345.  
  12346.    2. For each link-source object you read, call its SetSourcePart method to 
  12347.       associate it with your part. Add the link-source object to whatever 
  12348.       private list of link sources you maintain, and associate it with the 
  12349.       specific content in your part that is the source of the link. 
  12350.  
  12351.    3. For each link object you read, associate the link object with the 
  12352.       specific content in your part that is the destination of the link. Add 
  12353.       the link object to whatever private structures you maintain for link 
  12354.       destinations. 
  12355.  
  12356.    4. For each link object you read, be prepared to register for update 
  12357.       notification if updating is to be automatic. Once the linked data becomes 
  12358.       visible or affects visible content, pass the last-saved update ID to the 
  12359.       link's RegisterDependent method. 
  12360.  
  12361.  
  12362. ΓòÉΓòÉΓòÉ 10.6.2.6.2. Reading Links for Data Transfer ΓòÉΓòÉΓòÉ
  12363.  
  12364.  
  12365. Here are the steps you can take to handle linked data when reading (cloning) 
  12366. from the clipboard or drag and drop object. The overall procedure for reading 
  12367. from a data-transfer object is described in Incorporating Intrinsic Content. 
  12368.  
  12369.    1. After the clone operation completes successfully-assuming that you have 
  12370.       followed the cloning steps listed in Cloning Process and have saved all 
  12371.       object IDs returned by the Clone method-pass the ID of each cloned link 
  12372.       object or link-source object to your draft's IsValidID method to 
  12373.       determine if its object is valid. 
  12374.  
  12375.       If IsValidID returns true, call your draft's AcquireLinkSource or 
  12376.       AcquireLink method to read in the object. If IsValidID returns false, the 
  12377.       link-source object or link object no longer exists and was not cloned. 
  12378.  
  12379.    2. For each link-source object you read, call its SetSourcePart method to 
  12380.       associate it with your part. Add the link-source object to whatever 
  12381.       private list of link sources you maintain, and associate it with the 
  12382.       specific content in your part that is the source of the link. (That 
  12383.       information is included in the contents property of the transferred data 
  12384.       and is defined by the format of the part kind your editor is reading.) 
  12385.  
  12386.    3. For each link object you read, associate the link object with the 
  12387.       specific content in your part that is the destination of the link. Add 
  12388.       the link object to whatever private structures you maintain for link 
  12389.       destinations. (That information is included in the contents property of 
  12390.       the transferred data and is defined by the format of the part kind your 
  12391.       editor is reading.) 
  12392.  
  12393.    4. If you are reading and embedding a single part that is also a link source 
  12394.       or destination, there should be a property named kODPropProxyContent in 
  12395.       the data-transfer storage unit. The property should contain a persistent 
  12396.       reference to the link-source object or link object associated with the 
  12397.       embedded part, plus any other needed information such as the fields of 
  12398.       the link info structure. If you understand the format of the data in the 
  12399.       property, read it and use it. 
  12400.  
  12401.  Note that, if you have incorporated an existing link source into your part, 
  12402.  you may not be able to write all the data types (part kinds) to the link 
  12403.  source object that its previous owner did. That is not an error; simply write 
  12404.  the part kinds that you support. 
  12405.  
  12406.  
  12407. ΓòÉΓòÉΓòÉ 10.6.2.7. Revealing the Source of a Link ΓòÉΓòÉΓòÉ
  12408.  
  12409. Users need to be able to navigate from the destination of a link to the source 
  12410. content. When the user selects the Show Link Source button in the Link 
  12411. Destination Info dialog box the destination part calls the ShowSourceContent 
  12412. method of the link object. OpenDoc, in turn, calls the source part's RevealLink 
  12413. method. This is its interface: 
  12414.  
  12415. void RevealLink(in ODLinkSource linkSource);
  12416.  
  12417. If your part contains the source of a link, your RevealLink method should 
  12418. display the part content that corresponds to the link source, following these 
  12419. general steps: 
  12420.  
  12421.    1. Using whatever part-specific method you choose, locate a display frame of 
  12422.       the source content. If no suitable frame exists, open a part window to 
  12423.       display the source. 
  12424.  
  12425.    2. Ensure that the frame displaying the source is visible in the window. 
  12426.       Find its containing frame by calling its AcquireContainingFrame method, 
  12427.       then call the RevealFrame method of the containing frame's part. (The 
  12428.       procedure is simple if your part opened up a separate part window for the 
  12429.       link source, because the display frame, being the root frame for the 
  12430.       window, is already visible.) 
  12431.  
  12432.    3. Activate the frame, using your part's normal activation procedure (see 
  12433.       How Part Activation Happens). Scroll the content, if necessary, to make 
  12434.       the source content visible. 
  12435.  
  12436.    4. Select the content and draw a link border around it. 
  12437.  
  12438.  
  12439. ΓòÉΓòÉΓòÉ 10.6.2.8. Editing a Link Destination ΓòÉΓòÉΓòÉ
  12440.  
  12441. Because OpenDoc links are unidirectional from source to destination, the 
  12442. OpenDoc human interface guidelines restrict the editing that a user can perform 
  12443. within the destination of a link. Basically, changing of content in a link 
  12444. destination is not allowed. 
  12445.  
  12446. It is the responsibility of the destination part to block attempts to edit its 
  12447. link destinations. However, the part that initially receives an editing event 
  12448. may be a frame embedded within, perhaps deeply embedded within, the destination 
  12449. part. If your part's display frame has the status kODInLinkDestination and the 
  12450. user attempts to edit content within it, your part should call the EditInLink 
  12451. method of your frame. OpenDoc in turn calls the EditInLinkAttempted method of 
  12452. the part that maintains the link destination that includes your frame. This is 
  12453. the interface to EditInLinkAttempted: 
  12454.  
  12455. ODBoolean EditInLinkAttempted (in ODFrame frame);
  12456.  
  12457. The part that maintains the link destination should, in its EditInLinkAttempted 
  12458. method, take steps similar to these: 
  12459.  
  12460.    1. It should check that it does indeed maintain a link destination that 
  12461.       involves the specified frame. If not, the method should return false and 
  12462.       exit. 
  12463.  
  12464.    2. It should present to the user an alert box that allows the user to forego 
  12465.       the editing, break the link, or display its source. In any case, the part 
  12466.       should not activate itself. 
  12467.  
  12468.           If the user chooses to forego editing, EditInLinkAttempted should 
  12469.            simply return true. 
  12470.  
  12471.           If the user chooses to display the source, EditInLinkAttempted 
  12472.            should follow the instructions listed in Revealing the Source of a 
  12473.            Link. 
  12474.  
  12475.           If the user chooses to break the link, EditInLinkAttempted should 
  12476.            follow the instructions listed in Breaking and Cutting Links, and 
  12477.            return true. 
  12478.  
  12479.  If EditInLinkAttempted returns true, then EditInLink returns true to your part 
  12480.  (the part in whose display frame the edit attempt occurred). If the user has 
  12481.  broken the link, your part can allow editing in your display frame. 
  12482.  
  12483.  If EditInLinkAttempted returns false, then EditInLink returns false and 
  12484.  OpenDoc cannot find the part that maintains the link destination. Your part 
  12485.  should then put up its own simple alert box informing the user that editing in 
  12486.  a link destination is not allowed. 
  12487.  
  12488.  If the user selects more than one link destination in your part and then 
  12489.  attempts to edit the data, your part cannot even call EditInLink. It should 
  12490.  then disallow editing and display a dialog box, suggesting that the user 
  12491.  select a single destination. 
  12492.  
  12493.  
  12494. ΓòÉΓòÉΓòÉ 10.6.2.9. Breaking and Cutting Links ΓòÉΓòÉΓòÉ
  12495.  
  12496. Users can delete links in several ways. When you delete or cut content that 
  12497. includes a link source, or when you break a link at its source, your part 
  12498. relinquishes ownership of the link source object, as noted in the first table 
  12499. under Moving and Copying Links and Link Sources. You should: 
  12500.  
  12501.      Disassociate the link-source object from your part's content 
  12502.  
  12503.      Set the link's source part to null by calling the link source's 
  12504.       SetSourcePart method 
  12505.  
  12506.      save a reference to the link-source object in an undo action, rather than 
  12507.       releasing the link source 
  12508.  
  12509.      Call the SetChangedFromPrev method of your draft to make sure that this 
  12510.       change is saved when the document is closed 
  12511.  
  12512.      Change the link status of any affected frames (see Frame Link Status) for 
  12513.       a link that has been broken 
  12514.  
  12515.  It is not necessary at this point to update the link source to delete its 
  12516.  contents. If the user subsequently undoes the action, you can reverse the 
  12517.  steps listed in the previous paragraph. You must be sure to call the link 
  12518.  source object's SetSourcePart method once again to reclaim ownership of the 
  12519.  link source object. 
  12520.  
  12521.  When you delete or cut content that includes a link destination, or when you 
  12522.  break a link at its destination, you should: 
  12523.  
  12524.      Disassociate the link object from your part's content 
  12525.  
  12526.      Save a reference to the link object in an undo action, rather than 
  12527.       releasing the link 
  12528.  
  12529.      If there are no remaining destinations of this link in your part, call 
  12530.       the link object's UnregisterDependent method, so that your part will no 
  12531.       longer be notified when updates occur 
  12532.  
  12533.      Call the SetChangedFromPrev method of your draft, to make sure that this 
  12534.       change is saved when the document is closed 
  12535.  
  12536.      Change the link status of any affected frames (see Frame Link Status) for 
  12537.       a link that has been broken 
  12538.  
  12539.  Reversing these actions undoes the break or cut. Your part should hold the 
  12540.  references to a cut or broken link source or link until your 
  12541.  DisposeActionState method is called, at which time you can release the link or 
  12542.  link-source object. 
  12543.  
  12544.  
  12545. ΓòÉΓòÉΓòÉ 10.6.3. Transfer Rules for Links and Link Sources ΓòÉΓòÉΓòÉ
  12546.  
  12547. This section summarizes the semantics of data transfer involving link objects 
  12548. and link-source objects. This discussion is for informational purposes only; if 
  12549. you follow the procedures presented earlier in this chapter, the correct 
  12550. semantics will always occur. 
  12551.  
  12552. During some data-transfer operations, OpenDoc may delete or redirect link or 
  12553. link-source objects. Other operations are permitted by OpenDoc but should not 
  12554. be supported by your part. This section lists the basic data-transfer 
  12555. operations, in terms of: 
  12556.  
  12557.      What happens when your part moves or copies linked data 
  12558.  
  12559.      What happens when your part creates a link destination when pasting or 
  12560.       dropping data that is already linked 
  12561.  
  12562.      What configurations of links within links your part should support 
  12563.  
  12564.  
  12565. ΓòÉΓòÉΓòÉ 10.6.3.1. Moving and Copying Links and Link Sources ΓòÉΓòÉΓòÉ
  12566.  
  12567. OpenDoc enforces the actions listed in the following table when existing links 
  12568. or link sources and their associated intrinsic content are transferred by drag 
  12569. and drop or with the clipboard and the appropriate kinds of cloning 
  12570. transactions are specified. 
  12571.  
  12572. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  12573. ΓöéOperation           ΓöéObject              ΓöéBehavior            Γöé
  12574. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12575. ΓöéCopy (Drag-copy, or ΓöéLink source         ΓöéData is transferred;Γöé
  12576. ΓöéCopy followed by    Γöé                    Γöélink source is not. Γöé
  12577. ΓöéPaste)              Γöé                    Γöé                    Γöé
  12578. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12579. Γöé                    ΓöéLink destination    ΓöéData is transferred;Γöé
  12580. Γöé                    Γöé                    Γöélink destination is Γöé
  12581. Γöé                    Γöé                    Γöétransferred also    Γöé
  12582. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12583. Γöé                    ΓöéSource and          ΓöéData is transferred;Γöé
  12584. Γöé                    Γöédestination of same Γöélink source and     Γöé
  12585. Γöé                    Γöélink                Γöédestination are bothΓöé
  12586. Γöé                    Γöé                    Γöétransferred (but anyΓöé
  12587. Γöé                    Γöé                    Γöélinks to            Γöé
  12588. Γöé                    Γöé                    Γöédestinations of thisΓöé
  12589. Γöé                    Γöé                    Γöénew link source     Γöé
  12590. Γöé                    Γöé                    Γöéoutside the copied  Γöé
  12591. Γöé                    Γöé                    Γöécontent are broken) Γöé
  12592. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12593. ΓöéMove (Drag-move, or ΓöéLink source         ΓöéData is transferred;Γöé
  12594. ΓöéCut followed by     Γöé                    Γöélink source is      Γöé
  12595. ΓöéPaste)              Γöé                    Γöétransferred also    Γöé
  12596. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12597. Γöé                    ΓöéLink destination    ΓöéData is transferred;Γöé
  12598. Γöé                    Γöé                    Γöélink destination is Γöé
  12599. Γöé                    Γöé                    Γöétransferred also    Γöé
  12600. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12601. Γöé                    ΓöéSource and          ΓöéData is transferred;Γöé
  12602. Γöé                    Γöédestination of same Γöélink source and     Γöé
  12603. Γöé                    Γöélink                Γöédestination are bothΓöé
  12604. Γöé                    Γöé                    Γöétransferred         Γöé
  12605. Γöé                    Γöé                    ΓöéNote:               Γöé
  12606. Γöé                    Γöé                    ΓöéThe move function   Γöé
  12607. Γöé                    Γöé                    Γöéis not supported    Γöé
  12608. Γöé                    Γöé                    Γöéin the current      Γöé
  12609. Γöé                    Γöé                    Γöérelease of OpenDoc. Γöé
  12610. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  12611.  
  12612.  
  12613. ΓòÉΓòÉΓòÉ 10.6.3.2. Creating a Link that Includes Already-Linked Content ΓòÉΓòÉΓòÉ
  12614.  
  12615. When pasting or accepting a drop into your part, you can incorporate or embed 
  12616. data that includes existing link sources or destinations and at the same time 
  12617. attempt to make the data a link destination. In that situation, OpenDoc 
  12618. enforces the actions listed in the following table. Note that the link 
  12619. specification in the table refers to the entire clipboard (or drag and drop) 
  12620. content; it is written by the part that placed the data on the clipboard or 
  12621. drag and drop object. 
  12622.  
  12623. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  12624. ΓöéContent to Paste              ΓöéBehavior in New Link          Γöé
  12625. Γöé                              ΓöéDestination                   Γöé
  12626. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12627. ΓöéIntrinsic content             ΓöéData is pasted at the         Γöé
  12628. Γöé                              Γöédestination; new link         Γöé
  12629. Γöé                              Γöédestination is created from   Γöé
  12630. Γöé                              Γöélink specification.           Γöé
  12631. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12632. ΓöéLink source                   Γöé Data is pasted at the        Γöé
  12633. Γöé                              Γöédestination; new link         Γöé
  12634. Γöé                              Γöédestination is created from   Γöé
  12635. Γöé                              Γöélink specification (link      Γöé
  12636. Γöé                              Γöésource in pasted data is not  Γöé
  12637. Γöé                              Γöémaintained)                   Γöé
  12638. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12639. ΓöéLink destination              ΓöéData is pasted at the         Γöé
  12640. Γöé                              Γöédestination; new link         Γöé
  12641. Γöé                              Γöédestination is created from   Γöé
  12642. Γöé                              Γöélink specification (link      Γöé
  12643. Γöé                              Γöédestination in pasted data is Γöé
  12644. Γöé                              Γöénot maintained)               Γöé
  12645. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12646. ΓöéSource and destination of the ΓöéData is pasted at the         Γöé
  12647. Γöésame link                     Γöédestination; new link         Γöé
  12648. Γöé                              Γöédestination is created from   Γöé
  12649. Γöé                              Γöélink specification (link      Γöé
  12650. Γöé                              Γöésource and destination in     Γöé
  12651. Γöé                              Γöépasted data are not           Γöé
  12652. Γöé                              Γöémaintained)                   Γöé
  12653. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  12654.  
  12655. You can create links within links; OpenDoc does not prevent you from creating 
  12656. or pasting the source or destination of one link within the source or 
  12657. destination of another link. However, only some configurations make sense, as 
  12658. shown in the following table. 
  12659.  
  12660. You can use your display frame's link status (see Frame Link Status, as well as 
  12661. private link-status information about your own intrinsic content, to decide 
  12662. whether to allow the creation of a link source or destination in any given 
  12663. situation. In general, you cannot edit a link destination. 
  12664.  
  12665. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  12666. ΓöéTo create a new...  ΓöéWithin an           ΓöéRecommendation      Γöé
  12667. Γöé                    Γöéexisting...         Γöé                    Γöé
  12668. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12669. ΓöéLink source         ΓöéLink source         ΓöéOK. Result is two   Γöé
  12670. Γöé                    Γöé                    Γöéseparate link       Γöé
  12671. Γöé                    Γöé                    Γöésources with        Γöé
  12672. Γöé                    Γöé                    Γöépartially or        Γöé
  12673. Γöé                    Γöé                    Γöécompletely          Γöé
  12674. Γöé                    Γöé                    Γöéoverlapping content.Γöé
  12675. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12676. ΓöéLink source         ΓöéLink destination    ΓöéNO. When the        Γöé
  12677. Γöé                    Γöé                    Γöédestination updates,Γöé
  12678. Γöé                    Γöé                    Γöéit is generally     Γöé
  12679. Γöé                    Γöé                    Γöéimpossible to know  Γöé
  12680. Γöé                    Γöé                    Γöéwhich changes shouldΓöé
  12681. Γöé                    Γöé                    Γöébecome part of the  Γöé
  12682. Γöé                    Γöé                    Γöéupdated source.     Γöé
  12683. Γöé                    Γöé                    ΓöéAlso, any edits to  Γöé
  12684. Γöé                    Γöé                    Γöéthe source are then Γöé
  12685. Γöé                    Γöé                    Γöélost.               Γöé
  12686. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12687. ΓöéLink destination    ΓöéLink source         ΓöéOK. Updates to the  Γöé
  12688. Γöé                    Γöé                    Γöédestination simply  Γöé
  12689. Γöé                    Γöé                    Γöébecome part of the  Γöé
  12690. Γöé                    Γöé                    Γöésource.             Γöé
  12691. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12692. ΓöéLink destination    ΓöéLink destination    ΓöéNO. Updates to      Γöé
  12693. Γöé                    Γöé                    Γöéeither link         Γöé
  12694. Γöé                    Γöé                    Γöédestination will    Γöé
  12695. Γöé                    Γöé                    Γöéoverwrite the other.Γöé
  12696. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  12697.  
  12698.  
  12699. ΓòÉΓòÉΓòÉ 11. Semantic Events and Scripting ΓòÉΓòÉΓòÉ
  12700.  
  12701. This is the seventh of eight chapters that discuss the OpenDoc programming 
  12702. interface in detail. This chapter describes the scripting support provided for 
  12703. your parts by OpenDoc. 
  12704.  
  12705. Before reading this chapter, you should be familiar with the concepts presented 
  12706. in Introduction and Development Overview. For additional concepts related to 
  12707. your part editor's run-time environment, see OpenDoc Run-Time Features. 
  12708.  
  12709. Scripting support is one example of the use of the OpenDoc Extension interface. 
  12710. Extending OpenDoc through its extension interface is described in general terms 
  12711. in Extending OpenDoc. 
  12712.  
  12713. This chapter first summarizes the Open Scripting Architecture and OpenDoc 
  12714. scripting in general, and then describes the OpenDoc semantic interface, a set 
  12715. of classes and handlers you can take advantage of in implementing your support 
  12716. for scripting. The chapter then describes how to write and install: 
  12717.  
  12718.      Semantic-event handlers 
  12719.      Object accessors 
  12720.      Object-callback functions, coercion handlers, and pre-dispatch handlers 
  12721.  
  12722.  This chapter concludes with a discussion of how to construct object specifiers 
  12723.  and send semantic events from your part. 
  12724.  
  12725.  Note:  The explanations in this chapter extend the discussions of OSA events, 
  12726.         the OSA event object model, and the Open Scripting Architecture 
  12727.         presented in the Open Scripting Architecture Programming Guide and 
  12728.         Reference. It is assumed that you are already familiar with, or have 
  12729.         access to, the descriptions of scripting found in that book. 
  12730.  
  12731.  
  12732. ΓòÉΓòÉΓòÉ 11.1. Scripting and OpenDoc ΓòÉΓòÉΓòÉ
  12733.  
  12734. Scripting is a powerful way to automate and customize programs. By adding 
  12735. scripts to a program and executing them, a user can simplify and automate tasks 
  12736. that might otherwise require extensive and repetitive human interaction. If the 
  12737. program supports it, a user might even be able to use scripts to change the 
  12738. meaning of existing commands. As a simple example, a user might customize the 
  12739. meaning of a "Save" command so that it updates a logging database every time a 
  12740. document is saved. 
  12741.  
  12742. OpenDoc allows for scripting of semantic events, distinguished from user events 
  12743. in that they are high-level actions understandable by the user and by the 
  12744. program, but independent of individual user actions. Opening, closing, saving 
  12745. documents, embedding parts, and manipulating content can be examples of 
  12746. semantic events. 
  12747.  
  12748. OpenDoc supports your part editor's ability to receive and process semantic 
  12749. events through its semantic interface, a set of classes providing methods that 
  12750. you can use or override. The class ODSemanticInterface is a subclass of the 
  12751. extension class (ODExtension), described in Classes for Extending OpenDoc. You 
  12752. use the semantic interface class to set up and register semantic-event handlers 
  12753. and callback functions. (OpenDoc also supports your part editor's ability to 
  12754. create and send semantic events through another object, the messaging 
  12755. interface, an object of the class ODMessageInterface). 
  12756.  
  12757. Any entity that understands the semantic interface of a part can send it 
  12758. semantic events. Script editors can convert scripting commands to semantic 
  12759. events and send them to any object in any part of a document. Parts can send 
  12760. semantic events to their containing parts, to embedded parts, to sibling parts, 
  12761. to linked parts-to any parts for which they can find an address. Other types of 
  12762. OpenDoc components can also send semantic events; spelling checkers, for 
  12763. example, can use them to operate on the content of text parts. 
  12764.  
  12765. Scripting support in OpenDoc can be pervasive; if you take full advantage of 
  12766. it, literally every action a user can take may invoke a script. However, a 
  12767. range of options exists, and you can decide what level of scripting support 
  12768. makes the most sense for your parts. 
  12769.  
  12770. Your part editor supports scripting through the OpenDoc semantic interface in 
  12771. much the same way as a conventional application supports scripting. Your part 
  12772. editor must provide an interface to its content objects and operations, and it 
  12773. must accept semantic events. The document shell passes semantic events to 
  12774. OpenDoc to deliver to your parts. Event targets are described by object 
  12775. specifiers, which refer to objects in your parts in terms of your published 
  12776. content model. The document shell needs information from your part editor to 
  12777. resolve these specifiers so that it can determine where to deliver the events. 
  12778.  
  12779.  
  12780. ΓòÉΓòÉΓòÉ 11.1.1. Open Scripting Architecture ΓòÉΓòÉΓòÉ
  12781.  
  12782. The scripting capability of OpenDoc is based on the Open Scripting Architecture 
  12783. (OSA). OSA is a powerful cross-platform messaging and scripting system that can 
  12784. support multiple scripting languages. OSA has three basic components: 
  12785.  
  12786.      The events messaging system 
  12787.      The events object model 
  12788.      One or more scripting systems 
  12789.  
  12790.  This section gives a brief summary of these components. For complete 
  12791.  documentation of OSA, see the Open Scripting Architecture Programming Guide 
  12792.  and Reference 
  12793.  
  12794.  
  12795. ΓòÉΓòÉΓòÉ 11.1.1.1. OSA Events ΓòÉΓòÉΓòÉ
  12796.  
  12797. The system of semantic events at the base of the OpenDoc implementation of OSA 
  12798. is OSA events. OSA events are described in the events chapters of Open 
  12799. Scripting Architecture Programming Guide and Reference. 
  12800.  
  12801. OSA events are messages that applications use to request services and 
  12802. information from each other. The application making the request constructs and 
  12803. sends an event to the application receiving the request. The receiving 
  12804. application uses an event handler to extract pertinent data from the event, 
  12805. perform the requested action, and possibly return a result. 
  12806.  
  12807. OSA events constitute a standard vocabulary of actions that can be requested. 
  12808. OSA events are grouped into suites of related events. The OSA Event Registry: 
  12809. Standard Suites describes several commonly implemented suites. The most 
  12810. important suite to support for general scriptability is the Core suite, the 
  12811. suite that contains events common to many kinds of application software. 
  12812.  
  12813. When sending an event, a requesting application can specify that the event 
  12814. apply, not to the receiving application as a whole, but to some element of the 
  12815. application's data. For example, an application can request the data of a 
  12816. particular row of a particular table in a particular report. The sender 
  12817. constructs an object specifier that it sends along with the OSA event to denote 
  12818. the exact element or elements that the event applies to. The Event Registry 
  12819. includes definitions of the kinds of objects recognized within each suite. 
  12820.  
  12821. The Event Manager is the component of system software that manages the 
  12822. construction, sending, and processing of OSA events. It handles OSA events in 
  12823. general and performs event dispatching for conventional applications. With 
  12824. OpenDoc, events and the Event Manager function essentially as described in the 
  12825. Open Scripting Architecture Programming Guide and Reference; however, there are 
  12826. some differences caused by the differences between parts and conventional 
  12827. applications: 
  12828.  
  12829.      OpenDoc does its own dispatching of OSA events. This is to ensure that 
  12830.       the event is directed to the correct part and that the reply is directed 
  12831.       back to the part that sent the original event. That behavior is almost 
  12832.       exactly the same as that provided by the Event Manager, except that the 
  12833.       sender of the event no longer has access to the event's returnID 
  12834.       parameter. Because this parameter is for OpenDoc's internal use only it 
  12835.       is therefore missing from the Send method of ODMessageInterface 
  12836.  
  12837.      OpenDoc itself implements some of the Event Manager functions. For those 
  12838.       functions, you must use the corresponding methods defined by OpenDoc 
  12839.       instead of directly calling the Event Manager. Cover methods for event 
  12840.       functions are contained in the classes ODSemanticInterface (for calling, 
  12841.       installing, and removing handlers), ODMessageInterface (for constructing 
  12842.       and sending events), and ODNameResolver (for resolving object 
  12843.       specifiers). Functions for which there is no corresponding OpenDoc method 
  12844.       are available directly from the Event Manager. The following table lists 
  12845.       the OSA Event Manager functions and their equivalent OpenDoc methods: 
  12846.  
  12847.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  12848.   ΓöéOSA Event Manager Function (doΓöéOpenDoc Method (do use)                      Γöé
  12849.   Γöénot use)                      Γöé                                             Γöé
  12850.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12851.   ΓöéAEResolve                     ΓöéODNameResolver::Resolve                      Γöé
  12852.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12853.   ΓöéAECallObjectAccessor          ΓöéODNameResolver::CallObjectAccessor           Γöé
  12854.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12855.   ΓöéAECreateOSAEvent              ΓöéODMessageInterface::CreateEvent              Γöé
  12856.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12857.   ΓöéAESend                        ΓöéODMessageInterface::Send                     Γöé
  12858.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12859.   ΓöéAEInstallCoercionHandler      ΓöéODSemanticInterface::InstallCoercionHandler  Γöé
  12860.   ΓöéAEInstallEventHandler         ΓöéODSemanticInterface::InstallEventHandler     Γöé
  12861.   ΓöéAEInstallObjectAccessor       ΓöéODSemanticInterface::InstallObjectAccessor   Γöé
  12862.   ΓöéAEInstallSpecialHandler       ΓöéODSemanticInterface::InstallSpecialHandler   Γöé
  12863.   Γöé                              Γöé(plus individual InstallCallback methods)    Γöé
  12864.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12865.   ΓöéAEGetCoercionHandler          ΓöéODSemanticInterface::GetCoercionHandler      Γöé
  12866.   ΓöéAEGetEventHandler             ΓöéODSemanticInterface::GetEventHandler         Γöé
  12867.   ΓöéAEGetObjectAccessor           ΓöéODSemanticInterface::GetObjectAccessor       Γöé
  12868.   ΓöéAEGetSpecialHandler           ΓöéODSemanticInterface::GetSpecialHandler       Γöé
  12869.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  12870.   ΓöéAERemoveCoercionHandler       ΓöéODSemanticInterface::RemoveCoercionHandler   Γöé
  12871.   ΓöéAERemoveEventHandler          ΓöéODSemanticInterface::RemoveEventHandler      Γöé
  12872.   ΓöéAERemoveObjectAccessor        ΓöéODSemanticInterface::RemoveObjectAccessor    Γöé
  12873.   ΓöéAERemoveSpecialHandler        ΓöéODSemanticInterface::RemoveSpecialHandler    Γöé
  12874.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  12875.  
  12876.  At run time, OpenDoc handles semantic events by accepting the events and 
  12877.  passing them to the appropriate part editor. There is no separate dispatcher 
  12878.  object for semantic events; the OpenDoc dispatcher that handles user events 
  12879.  also dispatches semantic events. 
  12880.  
  12881.  
  12882. ΓòÉΓòÉΓòÉ 11.1.1.2. Event Object Model ΓòÉΓòÉΓòÉ
  12883.  
  12884. OpenDoc relies on the event object model to specify individual elements of a 
  12885. part's content. The object model defines a hierarchical arrangement of content 
  12886. objects whose nature depends on the content model of the part. OSA events have 
  12887. object specifiers in their direct parameters to access individual content 
  12888. objects within a part. Part editors provide object accessor functions, used by 
  12889. the name resolver's Resolve method to resolve the object specifiers in OSA 
  12890. events that the parts receive. 
  12891.  
  12892. The event object model used by OpenDoc is slightly different from that used by 
  12893. conventional applications. Here are the differences: 
  12894.  
  12895.      The OpenDoc version of the object model has the ability to deal with 
  12896.       multiple parts in a single document. It achieves this ability by defining 
  12897.       a context for each event. The context for an OSA event in OpenDoc is the 
  12898.       equivalent of the object model's default container; it is the outermost 
  12899.       object in the object hierarchy defined by the direct parameter. The 
  12900.       default container for an OSA event is typically represented by the 
  12901.       application that receives the event; the context for an OpenDoc OSA 
  12902.       event, by contrast, might be the document shell, or any of the parts in a 
  12903.       document. 
  12904.  
  12905.      In processing an OSA event, OpenDoc reverses the typical sequence from 
  12906.       that used by the OSA Event Manager. The object specifier in the direct 
  12907.       parameter of an OSA event is resolved before any event handler is called. 
  12908.       The direct object may contain a description of the destination part, and 
  12909.       that determines the context of the event. OpenDoc therefore replaces the 
  12910.       object specifier in the direct parameter of the OSA event with the token 
  12911.       returned from the resolution (see Returning Tokens) before calling a 
  12912.       part's event handler. 
  12913.  
  12914.      The Resolve method of the class ODNameResolver, which is a wrapper for 
  12915.       the Event Manager AEResolve function, has a parameter used only by 
  12916.       OpenDoc. The parameter, of type ODPart, specifies the part that is the 
  12917.       context from which to start an object resolution. Also, unlike AEResolve, 
  12918.       the Resolve method has no callbackFlags parameter, because callback flags 
  12919.       in OpenDoc are specified on a part-by-part basis; they are set when the 
  12920.       part calls the SetOSLSupportFlags method of the ODSemanticInterface 
  12921.       class. 
  12922.  
  12923.      Object resolution is possible for parts embedded within parts that do not 
  12924.       support scripting. OpenDoc provides default object accessors and event 
  12925.       handlers that allow a message to pass through a part that does not 
  12926.       support scripting into an embedded parts that does. See  OpenDoc Semantic 
  12927.       Interface for more information. 
  12928.  
  12929.      OpenDoc adds a noun to the OSA Event Registry. To represent a part (more 
  12930.       strictly a display frame of a part), the registry defines the descriptor 
  12931.       type 'part', for which you can also use the constant cPart. 
  12932.  
  12933.      OpenDoc does not support calling the RemoveSpecialHandler function with 
  12934.       the keyword keySelectProc in order to disable object-model support. 
  12935.       Instead, making this call throws an exception. 
  12936.  
  12937.  Your part editor should implement object accessors as if your part were a 
  12938.  stand-alone conventional application-that is, with your part itself as the 
  12939.  context. 
  12940.  
  12941.  
  12942. ΓòÉΓòÉΓòÉ 11.1.1.3. Scripting Systems ΓòÉΓòÉΓòÉ
  12943.  
  12944. A scripting system completes the OSA implementation on a platform. It is 
  12945. through a scripting system that the user designs, attaches, and executes code 
  12946. to generate the semantic events that a scriptable part receives. 
  12947.  
  12948. Any OSA-compliant scripting system can be used with OpenDoc. 
  12949.  
  12950. OpenDoc allows the user to employ any available scripting system and even to 
  12951. switch among them during execution. 
  12952.  
  12953.  
  12954. ΓòÉΓòÉΓòÉ 11.1.2. Part Content Model ΓòÉΓòÉΓòÉ
  12955.  
  12956. To fully support scripting of your parts, you must construct a content model 
  12957. that includes a full set of content objects, accessible through semantic 
  12958. events, to allow a complete range of operations on your user-visible content. 
  12959. Your part editor must provide accessor functions to resolve external references 
  12960. to content objects, and it must also provide semantic-event handlers that 
  12961. implement content operations. 
  12962.  
  12963. The advantage of developing a content model and implementing the functions for 
  12964. resolving object specifiers and handling semantic events is that you increase 
  12965. flexibility and you provide user control over the basic functions of your part 
  12966. editor. For example, your parts will automatically be able to accept input from 
  12967. currently unavailable or unforeseen user interfaces, such as voice or pen or 
  12968. touch, that generate semantic events. 
  12969.  
  12970. If you also factor your part editor-that is, if you separate your part editor's 
  12971. core date engine from its user interface-you further increase its flexibility. 
  12972. Interface elements such as menus and dialogs, if reconstructed to invoke 
  12973. scripts or otherwise generate semantic events, will still be able to 
  12974. communicate directly with your parts. Factoring also facilitates making your 
  12975. parts recordable (see hdref refid=odrcrdl.). 
  12976.  
  12977.  
  12978. ΓòÉΓòÉΓòÉ 11.1.2.1. Content Operations ΓòÉΓòÉΓòÉ
  12979.  
  12980. The operations of a content model should be consistent with user actions. They 
  12981. typically include selection, creation, deletion, insertion, setting of 
  12982. properties, and so on. Low-level internal functions, such as piece-table 
  12983. functions for efficient text insertion or matrix inversion for fast graphics 
  12984. processing, are probably not appropriate as content-model operations. 
  12985.  
  12986. Your content operations correspond to the semantic events you support. You 
  12987. implement a semantic-event handler for each operation. 
  12988.  
  12989.  
  12990. ΓòÉΓòÉΓòÉ 11.1.2.2. Content Objects ΓòÉΓòÉΓòÉ
  12991.  
  12992. The objects of a content model should be consistent with what the user sees and 
  12993. manipulates, regardless of your part editor's internal structures. Inside a 
  12994. text part, for example, a user may see lines, words, paragraphs, characters, 
  12995. and embedded parts. Those are typical content objects for such a part. 
  12996. Internally, your part editor might maintain run-length encoding arrays, line 
  12997. end arrays, and so on. However, because they are not presented to the user, 
  12998. they are not part of the content model. Likewise, a graphics part might have 
  12999. content objects like circles, rectangles, and lines, regardless of what 
  13000. internal mathematical descriptions it uses. 
  13001.  
  13002. If a part supports embedding, embedded parts within it constitute a special 
  13003. class of content objects. The containing part can use content operations to 
  13004. manipulate the frames of embedded parts and perhaps some part-wide properties, 
  13005. but it cannot in general manipulate their contents-only the parts themselves 
  13006. can do that. 
  13007.  
  13008. The OpenDoc default object accessors already provide this basic ability to 
  13009. access the properties of, and send semantic events to, embedded frames. If your 
  13010. part is a container part and needs capabilities beyond this basic level, your 
  13011. object model can include a named type of content object that represents an 
  13012. embedded part to which you can pass events and from which you can extract 
  13013. properties. 
  13014.  
  13015. User selections 
  13016. If you want to make user selections controllable through semantic events, you 
  13017. must describe them with object specifiers, defined in terms of your part's 
  13018. content model. 
  13019.  
  13020.  
  13021. ΓòÉΓòÉΓòÉ 11.1.2.3. Resolving Object References ΓòÉΓòÉΓòÉ
  13022.  
  13023. Object specifiers in an event can refer to any content objects, including 
  13024. embedded parts. When it receives events, your part must provide accessor 
  13025. functions to allow those specifiers to be resolved. The accessor functions of a 
  13026. part return tokens, which are descriptors that identify the content objects or 
  13027. properties of those objects. 
  13028.  
  13029. As an example of content-object resolution, consider a document whose root part 
  13030. is a text part. Suppose that the user selects a portion of document and chooses 
  13031. a text style of "bold". To handle this command through semantic events, the 
  13032. root part could generate an object specifier to represent the current 
  13033. selection. In response to the "bold" menu command, the root part sends itself a 
  13034. semantic event-"Set Data to bold"-with the selection as the event's direct 
  13035. parameter. 
  13036.  
  13037. In response to the "Set Data to bold" event, the part resolves the object 
  13038. specifier to a list of tokens representing its content objects. The event 
  13039. handler for "Set Data to bold" then tells each of the content objects to make 
  13040. itself bold. Some of those objects may represent embedded parts. If the frames 
  13041. understand how to pass the "Set Data to bold" event on to the embedded parts 
  13042. that they represent, they do so. If the embedded parts recognize how to set 
  13043. their content to bold, they then do so; otherwise, they do nothing. 
  13044.  
  13045. Object accessor functions and object-specifier resolution are described in more 
  13046. detail in Writing Object Accessors. 
  13047.  
  13048.  
  13049. ΓòÉΓòÉΓòÉ 11.1.3. Levels of Scripting Support ΓòÉΓòÉΓòÉ
  13050.  
  13051. You can implement different levels of support for scripting in your part 
  13052. editor. Each successive level requires more effort but it gives the user 
  13053. greater flexibility and control over the functioning of your parts. 
  13054.  
  13055.  
  13056. ΓòÉΓòÉΓòÉ 11.1.3.1. Scriptable Parts ΓòÉΓòÉΓòÉ
  13057.  
  13058. If you make your parts scriptable, they will have at least a basic level of 
  13059. scripting support. To do that, you must create a content model for your parts 
  13060. with defined content objects (available through object accessors) and content 
  13061. operations (represented by semantic-event handlers) that are meaningful to the 
  13062. user. Then your part editor publishes a description of its content objects and 
  13063. operations and accepts semantic events: 
  13064.  
  13065.      Your part editor publishes its list of content objects and operations by 
  13066.       placing them in its terminology resource, a resource of type Open 
  13067.       Scripting Architecture Quick Referenceaete" that each scriptable part 
  13068.       editor must provide. 
  13069.  
  13070.      Your part editor accepts semantic events through its semantic interface, 
  13071.       available publicly as an OpenDoc extension object. The semantic interface 
  13072.       includes object accessor functions as well as semantic-event handlers. 
  13073.  
  13074.  Even among scriptability there are different levels of support. You can allow 
  13075.  script access to only a few content objects and operations or to many of them. 
  13076.  For your parts to be fully scriptable, semantic events must be able to invoke 
  13077.  any action a user might be able to perform. 
  13078.  
  13079.  One advantage of making your part scriptable is that you can allow it to be 
  13080.  used by other parts, even parts that you may not have developed yourself. For 
  13081.  example, if your part is a text part and you allow script access to all of its 
  13082.  text-style settings, the user (or your containing part or a sibling part) can 
  13083.  easily format any of your text for any purpose. 
  13084.  
  13085.  
  13086. ΓòÉΓòÉΓòÉ 11.1.3.2. Recordable Parts ΓòÉΓòÉΓòÉ
  13087.  
  13088. If you make your parts recordable, the user's actions can be captured as a 
  13089. series of semantic events, converted to scripts, and replayed at a later time 
  13090. to reenact the actions. A recommended way to make your parts recordable is to 
  13091. completely separate the user interface from the core data engine of your part 
  13092. editor. 
  13093.  
  13094. If your part editor handles every user-interface event by generating, sending 
  13095. to itself, and handling an equivalent semantic event, it can process all 
  13096. semantic events through a standard bottleneck and have the Event Manager record 
  13097. the actions. This use of a bottleneck not only allows recording but also 
  13098. enhances code portability. 
  13099.  
  13100. The events that pass through the bottleneck should be just the set of actions 
  13101. that match the content model of your part editor. These events need not follow 
  13102. exactly the inner design of your core data engine, but they should reflect the 
  13103. complete range of user actions. 
  13104.  
  13105.  
  13106. ΓòÉΓòÉΓòÉ 11.1.3.3. Customizable Parts ΓòÉΓòÉΓòÉ
  13107.  
  13108. If you make your part's interface customizable, the user can only invoke all 
  13109. actions through scripts, but can also change the nature of the actions 
  13110. themselves by attaching additional scripts that are invoked when the actions 
  13111. are executed. 
  13112.  
  13113. To support customizable parts, a part editor must not only be scriptable but 
  13114. must also define content objects and operations for interface elements such as 
  13115. menus and buttons, or provide other ways to trigger scripts. It must provide 
  13116. persistent storage for any scripts that the user attaches to its interface 
  13117. elements. 
  13118.  
  13119. Making a part fully customizable requires that the part editor allow attachment 
  13120. and invocation of scripts during virtually any user action. For the highest 
  13121. levels of customizability, user actions such as open, close, save, and restore 
  13122. as well as all editing should be scriptable. (In OpenDoc, only the root part's 
  13123. attached scripts can be invoked for document-level events such as saving, 
  13124. restoring, opening, closing, printing, and so on). 
  13125.  
  13126. Before processing any user event or semantic event, the part editor must check 
  13127. whether a script attached to the part wants to handle the event. If so, it 
  13128. allows the script to run. 
  13129.  
  13130. Note that, if your part is recordable, you can check for the presence of and 
  13131. invoke scripts in a semantic-event dispatching bottleneck, in which case you 
  13132. achieve full customizability with little extra effort. 
  13133.  
  13134.  
  13135. ΓòÉΓòÉΓòÉ 11.1.4. Scripting-Related Objects ΓòÉΓòÉΓòÉ
  13136.  
  13137. Several OpenDoc classes provide a structure for its support of semantic events 
  13138. and scripting. Implementations of these and other classes constitute the 
  13139. OpenDoc semantic interface, described in OpenDoc Semantic Interface. The 
  13140. following figure, a duplication of a portion of the OpenDoc class hierarchy 
  13141. (first figure in A Set of Classes, Not a Framework), shows the principal 
  13142. OpenDoc classes involved with scripting. 
  13143.  
  13144. Three classes provide basic support for scripting in OpenDoc: 
  13145.  
  13146.      The class ODSemanticInterface defines the programming interface through 
  13147.       which script editors or other sources of semantic events communicate with 
  13148.       your part. It is a subclass of ODExtension and is an abstract superclass. 
  13149.  
  13150.      The class ODNameResolver represents the name resolver, a subclass of 
  13151.       ODObject that is instantiated by the session object. It is used in 
  13152.       resolving object specifiers; see Object Resolution. 
  13153.  
  13154.      The class ODMessageInterface represents the message interface, a subclass 
  13155.       of ODObject that is instantiated by the session object. It provides an 
  13156.       interface through which your part sends semantic events to other parts; 
  13157.       see Sending Semantic Events. 
  13158.  
  13159.  (The message interface is also the object through which OpenDoc sends semantic 
  13160.  events to your part, although your part does not make any calls to the message 
  13161.  interface in that situation). 
  13162.  
  13163.  OpenDoc also provides a set of scripting-related classes that are wrappers for 
  13164.  OSA event descriptor structures. These classes, whose inheritance is 
  13165.  diagrammed in the following figure, are analogous to the OpenDoc support 
  13166.  classes shown in the last figure in A Set of Classes, Not a Framework. 
  13167.  
  13168.  The object-descriptor classes exist so that future versions of OpenDoc can 
  13169.  support remote callbacks. They are mostly simple wrappers for structures, 
  13170.  although some define few methods that you can call. Other than ODOSLToken, the 
  13171.  structures that these objects wrap are all OSA events structures. Here is what 
  13172.  each of them is for: 
  13173.  
  13174.      The class ODDesc is a general wrapper for a descriptor structure (type 
  13175.       AEDesc), the basic structure used for building OSA event attributes and 
  13176.       parameters. The other classes in this list are all direct or indirect 
  13177.       subclasses of ODDesc. ODDesc itself is a direct subclass of ODObject. 
  13178.  
  13179.       ODDesc provides methods for extracting and replacing the data of the OSA 
  13180.       event descriptor it contains. 
  13181.  
  13182.      The class ODOSLToken is a wrapper for an OpenDoc token, described in 
  13183.       Returning Tokens. ODOSLToken provides a method for duplicating itself. 
  13184.  
  13185.      The class ODAddressDesc is a wrapper for an address descriptor structure 
  13186.       (type AEAddressDesc), a descriptor structure that contains a target 
  13187.       address. 
  13188.  
  13189.      The class ODObjectSpec is a wrapper for an object specifier structure 
  13190.       (type typeObjectSpecifier), a descriptor structure that describes the 
  13191.       location of one or more OSA event objects. 
  13192.  
  13193.      The class ODDescList is a wrapper for a descriptor list (type 
  13194.       AEDescList), a descriptor structure that is a list of other descriptor 
  13195.       structures. 
  13196.  
  13197.      The class ODRecord is a wrapper for an OSA structure (type AERecord), a 
  13198.       descriptor list that can be used to construct OSA event parameters and 
  13199.       other structures. 
  13200.  
  13201.      The class ODOSAEvent is a wrapper for an OSA event structure (type 
  13202.       AEEvent), a structure that describes a full-fledged OSA event. 
  13203.  
  13204.  
  13205. ΓòÉΓòÉΓòÉ 11.2. OpenDoc Semantic Interface ΓòÉΓòÉΓòÉ
  13206.  
  13207. The class ODSemanticInterface defines the programming interface through which 
  13208. your semantic-event handlers and object accessors are called. 
  13209.  
  13210. OpenDoc provides default semantic-event handlers and object accessors that 
  13211. allow it to access and send semantic events to scriptable parts embedded within 
  13212. parts that do not themselves support scripting. Even if your part does support 
  13213. scripting, you can use these defaults and build on their capabilities, rather 
  13214. than duplicating them. 
  13215.  
  13216.  
  13217. ΓòÉΓòÉΓòÉ 11.2.1. Default Get Data and Set Data Event Handlers ΓòÉΓòÉΓòÉ
  13218.  
  13219. To allow senders of semantic events to access certain basic information about 
  13220. any part in a document-regardless of whether that part is scriptable-OpenDoc 
  13221. provides two default event handlers. The handlers for the Get Data and Set Data 
  13222. OSA events are used for any part that does not replace them with its own 
  13223. versions. 
  13224.  
  13225. The information manipulated by these handlers is the standard set of Info 
  13226. properties. These handlers cannot manipulate the content of any part. The event 
  13227. class of the handlers is kCoreEventClass, and their event IDs are kAEGetData 
  13228. and kAESetData. 
  13229.  
  13230. You can rely on the default Get Data and Set Data handlers to provide script 
  13231. access to your parts standard Info properties. Such limited access does not 
  13232. really constitute scriptability; to provide script access to your part's 
  13233. intrinsic content or to other Info properties of your part or of parts embedded 
  13234. in your part, you need to write you own handlers. 
  13235.  
  13236. When you write your own semantic-event handler, follow the instructions in 
  13237. Writing Semantic-Event Handlers. 
  13238.  
  13239.  
  13240. ΓòÉΓòÉΓòÉ 11.2.2. Default Object Accessors ΓòÉΓòÉΓòÉ
  13241.  
  13242. OpenDoc provides default object accessors that give script access to 
  13243. information within parts that do not support semantic events. Even if your part 
  13244. editor does support scripting, you can rely on these accessors to perform the 
  13245. following specific tasks; you need write object accessors only for other 
  13246. purposes, such as accessing your intrinsic content. 
  13247.  
  13248.      Part. From the null container, a default accessor can return a token 
  13249.       representing an embedded part. If your part is not scriptable, if it does 
  13250.       not provide such an accessor, or if its accessor does not handle this 
  13251.       task, the name resolver's Resolve method uses a default accessor to 
  13252.       return a reference to a frame embedded within your part. 
  13253.  
  13254.       The default accessor can resolve references to embedded parts specified 
  13255.       by part name, part index, or part ID. Part ID in this case is not the 
  13256.       part's storage-unit ID, but its persistent object ID, an identifying 
  13257.       value used only for script access. A part's persistent object ID is 
  13258.       unique within its draft and is valid across sessions. You can obtain a 
  13259.       persistent ID for a part or a frame by calling the GetPersistentObjectID 
  13260.       method of its draft; you can recreate a part or frame object by passing 
  13261.       its persistent object ID to its draft's AcquirePersistentObject method. 
  13262.  
  13263.       The token returned by this default accessor has the format described in 
  13264.       Standard Embedded-Frame Token. 
  13265.  
  13266.      Property. From the null container, a default accessor can return a token 
  13267.       representing a standard Info property of the part that is the current 
  13268.       context. If you do not provide such an accessor, or if your accessor does 
  13269.       not handle this task, the name resolver uses this default accessor to 
  13270.       return a reference to a standard Info property of your part. 
  13271.  
  13272.      Wild card. From a container of type cPart, a default accessor can return 
  13273.       a swap token (see Returning a Swap Token), so that the name resolver can 
  13274.       switch the context from the current part to a more deeply embedded one. 
  13275.       If you do not provide such an accessor, or if your accessor does not 
  13276.       handle this task, the name resolver uses this default accessor to change 
  13277.       the context to the appropriate part embedded within your part. 
  13278.  
  13279.  If your part editor supports scripting but you do not want to duplicate the 
  13280.  functions of these default accessors, you can write accessors only for tasks 
  13281.  beyond the defaults: accessing objects in your part's intrinsic content, 
  13282.  accessing Info properties that you have defined for your own part of for parts 
  13283.  embedded in your part, altering the ordering/indexing scheme for embedded 
  13284.  parts, and so on. 
  13285.  
  13286.  When one of your object accessors receives a token that it does not recognize 
  13287.  as having been created by another of your own object accessors, it can simply 
  13288.  return the OSA event error errAEEventNotHandled to the name resolver; the name 
  13289.  resolver then attempts the resolution with the default accessors. Conversely, 
  13290.  when your accessor receives a token that it recognizes as your own, the 
  13291.  accessor creates a token as described in Returning Tokens, and returns it to 
  13292.  the name resolver. 
  13293.  
  13294.  Note that tokens created by your object accessors contain data in a format 
  13295.  that your semantic-event handlers can understand, whereas tokens describing 
  13296.  Info properties created by the default accessors are in a private format. 
  13297.  Therefore, if you allow the default accessor to return tokens for the standard 
  13298.  Info properties, you also need to allow the default Get Data and Set Data 
  13299.  handlers to manipulate those standard Info properties. In that case, your own 
  13300.  GetData and Set Data handlers need only manipulate your intrinsic content plus 
  13301.  any custom properties you have defined for your part or for embedded parts. 
  13302.  
  13303.  
  13304. ΓòÉΓòÉΓòÉ 11.2.3. Standard Embedded-Frame Token ΓòÉΓòÉΓòÉ
  13305.  
  13306. To allow access to scriptable parts embedded within parts that are not 
  13307. scriptable, OpenDoc provides the default part accessor (described in the 
  13308. previous section). That accessor returns a token in a standard format. The 
  13309. token has a descriptor type cPart, and its dataHandle field contains only a 
  13310. frame pointer and a part pointer (of type ODFrame and ODPart, respectively). 
  13311.  
  13312. If your part is a container part and is scriptable, it must be able to support 
  13313. the creation of an embedded-frame token, either through its own object 
  13314. accessors or by letting the default part accessor construct the token. 
  13315.  
  13316.  
  13317. ΓòÉΓòÉΓòÉ 11.3. Implementing your Semantic Interface ΓòÉΓòÉΓòÉ
  13318.  
  13319. To be scriptable, your part must create a semantic interface that allows it to 
  13320. accept semantic events, handle them, and reply to them. It must: 
  13321.  
  13322.      Provide semantic-event handlers for at least the core suite of OSA events 
  13323.  
  13324.      Provide object accessors for its content objects 
  13325.  
  13326.      Provide other kinds of handlers (such as object callback functions and 
  13327.       coercion handlers) as appropriate 
  13328.  
  13329.      Make public, through a terminology resource, the events it handles and 
  13330.       content-object types it recognizes 
  13331.  
  13332.  
  13333. ΓòÉΓòÉΓòÉ 11.3.1. Writing Semantic-Event Handlers ΓòÉΓòÉΓòÉ
  13334.  
  13335. You need to create a handler for every semantic event that your part editor 
  13336. recognizes. Your list of semantic-event handlers defines the content operations 
  13337. that your parts engage in and allow users to access. 
  13338.  
  13339. How your semantic-event handlers manipulate your parts' content is entirely up 
  13340. to you. This section discusses only the process by which your handler receives 
  13341. and handles a semantic event. Installing your handler is described in 
  13342. Installation 
  13343.  
  13344. A typical source of semantic events is a script engine or another part. The 
  13345. script engine or part generates semantic events and sends them to your 
  13346. document's document shell. This is how your part ends up receiving and 
  13347. processing a semantic event: 
  13348.  
  13349.    1. The identity of your part-the destination part-generally have been 
  13350.       encoded in the object specifier in the direct parameter of the OSA event. 
  13351.       Your part can be at any level of embedding in the document, and the 
  13352.       encoding can be either explicit or implicit; for example, your part may 
  13353.       be the implicit target when the event explicitly requests a custom Info 
  13354.       property of one of your embedded parts. 
  13355.  
  13356.    2. The OpenDoc document shell receives the OSA event and passes it to the 
  13357.       message interface object, by calling the message interface's 
  13358.       ProcessSemanticEvent method. 
  13359.  
  13360.    3. The message interface object calls the name resolver's Resolve method for 
  13361.       the event's direct parameter. Within the Resolve method, the 
  13362.       object-resolution process may cycle several times (see Resolving Object 
  13363.       References), until your part's semantic interface has been accessed and 
  13364.       an object accessor of yours has returned a token that specifies your part 
  13365.       or an object contained within it. 
  13366.  
  13367.    4. The message interface object calls the CallEventHandler method of the 
  13368.       semantic interface to dispatch the event to your semantic-event handler. 
  13369.       The CallEventHandler in turn examines the event class and ID to determine 
  13370.       to which handler to dispatch. 
  13371.  
  13372.    5. Your part may have an attached script for any semantic event. If so, you 
  13373.       execute the script at this point. If not, or if the script does not 
  13374.       handle the event, or if the script handler passes the event on after 
  13375.       processing, you dispatch the event to the semantic-event handler. 
  13376.  
  13377.    6. Your semantic event handler, on receiving the event, decides whether and 
  13378.       how to resolve additional parameters. In general, you should only perform 
  13379.       destructive actions (such as writing) on your own part; do not resolve 
  13380.       parameters that would result in destructive actions being taken on 
  13381.       embedded parts. 
  13382.  
  13383.    7. Your event handler carries out its operation, returning a reply OSA event 
  13384.       if appropriate. 
  13385.  
  13386.       You fill out reply OSA events just as conventional applications do, as 
  13387.       described in the Open Scripting Architecture Programming Guide and 
  13388.       Reference. If the semantic event was sent by another part, the message 
  13389.       interface object generates and keeps track of the return ID for the 
  13390.       event, so that your reply can be routed back to the sender's reply event 
  13391.       handler. 
  13392.  
  13393.  
  13394. ΓòÉΓòÉΓòÉ 11.3.2. Writing Object Accessors ΓòÉΓòÉΓòÉ
  13395.  
  13396. Object specifiers in an OSA event can refer to any content objects. If your 
  13397. part is to receive OSA events, it must provide accessor functions to allow 
  13398. those specifiers to be resolved. Your accessor functions return tokens (see 
  13399. Returning Tokens) that your own semantic-event handlers know how to interpret. 
  13400. OpenDoc passes those tokens to your handlers when it resolves objects in the 
  13401. direct parameters of OSA events; your handlers themselves call the name 
  13402. resolver's Resolve method and receive the tokens for other OSA event parameters 
  13403. that are object specifiers. 
  13404.  
  13405. If your scriptable part is also a container part, it must provide object 
  13406. accessor methods for objects that represent embedded parts, and it must be able 
  13407. to relinquish the context-that is, it must be able to hand off the 
  13408. object-resolution process to an embedded part (see Returning a Swap Token). 
  13409. OpenDoc includes default object accessors that provide the minimum capability 
  13410. for swapping context, but your part can replace or add to the capabilities of 
  13411. those accessors, if desired. 
  13412.  
  13413. This section describes how your object accessor is called and which tokens it 
  13414. constructs and returns. The section also describes the default accessors 
  13415. provided with OpenDoc so that semantic events can be sent to parts embedded 
  13416. within containing parts that do not themselves support scripting. 
  13417.  
  13418.  
  13419. ΓòÉΓòÉΓòÉ 11.3.2.1. Object Resolution ΓòÉΓòÉΓòÉ
  13420.  
  13421. OpenDoc resolves object specifiers for content objects within parts much as the 
  13422. OSA Event Manager resolves object specifiers in conventional applications. 
  13423. However, there are some differences, including these: 
  13424.  
  13425.      For semantic events sent from outside of a document, the document shell 
  13426.       is the first handler of an object-specifier resolution. Its role is to 
  13427.       hand off that resolution to correct part. To find that part, OpenDoc uses 
  13428.       object accessor functions provided by individual parts to obtain 
  13429.       part-relative tokens (tokens for which the part is the context). 
  13430.  
  13431.      OpenDoc reads parts into memory, if necessary, when interpreting object 
  13432.       specifiers. For example, an embedded part referred to in a specifier may 
  13433.       not be currently visible and thus not yet read into memory. To resolve 
  13434.       the chain of objects further, OpenDoc may have to read in the part and 
  13435.       then access an object within it. 
  13436.  
  13437.      The callback flags used by the Resolve method (equivalent to the 
  13438.       callbackFlags parameter of the OSA Event Manager AEResolve function) have 
  13439.       a scope that is local to each part, rather than global to the object 
  13440.       resolution process. Each part sets its callback flags by calling the 
  13441.       SetOSLSupportFlags method of its semantic interface. 
  13442.  
  13443.  OpenDoc takes the following steps to resolve a reference to a content object. 
  13444.  The process starts when the document shell (in the case of semantic events 
  13445.  from outside the document) receives a semantic event and calls the message 
  13446.  interface's ProcessSemanticEvent method, as described under steps 1 and 2 in 
  13447.  Writing Semantic-Event Handlers. 
  13448.  
  13449.    1. The message interface calls the Resolve method of the name resolver 
  13450.       (class ODNameResolver), passing it the object specifier in the direct 
  13451.       parameter of the OSA event (steps 1 and 2 of the figure shown at the end 
  13452.       of these steps). 
  13453.  
  13454.       If the direct parameter does not exist, there may be a subject attribute 
  13455.       in the event that takes the place of a direct parameter (see Sending 
  13456.       Semantic Events). If there is no direct parameter or subject attribute, 
  13457.       or if the direct parameter is not an object specifier, Resolve is not 
  13458.       called and the event goes to the root part. 
  13459.  
  13460.    2. Not shown in the figure represented at the end of these steps is the fact 
  13461.       that the Resolve method first accesses the document shell's semantic 
  13462.       interface and gives it a chance to resolve the object specifier. If, as 
  13463.       is typical, the event is targeted to a part rather than to the document 
  13464.       shell itself, the document shell passes resolution to the root part. The 
  13465.       Resolve method then takes the following steps, first with the root part 
  13466.       and then with the appropriate embedded parts until the specifier is 
  13467.       finally resolved. 
  13468.  
  13469.       (Note that, because OSA event objects exist in a hierarchy of containers, 
  13470.       several cycles through the following steps, and thus several context 
  13471.       swaps may be necessary to identify the specific object within a 
  13472.       hierarchy). 
  13473.  
  13474.         a. Starting with the default container (this part's context), the 
  13475.            Resolve method calls the AcquireExtension method of this part to get 
  13476.            the list of its object accessors. The Resolve method finds the 
  13477.            accessor for the specified property or element and calls it (step 3 
  13478.            of the figure shown at the end of these steps). 
  13479.  
  13480.         b. The object accessor returns a token to the Resolve method, following 
  13481.            the steps listed in Returning Tokens. 
  13482.  
  13483.                If the object is not an embedded part, the accessor puts into 
  13484.                 the token whatever information is needed to map the token to 
  13485.                 the right content object, and returns the token to the Resolve 
  13486.                 method. 
  13487.  
  13488.                If the content object represents an embedded frame as a whole, 
  13489.                 the accessor creates and returns a token that specifies the 
  13490.                 embedded frame. 
  13491.  
  13492.                 OpenDoc provides a default part accessor that performs this 
  13493.                 task if this part's object accessor does not, or if this part 
  13494.                 is not scriptable. See Default Object Accessors. 
  13495.  
  13496.                If the content object represents a directly accessible property 
  13497.                 of an embedded part-either a standard Info property such as the 
  13498.                 embedded part's modification date, or a custom property that 
  13499.                 this part may have defined, such as "is-selected"-the accessor 
  13500.                 creates and returns a token that specifies the requested 
  13501.                 property. 
  13502.  
  13503.                 OpenDoc provides a default property accessor that performs this 
  13504.                 task (for the standard Info properties only) if this part's 
  13505.                 object accessor does not, or if this part is not scriptable. 
  13506.                 See Default Object Accessors. 
  13507.  
  13508.                If the content object represents an object within an embedded 
  13509.                 part, or a property of the embedded part that this part cannot 
  13510.                 access, the accessor returns a special token (see Returning a 
  13511.                 Swap Token). At the next pass, the embedded part's list of 
  13512.                 accessors is used instead (step 4 of the figure shown at the 
  13513.                 end of these steps). 
  13514.  
  13515.                 OpenDoc provides a default wild-card accessor that performs 
  13516.                 this swap if this part's object accessor does not, or if this 
  13517.                 part is not scriptable. See Default Object Accessors. 
  13518.  
  13519.         c. The Resolve method finds the object accessor for the next property 
  13520.            or element in the hierarchy of the object specifier and passes the 
  13521.            returned token as the container to that accessor. That accessor, in 
  13522.            turn, returns another token. This cycle continues, with context 
  13523.            swaps occurring when appropriate, until the innermost element of the 
  13524.            object specifier has been converted to a token and passed back to 
  13525.            Resolve (steps 5 and 6 of the figure shown at the end of these 
  13526.            steps). 
  13527.  
  13528.    3. After resolving the object specifier, Resolve returns the final token to 
  13529.       the message interface object (step 7 of the figure shown at the end of 
  13530.       these steps). OpenDoc then passes that final token to the proper part's 
  13531.       semantic-event handler, as the direct parameter of the OSA event (step 8 
  13532.       of the figure shown at the end of these steps). 
  13533.  
  13534.  
  13535. ΓòÉΓòÉΓòÉ 11.3.2.2. Returning Tokens ΓòÉΓòÉΓòÉ
  13536.  
  13537. In the OpenDoc version of OSA events, a token is a special descriptor 
  13538. structure, implemented as an OpenDoc object of type ODOSLToken, that a part 
  13539. uses to identify one or more content objects within itself. Your object 
  13540. accessor functions return tokens when they successfully resolve object 
  13541. specifiers. The structure of a token is not public, but it contains an OpenDoc 
  13542. object (of type ODDesc) that is itself a wrapper for an OSA event descriptor 
  13543. structure (type AEDesc). An OSA event descriptor consists of a 4-byte 
  13544. descriptorType field followed by a 4-byte dataHandle field. 
  13545.  
  13546. OpenDoc hides the structure of the ODOSLToken and ODDesc objects; you cannot 
  13547. manipulate their fields directly. This privacy allows OpenDoc to store extra 
  13548. information that it needs inside a token, and it also ensures that OpenDoc's 
  13549. scripting support will be compatible with future distributed-object models. 
  13550.  
  13551. When your object accessor needs to return a token, it modifies the ODOSLToken 
  13552. object that was passed to it, placing the data of an AEDesc structure into the 
  13553. ODOSLToken object before returning: 
  13554.  
  13555.    1. The accessor creates a descriptor of type AEDesc and sets its 
  13556.       descriptorType and dataHandle fields to store the information needed. 
  13557.       (Note that the dataHandle field must really be a handle). 
  13558.  
  13559.    2. The accessor then calls the GetUserToken method of the name resolver to 
  13560.       access the OpenDoc descriptor object (of type ODDesc) that is contained 
  13561.       within the token that was passed to the accessor. 
  13562.  
  13563.    3. The accessor assigns the AEDesc descriptor to the ODDesc object, using 
  13564.       the function AEDescToODDesc (from a utility library provided with 
  13565.       OpenDoc), and then disposes of the AEDesc. 
  13566.  
  13567.    4. Because the ODOSLToken object passed to the accessor and the ODDesc 
  13568.       object returned by GetUserToken are not copies, any changes that the 
  13569.       accessor has made are already reflected in the ODOSLToken object itself. 
  13570.       Therefore, the accessor simply returns, and the name resolver can then 
  13571.       examine the modified token. 
  13572.  
  13573.  The ODDesUtl utility library also provides the function ODDescToAEDesc, which 
  13574.  allows you to extract the AEDesc descriptor structure from an ODDesc object, 
  13575.  in order to inspect or modify it. 
  13576.  
  13577.  Your object accessors can verify the tokens passed to them by calling the name 
  13578.  resolver's IsODToken method. The name resolver also provides the 
  13579.  GetContextFromToken method, which allows your accessor to determine, for 
  13580.  example, which display frame of its part contains the target of the event. 
  13581.  
  13582.  
  13583. ΓòÉΓòÉΓòÉ 11.3.2.3. Returning a Swap Token ΓòÉΓòÉΓòÉ
  13584.  
  13585. Sometimes your object accessor function is asked to access a content object (or 
  13586. a property that your part cannot directly access) from a object whose class is 
  13587. cPart-meaning that the requested item is something within a frame embedded in 
  13588. your part. In this case, the accessor must pass back a special token, called a 
  13589. swap token, to inform the name resolver of its inability to furnish the 
  13590. required token. Your accessor creates this  token by calling the 
  13591. CreateSwapToken method of the name resolver to initialize the swap token, 
  13592. passing it a pointer to the embedded frame and a pointer to the part (your 
  13593. part) containing the embedded frame. Your accessor then should simply return a 
  13594. value of noErr, taking no further action. 
  13595.  
  13596. Upon receipt of the swap token, the name resolver changes the current context 
  13597. from your part to the embedded part, and retries the object access in that 
  13598. context. 
  13599.  
  13600. If your part is a container part and is scriptable, it must support such 
  13601. context switches with swap tokens, either through its own object accessors or 
  13602. by letting a default accessor (see Default Object Accessors) perform the swap. 
  13603.  
  13604. Note:  OpenDoc reserves the descriptor type "swch" for its own use. Do not use 
  13605.        this value, or any value consisting solely of lowercase letters (such as 
  13606.        "part"), in the descriptorType field of your own tokens. 
  13607.  
  13608.  
  13609. ΓòÉΓòÉΓòÉ 11.3.2.4. Other Considerations ΓòÉΓòÉΓòÉ
  13610.  
  13611. When you write an object accessor, note that, in interpreting object 
  13612. specifiers, "part X of doc Y" implies "part X of <current draft> of doc Y". 
  13613.  
  13614. Your part can provide object accessors for document-wide user-interface 
  13615. elements, to be used when it is the root part of a document. For example, as 
  13616. root part it can provide accessors for window scroll bars or for document 
  13617. characteristics such as page size. 
  13618.  
  13619. If your object accessor needs to know the frame through which your part was 
  13620. accessed-the frame that displays the part that is the current context-it can 
  13621. call the GetContextFromToken method of the name resolver. The value returned 
  13622. represents the most recent frame passed to CreateSwapToken. 
  13623.  
  13624.  
  13625. ΓòÉΓòÉΓòÉ 11.3.3. Writing Other Kinds of Handlers ΓòÉΓòÉΓòÉ
  13626.  
  13627. In addition to semantic-event handlers and object accessors, you can write 
  13628. other special-purpose functions and install them for use in interpreting 
  13629. semantic events. This section discusses OpenDoc issues related to 
  13630. object-callback functions, coercion handlers, and other kinds of handlers. 
  13631.  
  13632.  
  13633. ΓòÉΓòÉΓòÉ 11.3.3.1. Object Callback Functions ΓòÉΓòÉΓòÉ
  13634.  
  13635. Your part can provide object callback functions for the Resolve method to call 
  13636. where your part needs to provide extra information before object resolution can 
  13637. occur. You can use these functions, also called special handlers, for a variety 
  13638. of purposes: 
  13639.  
  13640.      You can provide an object-counting function (CountProc) so that, when the 
  13641.       object specifier involves a test, Resolve can determine how many elements 
  13642.       it must examine in performing the test. You must provide this function if 
  13643.       you want the OSA Event Manager to perform whose tests, that is, to 
  13644.       resolve object specifier records of key form formTest without assistance 
  13645.       from your part. 
  13646.  
  13647.      You can provide an object-comparison function (CompareProc), which 
  13648.       determines whether one element or descriptor record is equal to another. 
  13649.       You must provide this function if you want the OSA Event Manager to 
  13650.       perform whose tests, that is, to resolve object specifier records of key 
  13651.       form formTest without assistance from your part. 
  13652.  
  13653.      You can provide a token-disposal function (DisposeTokenProc)-which 
  13654.       overrides the Event Manager's AEDisdposeDesc function-in case you need to 
  13655.       do any extra processing when your tokens are disposed of. 
  13656.  
  13657.      You can provide an error-callback function (GetErrDescProc), provides a 
  13658.       descriptor into which the Event Manager can write information about 
  13659.       resolution failures. 
  13660.  
  13661.      You can provide three kinds of marking-callback functions, which allow 
  13662.       your part to use its own marking scheme to identify sets of objects: 
  13663.  
  13664.         -  A marking function (MarkProc) marks a set of objects. 
  13665.  
  13666.         -  An unmarking function (AdjustMarksProc) removes marks from 
  13667.            previously marked object sets. 
  13668.  
  13669.         -  A marker-token function (GetMarkTokenProc) returns a token that can 
  13670.            be used to mark a set of objects. 
  13671.  
  13672.  All callback functions in OpenDoc function exactly as they do with 
  13673.  conventional applications, except for those minor changes: 
  13674.  
  13675.      Each has an additional parameter, of type ODPart, to allow access to your 
  13676.       part object from the callback function. 
  13677.  
  13678.      Some parameters have different types from their conventional equivalents. 
  13679.       For example, parameters of type AEDesc in conventional callbacks have 
  13680.       types ODDesc or ODOSLToken in OpenDoc callbacks. 
  13681.  
  13682.      OpenDoc callback functions return an error type of ODErr, instead of the 
  13683.       OSErr type returned by callback functions for conventional applications. 
  13684.  
  13685.  You install object callbacks as described in Installing Handlers, Accessors, 
  13686.  and Callbacks. 
  13687.  
  13688.  Object-callback functions (and whose tests) are described in more detail in 
  13689.  Open Scripting Architecture Programming Guide and Reference. 
  13690.  
  13691.  
  13692. ΓòÉΓòÉΓòÉ 11.3.3.2. Coercion Handlers ΓòÉΓòÉΓòÉ
  13693.  
  13694. Coercion handlers are functions that convert data of one descriptor type into 
  13695. data of another descriptor type. Coercion handlers are common in OSA events. 
  13696. Some are provided by the Event Manager, others may be provided by your part 
  13697. editor. Any coercion handlers installed by your part editor are called only 
  13698. when your part is the context for the event. Normally, the document shell is 
  13699. the context, but there are two situations in which your part can become the 
  13700. context: 
  13701.  
  13702.      When an object accessor installed by your part must be called during the 
  13703.       resolution of an object specifier 
  13704.  
  13705.      When your part's semantic-event handler is called 
  13706.  
  13707.  Coercion handlers are not chained by OpenDoc. That is, an embedded part does 
  13708.  not inherit the coercion handlers of its containing part, and a root part does 
  13709.  not inherit the coercion handlers of the shell. 
  13710.  
  13711.  Coercion handlers are described in more detail in the Open Scripting 
  13712.  Architecture Programming Guide and Reference 
  13713.  
  13714.  
  13715. ΓòÉΓòÉΓòÉ 11.3.3.3. Pre-Dispatch Handlers and Recording ΓòÉΓòÉΓòÉ
  13716.  
  13717. A pre-dispatch handler is a function that is called whenever your document 
  13718. receives any event, before your part's handler for that OSA event is called. 
  13719. OpenDoc allows you to install pre-dispatch handlers and to specify whether or 
  13720. not you are currently using a given pre-dispatch handler. 
  13721.  
  13722. For example, if your part is recordable, you can install a pre-dispatch handler 
  13723. to intercept the Start Recording and Stop Recording OSA events that are sent to 
  13724. the document shell. (OpenDoc does not automatically forward those events to 
  13725. each part in a document). Even so, your part may be read into memory and 
  13726. initialized after the user has turned recording on, in which case your 
  13727. pre-dispatch handler won't receive the Start Recording OSA event. Therefore, 
  13728. when your part initializes itself, it should also check with the OSA Event 
  13729. Manager to see if recording is on. If so, it can record its actions. 
  13730.  
  13731. Pre-dispatch handlers are described in more detail, along with the 
  13732. keyPreDispatch constant, in Open Scripting Architecture Programming Guide and 
  13733. Reference. 
  13734.  
  13735.  
  13736. ΓòÉΓòÉΓòÉ 11.3.4. Installation ΓòÉΓòÉΓòÉ
  13737.  
  13738. Once you have an instance of the semantic interface, you need to install its 
  13739. components as described in this section. 
  13740.  
  13741.  
  13742. ΓòÉΓòÉΓòÉ 11.3.4.1. Making the Semantic-Interface Extension Available ΓòÉΓòÉΓòÉ
  13743.  
  13744. You must override the (inherited) part methods HasExtension and 
  13745. AcquireExtension so that they return the semantic interface object. The ODType 
  13746. constant that names the semantic interface extension is 
  13747. kODExtSemanticInterface; the constant is passed by callers of your HasExtension 
  13748. and AcquireExtension methods. 
  13749.  
  13750. In implementing and interacting with the semantic interface, follow the rules 
  13751. for using OpenDoc extensions, as described in OpenDoc Extension Interface. 
  13752.  
  13753.  
  13754. ΓòÉΓòÉΓòÉ 11.3.4.2. Installing Handlers, Accessors, and Callbacks ΓòÉΓòÉΓòÉ
  13755.  
  13756. Your part editor's semantic interface is mainly a table of handlers that 
  13757. OpenDoc uses when processing a semantic event: You call methods of the semantic 
  13758. interface to install, remove, and call event handlers, object accessors and 
  13759. other special callback functions. 
  13760.  
  13761.      You install semantic-event handlers by calling the InstallEventHandler 
  13762.       method. 
  13763.  
  13764.      You install object accessors by calling the InstallObjectAccessor method. 
  13765.  
  13766.      You install coercion handlers by calling the InstallCoercionHandler 
  13767.       method. 
  13768.  
  13769.      You install object callback functions in either of two ways. You can call 
  13770.       the InstallSpecialHandler method and pass it a parameter specifying the 
  13771.       kind of function to install, or you can call function-specific methods 
  13772.       such as InstallCountProc and InstallMarkProc. Constants for the parameter 
  13773.       you pass to InstallSpecialHandler are defined by the OSA Event Manager, 
  13774.       and have names such as keyAECompareProc. 
  13775.  
  13776.      You install a pre-dispatch handler either by calling the 
  13777.       InstallSpecialHandler method, passing it a parameter whose value is 
  13778.       keyPreDispatch, or by calling the UsingPreDispatchProc method. 
  13779.  
  13780.  Other methods of the semantic interface allow access to and removal of these 
  13781.  handlers, accessors, and callbacks. 
  13782.  
  13783.  You use the SetOSLSupportFlags method to set flags that, during the resolution 
  13784.  process, notify the name resolver's Resolve method of the kinds of 
  13785.  object-callback support that your part editor can provide for resolution of 
  13786.  object specifiers. 
  13787.  
  13788.  
  13789. ΓòÉΓòÉΓòÉ 11.3.4.3. Installing System-Level Handlers ΓòÉΓòÉΓòÉ
  13790.  
  13791. To install system-level semantic-event handlers, coercion handlers, object 
  13792. accessors and object callback functions, you can use the standard OSA Event 
  13793. Manager installation functions and set the isSysHandler parameter to TRUE. 
  13794.  
  13795. In general installing system-level handlers is discouraged. If you do install 
  13796. them, be sure that you don't leave them installed after your part has closed. 
  13797. You should remove any installed handlers in your part's ReleaseAll method, or 
  13798. possibly in your part's Release method when the reference count goes to 0. 
  13799.  
  13800.  
  13801. ΓòÉΓòÉΓòÉ 11.3.5. Making your Terminology Resource Available ΓòÉΓòÉΓòÉ
  13802.  
  13803. When a scripting system first compiles a script that targets an OpenDoc 
  13804. document, it needs access to the terminology ("aete") resources associated with 
  13805. that document. The scripting system gains this access by calling the GetAETE 
  13806. method of the OSATerminology class. 
  13807.  
  13808. Your part editor should install a terminology resource in the registration 
  13809. database by using the OSAInstallApplication function when it is first 
  13810. registered. When the GetAETE method is called with OpenDoc specified, all the 
  13811. terminology resources of all installed part editors, including the document 
  13812. shell terminology resource, are returned. Because the scripting system merges 
  13813. all terminology resources into a single composite resource for all parts and 
  13814. all documents, it is extremely important that your part editor avoid 
  13815. terminology conflicts with other part editors. 
  13816.  
  13817. Also, because the only available terminologies are those in the system-wide 
  13818. merged "aete" resource, your part editor cannot make its terminologies known 
  13819. dynamically; it cannot itself handle the Get AETE event. 
  13820.  
  13821.  
  13822. ΓòÉΓòÉΓòÉ 11.4. Sending Semantic Events ΓòÉΓòÉΓòÉ
  13823.  
  13824. Although the ability to send semantic events is not required for scriptability, 
  13825. OpenDoc provides specific support for it. This section discusses the 
  13826. OpenDoc-specific aspects of sending semantic events; for more information, see 
  13827. the Open Scripting Architecture Programming Guide and Reference. 
  13828.  
  13829. The OpenDoc message interface object (ODMessageInterface) is responsible for 
  13830. constructing OSA events, getting and setting event attributes, parsing events, 
  13831. and sending events. This section describes how your part uses the message 
  13832. interface and the OSA Event Manager to send a semantic event. 
  13833.  
  13834. To construct the OSA event, you call the CreateEvent method of the message 
  13835. interface object. You can then construct additional parameters and add them to 
  13836. the OSA event by calling the OSA Event Manager AEPutParamPtr or AEPutParamDesc 
  13837. function. 
  13838.  
  13839.  
  13840. ΓòÉΓòÉΓòÉ 11.4.1. Constructing Object Specifiers ΓòÉΓòÉΓòÉ
  13841.  
  13842. To send an OSA event to an OpenDoc part, the sender must use an object 
  13843. specifier that identifies the target part. The object specifier can be in the 
  13844. direct parameter of the OSA event, or it can be in a subject attribute. A 
  13845. subject attribute is an object specifier that refers to a part by its 
  13846. persistent object ID (see Default Object Accessors). All recorded events (all 
  13847. events sent through the Send method of the message interface) include a subject 
  13848. attribute. The presence of a subject attribute allows a scripting system to 
  13849. record the events' targets, even for events that have no direct parameter. 
  13850.  
  13851. Conventional applications using the OSA Event Manager to send events to a part 
  13852. in an OpenDoc document construct the appropriate object specifier themselves. 
  13853. If your part sends a semantic event, you can use the methods described in this 
  13854. section to construct an object specifier. Note that if you send a semantic 
  13855. event to your own part (as when recording), you follow the same procedures as 
  13856. when sending an event to another part. 
  13857.  
  13858.  
  13859. ΓòÉΓòÉΓòÉ 11.4.1.1. Using CreatePartObjSpec ΓòÉΓòÉΓòÉ
  13860.  
  13861. If your part sends a semantic event to another part, you can use the 
  13862. CreatePartObjSpec method of the message interface to construct an object 
  13863. specifier for the direct parameter of the event. You must also call the 
  13864. CreatePartAddrDesc method of the message interface to create an address 
  13865. descriptor that identifies the process (OpenDoc document) in which the 
  13866. destination part resides. 
  13867.  
  13868. If you use CreatePartObjSpec, OpenDoc dispatches to the specified part 
  13869. directly, without calling the Resolve method of the name resolver. This 
  13870. dispatching is efficient and fast. However, you cannot inspect the contents of 
  13871. the object specifier constructed by CreatePartObjSpec or use it for recording, 
  13872. and you cannot use it as a component of another object specifier that you 
  13873. construct. 
  13874.  
  13875.  
  13876. ΓòÉΓòÉΓòÉ 11.4.1.2. Using EmbeddedFrameSpec ΓòÉΓòÉΓòÉ
  13877.  
  13878. You can also use the EmbeddedFrameSpec method of ODPart to help construct an 
  13879. object specifier. You can inspect the resulting specifier, you can use it for 
  13880. recording, and you can use it as the direct parameter or as another parameter 
  13881. in an OSA event. Object specifiers created through EmbeddedFrameSpec have forms 
  13882. such as "embedded frame 2 of embedded frame 1 of the root frame". 
  13883.  
  13884. To construct an object specifier in this way, you call the EmbeddedFrameSpec 
  13885. method of the part containing the frame that is the target for the event. Here 
  13886. is the interface to EmbeddedFrameSpec: 
  13887.  
  13888. void EmbeddedFrameSpec(in ODFrame embeddedFrame,
  13889.                        in ODObjectSpec spec);
  13890.  
  13891. A part receiving this method call should create an object specifier for the 
  13892. supplied embedded frame (using index number or any other appropriate 
  13893. identifying characteristic), call the EmbeddedFrameSpec method of its own 
  13894. containing part, and then concatenate the results. The final object specifier 
  13895. returned to the original caller thus describes the target frame in the context 
  13896. of its document. 
  13897.  
  13898. Constructing object specifiers with EmbeddedFrameSpec is most useful for 
  13899. situations in which a target part's position in the embedding hierarchy is more 
  13900. important than its specific identity. Note, however, that EmbeddedFrameSpec 
  13901. fails if any part in the embedding hierarchy from the target frame to the root 
  13902. frame is not scriptable or has not implemented the EmbeddedFrameSpec method. 
  13903. Also, an object specifier constructed by this method will become incorrect if 
  13904. the identifying characteristic of any frame in the hierarchy changes. 
  13905.  
  13906.  
  13907. ΓòÉΓòÉΓòÉ 11.4.1.3. Using Persistent Object ID ΓòÉΓòÉΓòÉ
  13908.  
  13909. The most reliable method for constructing an object specifier for a part is by 
  13910. using its persistent object ID. If you are constructing an object specifier and 
  13911. your call to EmbeddedFrameSpec fails, or if you are sending an OSA event to a 
  13912. part with no display frames, or any time you need an object specifier that will 
  13913. be valid for a part regardless of its position in the embedding hierarchy, use 
  13914. its persistent object ID. 
  13915.  
  13916. Call the GetPersistentObjectID method of the target frame's or part's draft and 
  13917. use the return value in the object specifier. If your own frame is the target, 
  13918. as when recording, call your own draft's GetPersistentObjectID method and pass 
  13919. it your own display frame. 
  13920.  
  13921.  
  13922. ΓòÉΓòÉΓòÉ 11.4.2. Sending the Event ΓòÉΓòÉΓòÉ
  13923.  
  13924. To send the OSA event, you call the Send method of the message interface 
  13925. object. The message interface adds a subject attribute, representing the target 
  13926. part (which is your part if you are sending the part to yourself) to the event. 
  13927. The message interface also generates and keeps track of the return ID for the 
  13928. event so that the reply can be routed back to your part editor's reply event 
  13929. handler. 
  13930.  
  13931.  
  13932. ΓòÉΓòÉΓòÉ 12. Extending OpenDoc ΓòÉΓòÉΓòÉ
  13933.  
  13934. This is the last of eight chapters that discuss the OpenDoc programming 
  13935. interface in detail. This chapter describes how you can use or alter portions 
  13936. of the OpenDoc class library to enhance the capabilities of your part editors. 
  13937.  
  13938. Before reading this chapter, you should be familiar with the concepts presented 
  13939. in Introduction and Development Overview. For additional concepts related to 
  13940. your part editor's run-time environment, see OpenDoc Run-Time Features. 
  13941.  
  13942. This chapter discusses the following ways in which you can extend OpenDoc: 
  13943.  
  13944.      By creating OpenDoc extension objects for your part editor, you can add 
  13945.       programming interfaces to your parts for any purpose. The semantic 
  13946.       interface support in OpenDoc, described in Semantic Events and Scripting 
  13947.       is an example of the use of extension objects. 
  13948.  
  13949.      By creating a settings extension, you can give users access to 
  13950.       editor-specific settings through the Properties notebook. 
  13951.  
  13952.      By creating specialized dispatch modules, you can define new kinds of 
  13953.       user events that your parts can respond to. 
  13954.  
  13955.      By creating specialized focus modules, you can define new categories of 
  13956.       foci (shared resources) that your parts can acquire and exchange. 
  13957.  
  13958.      By creating a subclass of ODTransform, you can extend the ways in which 
  13959.       your part transforms the images it draws. 
  13960.  
  13961.      By creating a shell plug-in, a modification of the functions of the 
  13962.       document shell, you can add additional document-wide capabilities to 
  13963.       OpenDoc. 
  13964.  
  13965.      By patching (replacing) specific OpenDoc objects, you can modify some of 
  13966.       the fundamental capabilities of OpenDoc. 
  13967.  
  13968.  
  13969. ΓòÉΓòÉΓòÉ 12.1. OpenDoc Extension Interface ΓòÉΓòÉΓòÉ
  13970.  
  13971. You can greatly extend the capabilities of your parts, in terms of fast 
  13972. processing of information or communication with other parts, if you use the 
  13973. interface-extension capabilities of OpenDoc. The extension protocol allows 
  13974. parts or other OpenDoc objects to increase their capabilities by extending 
  13975. their programming interfaces. By using extension interfaces, your parts can 
  13976. communicate with other parts or other kinds of OpenDoc components in ways not 
  13977. possible with the standard OpenDoc programming interface. 
  13978.  
  13979. The Semantic Interface extension to OpenDoc, described in Semantic Events and 
  13980. Scripting, is an example of the use of extensions to support scripting. Other 
  13981. kinds of extension interfaces can be especially valuable in those situations 
  13982. where scripting cannot provide enough integration or bandwidth. 
  13983.  
  13984. You design, create, and attach such an extension to your part editor. At 
  13985. run-time, other parts can then access and use the extension interface, through 
  13986. calls to your parts. 
  13987.  
  13988.  
  13989. ΓòÉΓòÉΓòÉ 12.1.1. Extension Objects ΓòÉΓòÉΓòÉ
  13990.  
  13991. All subclasses of ODObject, including shapes, facets, documents, windows, 
  13992. frames, and parts, can be extended. An extension is itself an object, an 
  13993. instantiation of a subclass of ODExtension. Each extension object is related to 
  13994. its base object -the object whose interface it extends-by its extension name, 
  13995. an ISO type name. A caller accesses a base object's extension through that 
  13996. extension name. (Note that base object in this sense has nothing to do with 
  13997. inheritance; OpenDoc uses the term superclass to describe an ancestor in the 
  13998. class hierarchy). For example, the extension name for the semantic interface 
  13999. extension to a part is kODExtSemanticInterface. 
  14000.  
  14001. Extensible objects create and delete their own extensions and manage the 
  14002. extensions' storage. If desired, a base object can share an extension object 
  14003. among multiple clients, perhaps using a reference-counting scheme to decide 
  14004. when to delete the extensions. A caller can query an extensible object to see 
  14005. if it supports a specified extension. 
  14006.  
  14007. The ODExtension class itself has minimal functionality. It is designed to act 
  14008. as a superclass class for subclasses that implement actual extension 
  14009. interfaces. Every extension object knows what base object it is an extension of 
  14010. and forwards two kinds of calls to its base object: Release calls and calls to 
  14011. its own interface. 
  14012.  
  14013.  
  14014. ΓòÉΓòÉΓòÉ 12.1.2. Using an Extension ΓòÉΓòÉΓòÉ
  14015.  
  14016. To access the extension interface of an extensible part, a client, or caller, 
  14017. takes these steps: 
  14018.  
  14019.    1. It calls the part's override of its inherited HasExtension method to see 
  14020.       if the extension is supported, passing the part (the base object) an 
  14021.       extension name. 
  14022.  
  14023.    2. If the part has such an extension, the client then calls the part's 
  14024.       (override of its inherited) AcquireExtension method to get a reference to 
  14025.       the extension object. The part either creates the extension object or 
  14026.       increases its reference count (if the object already exists) and passes 
  14027.       the reference back to the client. 
  14028.  
  14029.    3. The client makes extension-interface calls directly to the extension 
  14030.       object. 
  14031.  
  14032.  When the client has finished using the services of the extension object, it 
  14033.  takes these steps: 
  14034.  
  14035.    1. The client calls the extension's (override of its inherited) Release 
  14036.       method, to let the extension know that the client no longer needs it. 
  14037.  
  14038.    2. The extension, in turn, calls the (override of the inherited) 
  14039.       ReleaseExtension method of its part (its base object) if its reference 
  14040.       count has dropped to 0. The base object can then delete the extension. 
  14041.  
  14042.       However, if the extension's base object has already been deleted and has 
  14043.       called the extension's BaseRemoved method (see Closing your Part), the 
  14044.       extension cannot call its base's ReleaseExtension method. 
  14045.  
  14046.  
  14047. ΓòÉΓòÉΓòÉ 12.1.3. Implementing Extensions ΓòÉΓòÉΓòÉ
  14048.  
  14049. Your part editors can implement any kinds of desired extension interfaces 
  14050. through this mechanism. The capabilities gained through extensions can be in 
  14051. almost any area. Examples include extensions to handle text search, 
  14052. spell-checking, linking, specialized text formatting, database access, and 
  14053. specialized graphics processing. In general, extension objects are best suited 
  14054. for tasks requiring high bandwidth or tight integration, for which scripting is 
  14055. not appropriate. 
  14056.  
  14057. If you implement an extension object for your part, the extension must include 
  14058. a SOM constructor (somInit), a SOM destructor (somUninit), and an 
  14059. initialization (InitExtension) method. The extension must also support a 
  14060. GetBase method, through which a client can obtain a reference to the 
  14061. extension's base object. (The ODExtension class provides a default 
  14062. implementation for GetBase). 
  14063.  
  14064. Note that your part is the factory for its extensions, which are 
  14065. reference-counted objects. You must follow the procedures described in Factory 
  14066. Methods when creating, managing, and deleting extensions. Also, if your part's 
  14067. document is closed while it has extensions remaining in memory, your part's 
  14068. ReleaseAll method must call the extensions' BaseRemoved method. 
  14069.  
  14070. An extension object must always be valid (attached to its base object) to be 
  14071. used. If a client tries to access an invalid extension, a 
  14072. kODErrInvalidExtension exception is generated. Any time after your part, as 
  14073. base object, calls its extension's BaseRemoved method, the extension is 
  14074. invalid. If you want to provide your own validation scheme for extensions, you 
  14075. need to override the ODExtension methods CheckValid, IsValid, and BaseRemoved. 
  14076.  
  14077. Your extension interfaces can be private to your parts, or you can establish or 
  14078. follow public standards. CI Labs is the agency responsible for coordinating 
  14079. standard extension interfaces for parts. For information on existing extension 
  14080. interfaces, or to propose new interfaces, please contact CI Labs at the address 
  14081. shown in Cross-Platform Consistency and CI Labs. 
  14082.  
  14083.  
  14084. ΓòÉΓòÉΓòÉ 12.2. The Settings Extension ΓòÉΓòÉΓòÉ
  14085.  
  14086. The Properties notebook (see Selection properties) is accessed by the user from 
  14087. the Document or View menu and displayed by the Info object (ODInfo class). The 
  14088. information that OpenDoc displays in a part's Properties notebook consists of 
  14089. the part's Info properties. Info properties are those properties in a part's 
  14090. storage unit, separate from the part's contents property, that are intended to 
  14091. be visible to the user. They include properties such as creation date and 
  14092. modification date (which cannot be changed by the user) as well as name and 
  14093. part kind (which can be changed by the user). 
  14094.  
  14095. The Properties notebook provides access to only the standard Info properties 
  14096. that all OpenDoc parts have. To define and allow access to Info properties 
  14097. specific to your part editor, you can create a Settings extension to display 
  14098. your own Properties notebook. 
  14099.  
  14100. When you select the menu choice to display your part's properties, the ODInfo 
  14101. object queries your part for an ODSettingsExtension by calling the HasExtension 
  14102. method with the extension name kODSettingsExtension. If a part provides an 
  14103. extension, AcquireExtension is called and your parts notebook are displayed. If 
  14104. your part does not provide one, the standard notebook is displayed. 
  14105.  
  14106. Your settings extension should be implemented as a subclass of the 
  14107. ODSettingsExtension class. ODSettingsExtension is itself a subclass of 
  14108. ODExtension. 
  14109.  
  14110.  
  14111. ΓòÉΓòÉΓòÉ 12.3. Custom Event Types ΓòÉΓòÉΓòÉ
  14112.  
  14113. You can extend OpenDoc's event-dispatching architecture to include new kinds of 
  14114. events by creating your own dispatch module. 
  14115.  
  14116.  
  14117. ΓòÉΓòÉΓòÉ 12.3.1. Creating a Dispatch Module ΓòÉΓòÉΓòÉ
  14118.  
  14119. The class ODDispatchModule is an abstract superclass. OpenDoc uses instances of 
  14120. a subclass of ODDispatchModule to dispatch certain types of events (such as 
  14121. keystroke events) to part editors. For normal program execution, you do not 
  14122. need to subclass ODDispatchModule or even access the existing dispatch module 
  14123. objects directly. Your interaction with OpenDoc regarding event dispatching is 
  14124. mainly through the dispatcher. 
  14125.  
  14126. You can, however, provide for dispatching of new types of events or messages to 
  14127. your part editor by subclassing ODDispatchModule. For example, you could create 
  14128. a dispatch module that handled events from an exotic input device such as a 3D 
  14129. glove for a virtual reality game. 
  14130.  
  14131. Patching the dispatcher 
  14132. It is possible to use custom dispatch modules to patch the functioning of the 
  14133. dispatcher in relation to all event types, although that is in general not 
  14134. recommended. In most cases there is no need for such drastic alteration of 
  14135. OpenDoc functionality. 
  14136.  
  14137. At run-time the dispatcher maintains a dictionary of installed dispatch 
  14138. modules, keyed by event type. When the dispatcher's Dispatch method is called, 
  14139. it looks up the dispatch module for the supplied event type and calls the 
  14140. Dispatch method of that module. 
  14141.  
  14142. When the standard OpenDoc dispatch module transforms an event of one type (such 
  14143. as a mouse-down in the menu bar) into an event of another type (such as an 
  14144. OpenDoc menu event), it passes the event back to the dispatcher for 
  14145. redispatching, by calling the dispatcher's Redispatch method. This 
  14146. redispatching allows your custom dispatch module to patch out the standard 
  14147. dispatch module for just those transformed events. 
  14148.  
  14149. If you subclass ODDispatchModule, you need to implement a SOM constructor 
  14150. (somInit), a SOM destructor (somUninit), and an initialization method. Your 
  14151. initialization method should call (but not override) the InitDispatchModule 
  14152. method of ODDispatchModule. 
  14153.  
  14154. Your dispatch module is responsible for performing the actual dispatching of 
  14155. events. The dispatcher calls your module's override of the Dispatch method, 
  14156. passing it the event information. 
  14157.  
  14158. You install the dispatch module by calling the AddDispatchModule method of the 
  14159. dispatcher; you remove a dispatch module by calling the RemoveDispatchModule 
  14160. method of the dispatcher. The installation might occur during the 
  14161. initialization of your part (or shell plug-in, if you create one). 
  14162.  
  14163. Your dispatch module should be installed just before your part will be handling 
  14164. events of the specified type, and removed right after your part is finished 
  14165. handling events of that type. If you are unable to add your dispatch module 
  14166. because another dispatch module already exists, you can still handle your 
  14167. events by doing the following: 
  14168.  
  14169.      Use GetDispatchModule to obtain the address of the existing dispatch 
  14170.       module 
  14171.  
  14172.      Remove the existing dispatch module (using its address) 
  14173.  
  14174.      Add your own dispatch module 
  14175.  
  14176.      Handle your events 
  14177.  
  14178.      Remove your dispatch module 
  14179.  
  14180.      Add the previous dispatch module back 
  14181.  
  14182.  
  14183. ΓòÉΓòÉΓòÉ 12.3.2. Using a Dispatch Module as a Monitor ΓòÉΓòÉΓòÉ
  14184.  
  14185. You can also use a dispatch module as a monitor, in which case it is notified 
  14186. of events of its kinds but does not have to dispatch them. You might use a 
  14187. monitor in debugging, for example, to capture all events and display a log of 
  14188. them in a window. 
  14189.  
  14190. You install a monitor with the dispatcher's AddMonitor method. For a given 
  14191. event, the dispatcher calls the Dispatch method for all installed monitors (of 
  14192. that event type) before calling the Dispatch method of the regular dispatch 
  14193. module for that event type. The dispatcher ignores the Boolean function result 
  14194. of the Dispatch method of all monitors; thus, unlike with normal use of a 
  14195. dispatch module, you can have more than one monitor for a single event type. 
  14196.  
  14197.  
  14198. ΓòÉΓòÉΓòÉ 12.4. Custom Focus Types ΓòÉΓòÉΓòÉ
  14199.  
  14200. You can extend OpenDoc's model for shared-resource arbitration by creating your 
  14201. own focus module, allowing your parts to recognize and negotiate ownership of 
  14202. new kinds of focus. 
  14203.  
  14204.  
  14205. ΓòÉΓòÉΓòÉ 12.4.1. Creating a Focus Module ΓòÉΓòÉΓòÉ
  14206.  
  14207. The class ODFocusModule is an abstract superclass. OpenDoc uses instances of a 
  14208. subclass of ODFocusModule to assign ownership of specific types of focus to 
  14209. part editors. For normal program execution, you do not need to subclass 
  14210. ODFocusModule or even access the existing focus module objects directly. Your 
  14211. interaction with OpenDoc regarding focus ownership is mainly through the 
  14212. arbitrator. 
  14213.  
  14214. You can, however, provide for new types of focus ownership, perhaps related to 
  14215. new types of peripheral devices or new classes of shared resources, by 
  14216. subclassing ODFocusModule. For example, if you provide an exotic input device 
  14217. such as a 3D glove for a virtual reality game, you could create a focus module 
  14218. that tracked the ownership of input from the glove. 
  14219.  
  14220. You define a new kind of focus to be handled by that focus module by creating 
  14221. an ISO string that is the name of the focus. As an example, the ISO string that 
  14222. defines the scrolling focus is "Scrolling"; that and other currently defined 
  14223. foci are listed in the table shown in Focus Types. Patching the arbitrator 
  14224. It is possible to use custom focus modules to patch the functioning of the 
  14225. arbitrator in relation to all types of focus, although that is in general not 
  14226. recommended. In most cases there is no need for such drastic alteration of 
  14227. OpenDoc functionality. 
  14228.  
  14229. If you subclass ODFocusModule, you need to implement a SOM constructor 
  14230. (somInit), a SOM destructor (somUninit), and an initialization method. Your 
  14231. initialization method should call (but not override) the InitFocusModule method 
  14232. of ODFocusModule. 
  14233.  
  14234. Your focus module is responsible for maintaining the identities of the 
  14235. individual frames that own the foci that your focus module manages. You must 
  14236. implement the methods AcquireFocusOwner, SetFocusOwnership, 
  14237. UnsetFocusOwnership, and TransferFocusOwnership, all called by the arbitrator 
  14238. to request or change the owner of a focus. 
  14239.  
  14240. You must also implement the methods BeginRelinquishFocus, 
  14241. CommitRelinquishFocus, and AbortRelinquishFocus, which your focus module uses 
  14242. in the two-stage process of relinquishing the ownership of a focus. The 
  14243. arbitrator calls these methods, and your focus module in turn calls the 
  14244. equivalent methods of the part that currently owns the focus. 
  14245.  
  14246. You install a focus module by calling the RegisterFocus method of the 
  14247. arbitrator; you remove it by calling the UnregisterFocus method of the 
  14248. arbitrator. 
  14249.  
  14250.  
  14251. ΓòÉΓòÉΓòÉ 12.4.2. Focus Modules for NonExclusive Foci ΓòÉΓòÉΓòÉ
  14252.  
  14253. The arbitrator and focus modules allow foci to be nonexclusive, meaning that a 
  14254. given focus can have more than one owner. As a possible example, if video input 
  14255. is provided, a focus module for video focus might track the part or parts that 
  14256. are currently receiving video input. 
  14257.  
  14258. If you create a focus module for nonexclusive foci, you must implement methods 
  14259. for testing exclusivity (IsFocusExclusive), and for allowing a caller to 
  14260. iterate over the owners of a focus (CreateOwnerIterator). 
  14261.  
  14262.  
  14263. ΓòÉΓòÉΓòÉ 12.5. Custom Transform Objects ΓòÉΓòÉΓòÉ
  14264.  
  14265. OpenDoc transform objects provide powerful transformational capabilities that 
  14266. are sufficient for most 2-dimensional drawing. With transforms, you can not 
  14267. only position your graphical objects, but you can also easily scale, rotate, 
  14268. and skew them. You can combine the operations of frame-internal transforms with 
  14269. those of facet-external transforms to achieve sophisticated effects with a 
  14270. minimum of code. 
  14271.  
  14272. If you need to extend the power of transform objects even further, you can 
  14273. obtain the extra capability most efficiently by creating your own transform 
  14274. subclass. If you need to provide for nonlinear transformations (such as curved 
  14275. projections or sophisticated perspective effects), you can implement them as 
  14276. new methods and as overrides to the methods of ODBaseTransform, the superclass 
  14277. of ODTransform. 
  14278.  
  14279. If you subclass ODBaseTransform, you must override at least the following 
  14280. methods: 
  14281.  
  14282.      Copy 
  14283.      CopyFrom 
  14284.      GetMatrix (must throw the ODErrTransformErr exception) 
  14285.      GetMATRIXLF (must throw the ODErrTransformErr exception) 
  14286.      HasMatrix (must return kODFalse) 
  14287.      Invert 
  14288.      InvertPoint 
  14289.      InvertShape 
  14290.      PostCompose 
  14291.      PreCompose 
  14292.      ReadFrom 
  14293.      Reset 
  14294.      TransformPoint 
  14295.      TransformPoints 
  14296.      TransformShape 
  14297.      WriteTo 
  14298.  
  14299.  For more information on matrices and transformations in two-dimensional 
  14300.  drawing, you can consult any standard computer-graphics textbook, such as 
  14301.  Computer Graphics Principles and Practice, 2nd ed., by Foley, vanDam, Feiner, 
  14302.  and Hughes (Addison-Wesley, 1990). 
  14303.  
  14304.  
  14305. ΓòÉΓòÉΓòÉ 12.6. Shell Plug-Ins ΓòÉΓòÉΓòÉ
  14306.  
  14307. You can extend the capabilities of the document shell or add session-wide 
  14308. functionality to OpenDoc by implementing shell plug-ins. Shell plug-ins are 
  14309. shared libraries, rather than subclasses of ODExtension. A shell plug-in is not 
  14310. associated with any particular part object. 
  14311.  
  14312. Your shell plug-in must be installed on the user's machine when a document 
  14313. first opens, if it is to be used with that document. When called by the 
  14314. document shell, your plug-in can add its own dispatch modules or focus modules, 
  14315. add entries to name spaces, or even patch the session-level objects such as the 
  14316. clipboard, as described later in this chapter. 
  14317.  
  14318. A shell plug-in has a single exported entry point (its Install function). 
  14319. Execution of a shell plug-in happens like this: 
  14320.  
  14321.    1. Whenever the user opens an OpenDoc document, OpenDoc launches the 
  14322.       document shell. The document shell initializes itself and the session 
  14323.       object, and gains access to the document's current draft. 
  14324.  
  14325.    2. The document shell then accesses each plug-in library and calls its 
  14326.       Install function. The Install function performs the functions the plug-in 
  14327.       is designed for, and exits. 
  14328.  
  14329.    3. After all plug-ins have executed, the root part of the OpenDoc document 
  14330.       then opens the document window. Your plug-in library needs to implement 
  14331.       only an Install function, with this interface: 
  14332.  
  14333.             void ODShellPlugInInstall(Environment *ev,
  14334.                                       ODDraft *draft
  14335.                                       ODShellPlugInActionCodes *action);
  14336.  
  14337.  Your Install function should perform whatever tasks the library was designed 
  14338.  to perform: installing custom focus modules or dispatch modules, patching 
  14339.  session-level objects, or otherwise modifying shell functionality. 
  14340.  
  14341.  
  14342. ΓòÉΓòÉΓòÉ 12.7. Patching OpenDoc ΓòÉΓòÉΓòÉ
  14343.  
  14344. Besides implementing the extension interfaces, dispatch modules, and focus 
  14345. modules discussed earlier in this chapter, you can enhance or alter the 
  14346. functioning of OpenDoc in another way. Because OpenDoc is modular and 
  14347. object-oriented, you can directly replace certain of its objects with your own 
  14348. versions. 
  14349.  
  14350. OpenDoc allows you to patch any of its session-level objects. The session-level 
  14351. objects are those directly referenced by the session object, as shown in the 
  14352. figure presented in Session Object. They are represented by these OpenDoc 
  14353. classes: 
  14354.  
  14355.      ODArbitrator 
  14356.      ODInfo 
  14357.      ODSemanticInterface subclass 
  14358.       (The document shell's semantic interface) 
  14359.      ODBinding 
  14360.      ODClipboard 
  14361.      ODDispatcher 
  14362.      ODDragAndDrop 
  14363.      ODLinkManager 
  14364.      ODMessageInterface 
  14365.      ODNameResolver 
  14366.      ODNameSpaceManager 
  14367.      ODStorageSystem 
  14368.      ODTranslation 
  14369.      ODUndo 
  14370.      ODWindowState 
  14371.  
  14372.  This section discusses the mechanics of writing a patch to a session-level 
  14373.  object, but it does not discuss the capabilities of the individual objects or 
  14374.  why you would want to patch one. Before patching any object, be sure you are 
  14375.  very familiar with its purpose and its interface; see information elsewhere in 
  14376.  this book for more information. 
  14377.  
  14378.  
  14379. ΓòÉΓòÉΓòÉ 12.7.1. Writing a Patch ΓòÉΓòÉΓòÉ
  14380.  
  14381. Because your OpenDoc patch replaces a specific object with a known public 
  14382. interface, you should write it as a subclass of the class of object you are 
  14383. patching. You must override every method, and your overrides (other than 
  14384. somInit, somUninit, and your initialization method) should not call their 
  14385. inherited versions. If you want only partial replacement of OpenDoc's 
  14386. functionality, delegate to the patched-out object (the one you have replaced) 
  14387. those methods that you do not wish to change. 
  14388.  
  14389. Immediately after creating your replacement object, your patch installer should 
  14390. call the object's initialization method (InitClassName). For example, if you 
  14391. are replacing the drag-and-drop object, you would call your replacement 
  14392. object's InitDragAndDrop method immediately after calling new to create it. 
  14393.  
  14394. Your initialization method should call the GetClassName method of the session 
  14395. object to get a reference to the current object, and store that reference in a 
  14396. field. For the drag-and-drop example, your InitDragAndDrop method would call 
  14397. the session object's GetDragAndDrop method, and store the returned reference in 
  14398. a field such as fOldDragAndDrop. 
  14399.  
  14400. At the end of initialization, your InitClassName method should assign the 
  14401. replacement object as the current object, by calling the SetClassName method of 
  14402. the session object and passing itself (somSelf) as the new object reference. 
  14403.  
  14404. Your destructor method (somUninit) should delete the patched-out object (the 
  14405. one referenced in the fOldDragAndDrop field, for example) before calling 
  14406. inherited somUninit. 
  14407.  
  14408. If the object you are replacing has additional entry points besides those based 
  14409. on the session object's reference to it, you will need to patch those also. For 
  14410. example, the drag-and-drop object registers callbacks with the Drag Manager; 
  14411. your replacement object would have to re-register those callbacks to point to 
  14412. itself. 
  14413.  
  14414.  
  14415. ΓòÉΓòÉΓòÉ 12.7.2. Installing a Patch ΓòÉΓòÉΓòÉ
  14416.  
  14417. Once you have written your patch, you need to install it so that OpenDoc uses 
  14418. it in place of the original object. Depending on what your patching needs are, 
  14419. you can place your patch installer in either of two places. 
  14420.  
  14421.      If the scope of your patch needs to be global (applied to all OpenDoc 
  14422.       documents), make your patch installer a Shell plug-in (see Shell 
  14423.       Plug-Ins). Install the patch within your plug-in's Install method. 
  14424.  
  14425.      If the scope of your patch is confined to the document containing your 
  14426.       part, you can use your part editor's Open method to install the patch. 
  14427.       Only the root part of a document can install an OpenDoc patch. 
  14428.  
  14429.  When called, your installer instantiates and initializes the patch object. 
  14430.  
  14431.  Potential patch conflicts 
  14432.  Every time it opens a document, the document shell installs, in order, all 
  14433.  shell plug-ins, and then the root part opens its window. This can lead to 
  14434.  patching conflicts; because you do not control the order in which shell 
  14435.  plug-ins are installed, you cannot ensure that your patch will not itself be 
  14436.  patched out by a subsequently installed patch. Ultimately, the root part 
  14437.  controls which patches remain, because it has the final opportunity to install 
  14438.  its own patches.