home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ctcoll95.zip / RAHMEN / PART_MAC.SEA / CPRedPart.cpp next >
Text File  |  1995-03-24  |  43KB  |  1,483 lines

  1. /*
  2.     File:        CPRedPart.cpp
  3.  
  4.     Contains:    CPRedPart OpenDoc part editor class implementation.
  5.                 Built using PartMaker, then modified by JÜrn Loviscach,
  6.                 c╒t Magazin fƒr Computertechnik
  7.  
  8.     Written by:    Tantek éelik, Eric Soldan, Jens Alfke, AND PartMaker 
  9. */
  10.  
  11. #ifndef _ALTPOINT_
  12. #include <AltPoint.h>
  13. #endif
  14.  
  15. #ifndef _CPREDPART_
  16. #include "CPRedPart.h"
  17. #endif
  18.  
  19. #ifndef _PARTUTILS_
  20. #include "PartUtils.h"
  21. #endif
  22.  
  23. #ifndef _REDPARTDEF_
  24. #include "RedPartDef.h"
  25. #endif
  26.  
  27. #ifndef _USERSRCM_
  28. #include <UseRsrcM.h>
  29. #endif
  30.  
  31. #ifndef _INFOUTIL_
  32. #include <InfoUtil.h>
  33. #endif
  34.  
  35. #ifndef _ITEXT_
  36. #include <IText.h>
  37. #endif
  38.  
  39. #ifndef SOM_ODDraft_xh
  40. #include <Draft.xh>
  41. #endif
  42.  
  43. #ifndef SOM_ODArbitrator_xh
  44. #include <Arbitrat.xh>
  45. #endif
  46.  
  47. #ifndef SOM_ODCanvas_xh
  48. #include <Canvas.xh>
  49. #endif
  50.  
  51. #ifndef SOM_ODPart_xh
  52. #include <Part.xh>
  53. #endif
  54.  
  55. #ifndef SOM_ODFacet_xh
  56. #include <Facet.xh>
  57. #endif
  58.  
  59. #ifndef SOM_ODFrame_xh
  60. #include <Frame.xh>
  61. #endif
  62.  
  63. #ifndef SOM_ODFrameFacetIterator_xh
  64. #include <FrFaItr.xh>
  65. #endif
  66.  
  67. #ifndef SOM_ODFoci_xh
  68. #include <Foci.xh>
  69. #endif
  70.  
  71. #ifndef SOM_ODInfo_xh
  72. #include <Info.xh>
  73. #endif
  74.  
  75. #ifndef SOM_ODPstObj_
  76. #include <PstObj.xh>
  77. #endif
  78.  
  79. #ifndef SOM_ODShape_xh
  80. #include <Shape.xh>
  81. #endif
  82.  
  83. #ifndef SOM_ODStdProps_xh
  84. #include <StdProps.xh>
  85. #endif
  86.  
  87. #ifndef SOM_ODStdTypes_xh
  88. #include <StdTypes.xh>
  89. #endif
  90.  
  91. #ifndef _STDDEFS_
  92. #include <StdDefs.h>
  93. #endif
  94.  
  95. #ifndef _PLFMDEF_
  96. #include <PlfmDef.h>
  97. #endif
  98.  
  99. #ifndef SOM_ODCmdDefs_xh
  100. #include <CmdDefs.xh>
  101. #endif
  102.  
  103. #ifndef SOM_ODStorageU_xh
  104. #include <StorageU.xh>
  105. #endif
  106.  
  107. #ifndef SOM_ODTrnsform_xh
  108. #include <Trnsform.xh>
  109. #endif
  110.  
  111. #ifndef SOM_ODFocusSet_xh
  112. #include <FocusSet.xh>
  113. #endif
  114.  
  115. #ifndef SOM_ODFoci_xh
  116. #include <Foci.xh>
  117. #endif
  118.  
  119. #ifndef SOM_ODMenuBar_xh
  120. #include <MenuBar.xh>
  121. #endif
  122.  
  123. #ifndef SOM_ODWindow_xh
  124. #include <Window.xh>
  125. #endif
  126.  
  127. #ifndef SOM_ODWinStat_xh
  128. #include <WinStat.xh>
  129. #endif
  130.  
  131. #ifndef SOM_ODSession_xh
  132. #include <ODSessn.xh>
  133. #endif
  134.  
  135. #ifndef _PASCLSTR_
  136. #include <PasclStr.h>
  137. #endif
  138.  
  139. #ifndef _FOCUSLIB_
  140. #include <FocusLib.h>
  141. #endif
  142.  
  143. #ifndef __ERRORS__
  144. #include <Errors.h>
  145. #endif
  146.  
  147. #ifndef __RESOURCES__
  148. #include <Resources.h>
  149. #endif
  150.  
  151. #ifndef __DIALOGS__
  152. #include <Dialogs.h>
  153. #endif
  154.  
  155. #ifndef __TOOLUTILS__
  156. #include <ToolUtils.h>
  157. #endif
  158.  
  159.  
  160. //====================================================================
  161. // Miscellaneous
  162. //====================================================================
  163.  
  164.  
  165. #if qDebug
  166.     #define     WeBeHere(StringPtr) DebugStr(StringPtr)
  167. #else
  168.     #define     WeBeHere(StringPtr)
  169. #endif
  170.  
  171.  
  172. #ifdef applec
  173. #pragma segment RedPart
  174. #endif
  175.  
  176.  
  177. ODSession* gSession = kODNULL;
  178.  
  179.  
  180.  
  181. //====================================================================
  182. // Constants
  183. //====================================================================
  184.  
  185.  
  186.  
  187. const short kContentStringResID = 5000;
  188. const short kContentStringID    = 1;
  189. const short kAboutTextID        = 2;
  190. const short kShowPartsBinID     = 3;
  191. const short kHidePartsBinID     = 4;
  192.  
  193.  
  194.  
  195. //====================================================================
  196. // CPRedPart
  197. //====================================================================
  198.  
  199.  
  200.  
  201. //--------------------------------------------------------------------
  202. // CPRedPart::CPRedPart
  203. //--------------------------------------------------------------------
  204.  
  205. CPRedPart::CPRedPart()
  206. {
  207.     WeBeHere("\pCPRedPart::CPRedPart");
  208.  
  209.     fDirty    = kODFalse;
  210.     fWindowID = 0;
  211.     fSession  = kODNULL;
  212.     fMenuBar  = kODNULL;
  213.  
  214.     fPartsBinWin  = 0;
  215.     fPartsBinOpen = kODFalse;
  216.  
  217.     // Note that fFacetList is a static field, and therefore
  218.     // its constructor is automatically called before
  219.     // CPRedPart constructor.
  220. }
  221.  
  222.  
  223.  
  224. //--------------------------------------------------------------------
  225. // CPRedPart::~CPRedPart
  226. //--------------------------------------------------------------------
  227.  
  228. CPRedPart::~CPRedPart()
  229. {
  230.     WeBeHere("\pCPRedPart::~CPRedPart");
  231. }
  232.  
  233.  
  234.  
  235. //--------------------------------------------------------------------
  236. // CPRedPart::InitPart
  237. //--------------------------------------------------------------------
  238.  
  239. void CPRedPart::InitPart(Environment* ev, ODStorageUnit* storageUnit, ODPart* partWrapper)
  240.  
  241. // Called by the draft object.
  242.  
  243. {
  244.     WeBeHere("\pCPRedPart::InitPart");
  245.  
  246.     fPartWrapper = partWrapper;        // Will very much need this later.
  247.  
  248.     this->MyCommonInitPart(ev);        // We say "this" everywhere just to be explicit.
  249.  
  250.     storageUnit->AddProperty(ev, kODPropContents)->AddValue(ev, kRedPartKind);
  251.         // For your edification, AddProperty & AddValue 
  252.         // implicitly focus.  Check the API for more info.
  253.  
  254.     {
  255.         CUsingLibraryResources fil;
  256.         //::GetIndString(fTextData, kContentStringResID, kContentStringID); //gestrichen, jl
  257.     }        // Use CUsingLibraryResources to use your part's resource fork.
  258.             // Make it go out of scope when you are done.
  259.             // We are creating our part's initial content here.
  260.  
  261.  
  262.     // Initialize your other fields here.
  263.  
  264.     fDirty = kODTrue;
  265.     
  266.     this->fCount = 0L;//eingefƒgt, jl
  267. }
  268.  
  269.  
  270.  
  271. //--------------------------------------------------------------------
  272. // CPRedPart::InitPartFromStorage
  273. //--------------------------------------------------------------------
  274.  
  275. void CPRedPart::InitPartFromStorage(Environment* ev, ODStorageUnit* storageUnit, ODPart* partWrapper)
  276.  
  277. // Called by the draft object.
  278.  
  279. {
  280.     WeBeHere("\pCPRedPart::InitPartFromStorage");
  281.  
  282.     fPartWrapper = partWrapper;        // Will very much need this later.
  283.  
  284.     this->MyCommonInitPart(ev);
  285.     storageUnit->Focus(ev, kODPropContents, kODPosSame,
  286.                        kRedPartKind, 0, kODPosSame);
  287.     //fTextData[0] = (unsigned char)storageUnit->GetSize(ev);
  288.     storageUnit->GetValue(ev, sizeof(long), &(this->fCount)); //geèndert, jl
  289. }
  290.  
  291.  
  292.  
  293. //--------------------------------------------------------------------
  294. // CPRedPart::MyCommonInitPart
  295. //--------------------------------------------------------------------
  296.  
  297. void CPRedPart::MyCommonInitPart(Environment* ev)
  298. {
  299.     WeBeHere("\pCPRedPart::MyCommonInitPart");
  300.  
  301.     fSession = fPartWrapper->GetStorageUnit(ev)->GetSession(ev);
  302.         // As your part grows, add your initialization that is common
  303.         // between InitPart and InitPartFromStorage here.
  304.         // Note that GetStorageUnit can be used, since just prior to
  305.         // calling this method, InitPart calledInitPersistentObject or
  306.         // InitPartFromStorage called InitPersistentObjectFromStorage.
  307.  
  308.     fSelectionFocus = fSession->Tokenize(ev, kODSelectionFocus);
  309.     fMenuFocus      = fSession->Tokenize(ev, kODMenuFocus);
  310.     fKeyFocus       = fSession->Tokenize(ev, kODKeyFocus);
  311.     fModalFocus     = fSession->Tokenize(ev, kODModalFocus);
  312.  
  313.     fFocusSet = new ODFocusSet();
  314.     fFocusSet->InitFocusSet(ev);
  315.     fFocusSet->Add(ev, fKeyFocus);
  316.     fFocusSet->Add(ev, fMenuFocus);
  317.     fFocusSet->Add(ev, fSelectionFocus);
  318.  
  319.     fMenuBar = fSession->GetWindowState(ev)->CopyBaseMenuBar(ev);
  320.  
  321.     {
  322.         CUsingLibraryResources fil;
  323.         fMenu = ::GetMenu(kMenuID);
  324.         if (fMenu)
  325.             ::DetachResource((Handle)fMenu);        // Must detach it!
  326.     }
  327.  
  328.     if (!fMenu)
  329.         DebugStr("\pCPRedPart::MyCommonMyInitPart -- couldn't create menu.");
  330.             // Note that THROW, while valid under the temporary ASLM
  331.             // implementation of OpenDoc, won't be correct when OpenDoc
  332.             // is converted to SOM.  Therefore we are using debug messages
  333.             // for these types of errors.  When SOM is available, this issue
  334.             // will be addressed correctly.
  335.  
  336.  
  337.     fMenuBar->AddMenuLast(ev, kMenuID, fMenu, fPartWrapper);
  338. }
  339.  
  340.  
  341.  
  342. //--------------------------------------------------------------------
  343. // CPRedPart::Externalize
  344. //--------------------------------------------------------------------
  345.  
  346. void    CPRedPart::Externalize(Environment* ev)
  347. {
  348.     WeBeHere("\pCPRedPart::Externalize");
  349.  
  350.     if (fDirty != kODFalse)
  351.     {
  352.         ODStorageUnit* storageUnit = fPartWrapper->GetStorageUnit(ev);
  353.             // Get the reference to where we are writing to.
  354.  
  355.         storageUnit->Focus(ev, kODPropContents, kODPosSame, kRedPartKind, 0, kODPosSame);
  356.             // First we focus on the property we want to write out.
  357.  
  358.         storageUnit->SetValue(ev, sizeof(long), &(this->fCount)); //geèndert, jl
  359.             // Now we write out the property.
  360.  
  361.         fDirty = kODFalse;
  362.             // Flag our part as no longer being dirty.
  363.     }
  364. }
  365.  
  366.  
  367.  
  368. //-------------------------------------------------------------------------
  369. // CPRedPart::MySetDirty
  370. //-------------------------------------------------------------------------
  371.  
  372. void CPRedPart::MySetDirty(Environment* ev)
  373. {
  374.     fDirty = kODTrue;
  375.     fPartWrapper->GetStorageUnit(ev)->GetDraft(ev)->SetChangedFromPrev(ev);
  376. }
  377.  
  378.  
  379.  
  380. //-------------------------------------------------------------------------
  381. // CPRedPart::Purge
  382. //-------------------------------------------------------------------------
  383.  
  384. ODSize CPRedPart::Purge(Environment* ev, ODSize size)
  385. {
  386. ODUnused(size);
  387.     WeBeHere("\pCPRedPart::Purge");
  388.     
  389.     // CPRedPart doesn't do anything here.
  390.  
  391.     return 0;
  392. }
  393.  
  394.  
  395.  
  396. //-------------------------------------------------------------------------
  397. // CPRedPart::Release
  398. //-------------------------------------------------------------------------
  399.  
  400. void CPRedPart::Release(Environment* ev)
  401. {
  402.     WeBeHere("\pCPRedPart::Release");
  403.  
  404.     // ÑÑ╩6/23/94
  405.     //
  406.     // If you are using RegisterIdle on the part, not on frames, then
  407.     // the RefCount is bumped up by one by OpenDoc.  OpenDoc keeps a
  408.     // reference to all parts that register idle time.  ALL OF THESE MUST
  409.     // BE RESOLVED BEFORE THE DESTRUCTOR IS CALLED.  This is
  410.     // the place to do that.
  411.  
  412.     // The logic below, assuming that CPRedPart has registered for idle
  413.     // time, is that if the RefCount is 1, then we are here to unregister
  414.     // the idle.  When the part is being removed, OpenDoc must decrement
  415.     // the RefCount and call Release until the part gets messaged with
  416.     // a RefCount of 0.  Once you return from here with a RefCount of 0,
  417.     // OpenDoc will call the destructor.
  418.  
  419.     // This means that if you have registered for idle time, Release will
  420.     // be called TWICE when closing down your part.  The first time the
  421.     // RefCount is 1.  This is when you should unregister the idle time.
  422.     // When you are called with a RefCount of 0, that when it gets really
  423.     // serious.  This is when you detach from the draft.
  424.  
  425.     if (fPartWrapper->GetRefCount(ev) == 1) {
  426.         // Here is where you would unregister idle time for the part if
  427.         // have registered time.  Note that if you unregister without
  428.         // registering, OpenDoc will crash.  It's not just a simple
  429.         // look-up-and-if-there-remove kind of operation.
  430.  
  431.         // Note that if you unregister idle here, OpenDoc will need to
  432.         // call Release (here) due to it.  This means that when we call
  433.         // to unregister the idle, we are nesting calls to Release.
  434.         // Due to this, I return out of each case, just to make the
  435.         // flow of control of the call(s) to Release more straightforward.
  436.  
  437.         // Note that if you are going to use idle registration, you will
  438.         // need to include "Disptch.h"
  439.  
  440.         return;
  441.     }
  442. }
  443.  
  444.  
  445.  
  446. //--------------------------------------------------------------------
  447. // CPRedPart::Open
  448. //--------------------------------------------------------------------
  449.  
  450. ODID  CPRedPart::Open(Environment* ev, ODFrame* frame)
  451.  
  452. // Creates and opens a presentation of the part in a frame
  453. // in a new window.
  454. //
  455. // This method adds this part as the root part of the window.
  456. // It bases the presentation in the new frame on the presentation
  457. // in the old frame, or on a default presentation if there
  458. // is no old frame.
  459.  
  460. {
  461.     WeBeHere("\pCPRedPart::Open");
  462.  
  463.     ODWindow*    window = kODNULL;
  464.  
  465.     if (frame)
  466.         window = fSession->GetWindowState(ev)->GetWindow(ev, fWindowID);
  467.  
  468.     if (window == kODNULL)
  469.     {
  470.         window = this->MyMakeWindow(ev, frame);
  471.         fWindowID = window->GetID(ev);
  472.         window->Open(ev);
  473.         window->Show(ev);
  474.     }
  475.  
  476.     window->Select(ev);
  477.  
  478.     return window->GetID(ev);
  479. }
  480.  
  481.  
  482.  
  483. //--------------------------------------------------------------------
  484. // CPRedPart::ReleaseAll
  485. //--------------------------------------------------------------------
  486.  
  487. void    CPRedPart::ReleaseAll(Environment* ev)
  488. {
  489.     WeBeHere("\pCPRedPart::ReleaseAll");
  490.  
  491.     if (fMenuBar != kODNULL)
  492.         fMenuBar->Release(ev);
  493. }
  494.  
  495.  
  496.  
  497. //--------------------------------------------------------------------
  498. // CPRedPart::MyWantResizable
  499. //--------------------------------------------------------------------
  500.  
  501. ODBoolean CPRedPart::MyWantResizable()
  502. {
  503.     return kODFalse;
  504.         // used in MyMakeWindow() to toggle some parameters
  505. }
  506.  
  507.  
  508. //--------------------------------------------------------------------
  509. // CPRedPart::MyMakeWindow
  510. //--------------------------------------------------------------------
  511.  
  512. ODWindow*    CPRedPart::MyMakeWindow(Environment* ev, ODFrame* sourceFrame)
  513. {
  514.     WeBeHere("\pCPRedPart::MyMakeWindow");
  515.  
  516.     Rect                windRect;
  517.     ODPlatformWindow    platformWindow = kODNULL;
  518.     ODWindow*            window = kODNULL;
  519.     
  520.     if (sourceFrame)
  521.     {
  522.         SetRect(&windRect, 100, 100, 300, 300);    
  523.     }
  524.     else
  525.     {
  526.         const ODSShort        kOnePageWidth = 600;
  527.  
  528.         ::SetRect(&windRect, 4, GetMBarHeight() + 24,
  529.                 ODQDGlobals.screenBits.bounds.right - 64,
  530.                 ODQDGlobals.screenBits.bounds.bottom - 4);
  531.         
  532.         if (windRect.right - windRect.left > kOnePageWidth)
  533.             windRect.right = windRect.left + kOnePageWidth;
  534.     }
  535.  
  536.     Str255        windowTitleStr;
  537.     ODName*    partName = ODGetPOName(fPartWrapper, kODNULL);
  538.     IntlToPStr(partName, (StringPtr)&windowTitleStr);
  539.     DisposeIText(partName);
  540.  
  541.     platformWindow = ::NewCWindow
  542.     (
  543.         kODNULL,
  544.         &windRect,
  545.         windowTitleStr,
  546.         false,
  547.         this->MyWantResizable() ? zoomDocProc : zoomNoGrow,
  548.         (WindowPtr)-1L,
  549.         true,
  550.         kODNULL
  551.     );
  552.  
  553.     window = fSession->GetWindowState(ev)->RegisterWindow
  554.     (
  555.         ev,
  556.         platformWindow,                                // newWindow
  557.         kODNULL,                                    // frameType
  558.         (sourceFrame == kODNULL),                    // isRootWindow
  559.         this->MyWantResizable(),                    // isResizable
  560.         kODFalse,                                    // isFloating
  561.         kODTrue,                                    // shouldSave
  562.         fPartWrapper,                                // rootPart
  563.         fSession->Tokenize(ev, kODViewAsFrame),        // viewType
  564.         kODNullTypeToken,                            // presentation
  565.         sourceFrame                                    // sourceFrame
  566.     );
  567.  
  568.     return window;
  569. }
  570.  
  571.  
  572.  
  573. //--------------------------------------------------------------------
  574. // CPRedPart::Draw
  575. //--------------------------------------------------------------------
  576.  
  577. void CPRedPart::Draw(Environment* ev, ODFacet* facet, ODShape* invalidShape)
  578.  
  579. // Draws the part in the facet, updating the portion of the
  580. // facet in the invalidShape.
  581. //
  582. // Called by the facet object.
  583. //
  584. // The part should draw itself on the facet's canvas. The part
  585. // must examine its canvas' isDynamic flag to determine if it
  586. // will be drawing on the screen or to a printer, and then draw
  587. // itself appropriately.
  588. //
  589. // Draw the part in the given facet. Only the portion in the
  590. // invalidShape needs to be drawn.
  591. //
  592. // There are several steps a part needs to take to perform the
  593. // imaging.
  594. // 1) The part should look at the given facet and its frame.
  595. //    Both the frame and the facet may have some partInfo that
  596. //    the part has placed there, which the part can use to
  597. //    decide how it will display itself.  The frame also has
  598. //    viewType and presentation fields, which indicate what kind
  599. //    of view of the part should display.
  600. // 2) The part should examine its canvas to see how it should
  601. //    be imaged. The canvas can be obtained from the facet via
  602. //    ODFacet::GetCanvas(). If the canvas╒ isDynamic flag is
  603. //    kODTrue, the part is imaging onto a dynamic device like
  604. //    a CRT; otherwise, it is imaging to a static device like
  605. //    a printer. The part will probably display its content
  606. //    differently for static and dynamic views. For instance,
  607. //    it should not display scroll bars on a static canvas.
  608. // 3) The part must make sure the platform graphics system is
  609. //    prepared to draw into the correct context for the facet.
  610. //    On the Macintosh using QuickDraw, it is necessary to call
  611. //    SetPort() for the appropriate canvas, and set up other
  612. //    attributes of the drawing environment. A FocusLib library
  613. //    is supplied to help focus drawing commands to a facet.
  614. //    Make sure to clip to the facet╒s clipShape (FocusLib
  615. //    does this for you).
  616. // 4) Draw the part╒s contents.
  617. // 5) Restore the old graphics environment.
  618. //
  619. // Part editors may sometimes need to display their parts
  620. // asynchronously, that is, not in response to a ::Draw() call.
  621. // This process is very similar to the basic drawing recipe,
  622. // with minor modifications.
  623. // 1) Determine which of the part╒s frames should be drawn. A part
  624. //    may have multiple display frames, and more than one may need
  625. //    updating. Parts store their display frames in whatever way
  626. //    they want, so we can╒t tell you how to find them here.
  627. // 2) For each frame being displayed, all facets must be drawn.
  628. //    ODFrame::CreateFrameFacetIterator() returns an iterator
  629. //    which will list all the facets of a frame. Draw the part╒s
  630. //    contents in each of these facets, using the recipe above.
  631. // 3) After drawing in a facet, call ODFacet::DrawnIn() on it to
  632. //    tell it you╒ve drawn in it asynchronously. If the facet is
  633. //    on an offscreen canvas, this lets it get copied into the window. 
  634.  
  635. {
  636.     WeBeHere("\pCPRedPart::Draw");
  637.     ODUnused(invalidShape);
  638.  
  639.     CFocus    foc(ev, facet);
  640.  
  641.     ODFrame*    frame     = facet->GetFrame(ev);
  642.     ODShape*    usedShape = frame->GetUsedShape(ev, kODNULL);
  643.     RgnHandle    rgn       = usedShape->GetQDRegion(ev);
  644.  
  645.     usedShape->Release(ev);
  646.  
  647.  
  648.     Rect        rct     = (*rgn)->rgnBBox;
  649.     RgnHandle    oldClip = nil;
  650.     RgnHandle    newClip;
  651.  
  652.     ::ForeColor(redColor); //ab hier geèndert, jl
  653.     ::PaintRect(&rct);
  654.     
  655.     ::PenNormal();
  656.     ::ForeColor(blackColor);
  657.     Str255 text;
  658.     ::NumToString(this->fCount, text);
  659.     short x = (rct.right - rct.left - ::StringWidth(text)) / 2;
  660.     short y = (rct.bottom - rct.top - 12) / 2;
  661.     ::MoveTo(x, y);
  662.     ::DrawString(text);
  663.  
  664.     if (oldClip) {
  665.         ::SetClip(oldClip);
  666.         ::DisposeRgn(oldClip);
  667.     }
  668. }
  669.  
  670.  
  671.  
  672. //====================================================================
  673. // PartsBin
  674. //====================================================================
  675.  
  676. void CPRedPart::MyShowPartsBin(Environment* ev, ODFrame* frame)
  677. {
  678.     WeBeHere("\pCPRedPart::MyShowPartsBin");
  679.     ODPart*                partsbin;
  680.     ODStorageUnit*        su = fPartWrapper->GetStorageUnit(ev);
  681.     ODStorageUnit*        pbSU;
  682.     ODStorageUnitRef    pbSURef;
  683.     ODStorageUnitID        pbSUID;
  684.     
  685.     if (su->Exists(ev, kODPropPartsBin,kODStrongStorageUnitRef,0))
  686.     {
  687.         su->Focus(ev, kODPropPartsBin,kODPosSame,kODStrongStorageUnitRef,1,kODPosFirstSib);
  688.         su->SetOffset(ev, 0);
  689.         su->GetValue(ev, sizeof(kODStrongStorageUnitRef), (ODValue)&pbSURef);
  690.         
  691.         pbSUID = su->GetIDFromStorageUnitRef(ev, pbSURef);
  692.         partsbin = su->GetDraft(ev)->GetPart(ev, pbSUID);
  693.     }
  694.     else
  695.     {
  696.         su->AddProperty(ev, kODPropPartsBin)->AddValue(ev, kODStrongStorageUnitRef);
  697.  
  698.         partsbin = su->GetDraft(ev)->CreatePart(ev, kODKindPartsBin, kODNULL);
  699.         if (partsbin != kODNULL)
  700.         {
  701.             pbSU    = partsbin->GetStorageUnit(ev);
  702.             pbSURef = su->GetStrongStorageUnitRef(ev, pbSU->GetID(ev));
  703.  
  704.             su->SetValue(ev, sizeof(kODStrongStorageUnitRef), (ODValue)&pbSURef);
  705.         }
  706.         else {
  707.             DebugStr("\pCannot Create Parts Bin");
  708.         }
  709.     }
  710.     
  711.     fPartsBinWin = partsbin->Open(ev, frame);
  712.     partsbin->Release(ev);
  713.     fPartsBinOpen = kODTrue;
  714. }
  715.  
  716. void CPRedPart::MyHidePartsBin(Environment* ev)
  717. {
  718.     WeBeHere("\pCPRedPart::MyHidePartsBin");
  719.     if (fPartsBinOpen && fPartsBinWin)
  720.     {
  721.         ODWindow* pbWin = fSession->GetWindowState(ev)->GetWindow(ev, fPartsBinWin);
  722.  
  723.         if (pbWin != kODNULL) 
  724.             pbWin->Hide(ev);
  725.         else
  726.             DebugStr("\pCannot Hide Parts Bin");
  727.  
  728.         fPartsBinOpen = kODFalse;
  729.     }
  730. }
  731.  
  732.  
  733.  
  734. //-------------------------------------------------------------------------
  735. // UI Events protocol
  736. //-------------------------------------------------------------------------
  737.  
  738. ODBoolean CPRedPart::HandleEvent(Environment* ev, ODEventData* event,
  739.                                      ODFrame* frame, ODFacet* facet)
  740. {
  741.     WeBeHere("\pCPRedPart::HandleEvent");
  742.  
  743.     ODBoolean    tWasHandled = kODFalse;
  744.     
  745.     switch ( event->what ) {
  746.         case nullEvent:
  747.             if (::IsDialogEvent((EventRecord *)event))
  748.             {
  749.                 short itemHit;
  750.                 DialogPtr dialog;
  751.                 tWasHandled = ::DialogSelect((EventRecord *)event, &dialog, &itemHit);
  752.                 return tWasHandled;
  753.             }
  754.             tWasHandled = kODTrue;
  755.             break;
  756.             
  757.         case mouseDown:
  758.             tWasHandled = this->MyHandleMouseDown(ev, event, frame, facet);
  759.             break;
  760.             
  761.         case kODEvtMouseDownEmbedded:
  762.         case mouseUp:
  763.         case keyDown:
  764.         case autoKey:
  765.         case activateEvt:
  766.             tWasHandled = kODTrue;
  767.             break;
  768.         case kODEvtMenu:
  769.             tWasHandled = this->MyHandleMenuEvent(ev, frame, event );
  770.             break;
  771.         default:
  772.             break;
  773.     }
  774.  
  775.     return tWasHandled;
  776.  
  777. // Below is some documentation for this method.  If you don't care for
  778. // being here, then just delete it.
  779. //
  780. // The frame and facet parameters of HandleEvent() may be
  781. // kODNULL, depending on the kind of event.
  782. //
  783. // Parts must handle the following events, which correspond to
  784. // standard Macintosh events:
  785. //
  786. //    kODEvtNull
  787. //     kODEvtMouseDown
  788. //     kODEvtMouseUp
  789. //     kODEvtKeyDown
  790. //     kODEvtKeyUp
  791. //     kODEvtAutoKey
  792. //     kODEvtUpdate
  793. //     kODEvtActivate
  794. //     kODEvtOS
  795. //
  796. // Null Events --
  797. // In order to receive null events (i.e. idle time), parts must call
  798. // ODDispatcher::RegisterIdle(), specifying the part, a frame
  799. // (optional) and idle frequency. The part will receive a null event
  800. // for each frame registered. ODDispatcher::GetSleepTime() is called
  801. // by the shell, and the value passed to WaitNextEvent. An appropriate
  802. // sleep time is computed based on the idle frequencies of registered
  803. // idle frames.
  804. //
  805. // Mouse Events --
  806. // Unmodified mouse events are delivered to the facet under the mouse
  807. // location using Part::HandleEvent().
  808. //
  809. // Shift-Click and Command-Click go to the frame with the selection
  810. // focus.  Mouse events in window title bars are converted to window
  811. // events. (See below)  Mouse down events in the menu bar are converted
  812. // to menu events. (See below)
  813. //
  814. // Keyboard Events --
  815. // Keyboard events go to the frame with the keyboard focus, with the
  816. // exception of the Page Up, Page Down, Home and End keys, which will
  817. // go to the frame with the scrolling focus, if there is one.
  818. //
  819. // Update Events --
  820. // Update events are not passed to Part::HandleEvent(). Rather
  821. // Part::Draw() will be called for each facet in the window.
  822. //
  823. // Activate Events --
  824. // Activate events are also delivered to each facet, using
  825. // Part::HandleEvent().
  826. //
  827. // Disk Events --
  828. // Currently, disk events are not distributed to parts.
  829. // But where do they go???
  830. //
  831. // OS Events --
  832. // Suspend/Resume events are delivered to each facet in each
  833. // window using Part::HandleEvent(). 
  834. //
  835. // Mouse Moved events are not passed to Part::HandleEvent().
  836. // They are handled by the dispatcher, and translated into calls
  837. // to Part::MouseEnter(), MouseWithin() and MouseLeave().
  838. // See Cursor Tracking below.
  839. //
  840. // Menu Events --
  841. // OpenDoc converts a mouse down in the menu bar, or its
  842. // command-key equivalent, into a menu event of type kODEvtMenu.
  843. //
  844. // The message field of the event record contains the result 
  845. // returned by MenuSelect() or MenuKey(). i.e. the menu is in 
  846. // the high word, and the item in the low word. The part can 
  847. // obtain a command number using ODMenuBar::GetCommand().
  848. //
  849. // Window Events --
  850. // Events in the title bar of a window (eg. clicking in the
  851. // close box) are usually handled by the shell, but are first
  852. // offered to the root part of the window. Parts which wish to
  853. // intercept these events (perhaps to hide rather than close a
  854. // window) must handle the following event: kODEvtWindow 
  855. // The message field of the event contains the part code, as
  856. // returned by FindWindow().
  857. //
  858. // Events in Embedded Frames --
  859. // Parts which support embedding may also receive the following events:
  860. //    
  861. //    kODEvtMouseDownEmbedded 
  862. //    kODEvtMouseUpEmbedded
  863. //    kODEvtMouseDownBorder
  864. //    kODEvtMouseUpBorder
  865. //
  866. // If the user clicks in the active border, the containing
  867. // facet/frame/part will receive a kODEvtMouseDownBorder event.
  868. // The message field of the event record contains the embedded facet.
  869. //
  870. // Similarly, if the user clicks in an embedded frame with the
  871. // ╥frozen╙ or ╥selected╙ property set, a kODEvtMouseDownEmbedded
  872. // event is directed to the containing frame.
  873. //
  874. // If the user shift-clicks or command-clicks in a frame which is
  875. // embedded in the frame with the selection focus, then the latter
  876. // frame gets a kODEvtMouseDownEmbedded event.  
  877. //
  878. // Cursor Tracking --
  879. // OpenDoc tracks cursor movement (with the mouse button up), and
  880. // calls MouseEnter() when the cursor first moves into a facet, and
  881. // MouseLeave() when the cursor leaves the facet. A part can change
  882. // the cursor on MouseEnter, and set it to the arrow on MouseLeave.
  883. //
  884. // This process is triggered by the shell calling
  885. // ODDispatcher::GetMouseRegion() and passing the result to
  886. // WaitNextEvent(). The region is only recomputed when necessary. 
  887. // If the cursor is motionless within a facet, the shell application
  888. // goes to sleep because OpenDoc computes a mouse region containing
  889. // just the cursor location. The part can make this region larger
  890. // by calling ODDispatcher::SetMouseRegion(). In a future release,
  891. // OpenDoc will also compute a suitably large sleep region if the
  892. // cursor is not within any facet.
  893. //
  894. // Modal Focus --
  895. // Some events are constrained by the modal focus. For example a
  896. // mouse click outside the frame with the modal focus will be sent
  897. // to the modal focus frame, but a click in an embedded frame
  898. // within the modal focus frame will go to the embedded frame. 
  899. //
  900. // Propagating Events --
  901. // If a containing part sets the ╥DoesPropagateEvents╙ property of
  902. // an embedded frame, the containing part will receive events not
  903. // handled by the embedded frame. A part which does this will have
  904. // to inspect the frame passed to HandleEvent() to determine if it
  905. // is one of its display frames.
  906.  
  907. }
  908.  
  909.  
  910. void CPRedPart::AdjustMenus(Environment* ev, ODFrame* frame)
  911. {
  912.     Str63        aboutText, showPartsBin, hidePartsBin;
  913.     ODIText*    odiText;
  914.  
  915.     WeBeHere("\pCPRedPart::AdjustMenus");
  916. ODUnused(frame);
  917.     fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frame->IsRoot(ev) );
  918.     fMenuBar->EnableCommand(ev, kODCommandGetPartInfo, kODTrue);
  919.     fMenuBar->EnableCommand(ev, kODCommandShowPartsBin, kODTrue);
  920.  
  921.     {
  922.         CUsingLibraryResources fil;
  923.         ::GetIndString(aboutText,    kContentStringResID, kAboutTextID);
  924.         ::GetIndString(showPartsBin, kContentStringResID, kShowPartsBinID);
  925.         ::GetIndString(hidePartsBin, kContentStringResID, kHidePartsBinID);
  926.     }
  927.  
  928.     odiText = CreateIText(kODRomanScript, kODEnglishLang, aboutText);
  929.     fMenuBar->SetItemString(ev, kODCommandAbout, odiText);
  930.     DisposeIText(odiText);
  931.  
  932.     if (fPartsBinWin)
  933.     {
  934.         ODWindow* window = fSession->GetWindowState(ev)->GetWindow(ev, fPartsBinWin);
  935.         if (window) 
  936.             fPartsBinOpen = window->IsShown(ev);
  937.         else
  938.             fPartsBinOpen = kODFalse;
  939.     }
  940.     
  941.     if (fPartsBinOpen) {
  942.         odiText = CreateIText(kODRomanScript, kODEnglishLang, hidePartsBin);
  943.         fMenuBar->SetItemString(ev, kODCommandShowPartsBin, odiText);
  944.         DisposeIText(odiText);
  945.     }
  946.     else {
  947.         odiText = CreateIText(kODRomanScript, kODEnglishLang, showPartsBin);
  948.         fMenuBar->SetItemString(ev, kODCommandShowPartsBin, odiText);
  949.         DisposeIText(odiText);
  950.     }
  951. }
  952.  
  953.  
  954.  
  955. //--------------------------------------------------------------------
  956. // CPRedPart::MyHandleMenuEvent
  957. //--------------------------------------------------------------------
  958.  
  959. ODBoolean CPRedPart::MyHandleMenuEvent(Environment* ev, ODFrame* frame, ODEventData* event)
  960. {
  961.     WeBeHere("\pCPRedPart::MyHandleMenuEvent");
  962. ODUnused(frame);
  963.     long    menuResult = event->message;
  964.     short    menu = HiWord(menuResult);
  965.     short    item = LoWord(menuResult);
  966.  
  967.     if (menu) {            // If your custom menu(s)...  ÑÑ 6/23/94
  968.  
  969.         switch( fMenuBar->GetCommand(ev, menu, item) ) {
  970.  
  971.             case kODCommandAbout:
  972.             {
  973.                 CUsingLibraryResources fil;
  974.         
  975.                 if (fSession->GetArbitrator(ev)->RequestFocus(ev, fModalFocus, frame))
  976.                 {
  977.                     SetCursor(&ODQDGlobals.arrow);
  978.                     gSession = fSession;                // DialogFilter uses this!
  979.                     ModalFilterUPP modalFilter = NewModalFilterProc(MyDialogFilter);
  980.                     ::Alert(kRedPartAboutBoxID, modalFilter);
  981.                     DisposeRoutineDescriptor(modalFilter);
  982.                     fSession->GetArbitrator(ev)->RelinquishFocus(ev, fModalFocus,frame);
  983.                 }
  984.                 else
  985.                     ::SysBeep(1);
  986.             }
  987.             break;
  988.  
  989.             case kODCommandClear:
  990.                 break;
  991.  
  992.             case kODCommandShowPartsBin:
  993.                 if (fPartsBinOpen)
  994.                     this->MyHidePartsBin(ev);
  995.                 else
  996.                     this->MyShowPartsBin(ev, frame);
  997.                 break;
  998.  
  999.             case kODCommandViewAsWin:
  1000.                 this->Open(ev, frame);
  1001.                 break;
  1002.  
  1003.             case kODCommandGetPartInfo:
  1004.                 ODFrameFacetIterator* facets = frame->CreateFacetIterator(ev);
  1005.                 fSession->GetInfo(ev)->ShowPartFrameInfo(ev, facets->First(ev));
  1006.                 break;
  1007.  
  1008.             default:
  1009.                 return kODFalse;
  1010.         }
  1011.     }
  1012.         
  1013.     return kODTrue;
  1014. }
  1015.  
  1016.  
  1017.  
  1018. //------------------------------------------------------------------------------
  1019. // CPRedPart::MyHandleMouseDown
  1020. //------------------------------------------------------------------------------
  1021.  
  1022. ODBoolean CPRedPart::MyHandleMouseDown(Environment* ev, ODEventData* event,
  1023.                                          ODFrame* frame, ODFacet* facet)
  1024. {
  1025.     WeBeHere("\pCPRedPart::MyHandleMouseDown");
  1026.  
  1027.     ODBoolean handled = kODFalse;
  1028.     
  1029.     if (facet == kODNULL)        // Did we get a click outside a modal dialog? ╔
  1030.     {
  1031.         ::SysBeep(1);
  1032.         return kODTrue;            // Return that click was handled.
  1033.     }
  1034.  
  1035.     // Activate the window if it is not active╔
  1036.     if (!facet->GetWindow(ev)->IsActive(ev))
  1037.     {
  1038.         facet->GetWindow(ev)->Select(ev);
  1039.  
  1040. #ifdef FIRST_CLICK_WINDOW_BEHAVIOR
  1041.         handled = kODTrue;
  1042. #else
  1043.         return kODTrue;
  1044. #endif
  1045.             // We argued way too much about which this should be.  The answer is that
  1046.             // some types of content need first click, and some absolutely don't.  Even
  1047.             // for 'TEXT', sometimes you want one, and sometimes you want the other.
  1048.             // It depends on your content, usage model, etc.
  1049.             //
  1050.             // If you are unsure about which you want, the default for RedPart
  1051.             // should be FIRST_CLICK_WINDOW_BEHAVIOR.  This probably means fewer clicks
  1052.             // for the user.  If this doesn't work for your part, of course change it.
  1053.     }
  1054.  
  1055.     if (::IsDialogEvent((EventRecord *)event))
  1056.     {
  1057.         short        itemHit;
  1058.         DialogPtr    dialog;
  1059.  
  1060.         handled = ::DialogSelect((EventRecord *)event, &dialog, &itemHit);
  1061.         ODWindow* window = fSession->GetWindowState(ev)->GetODWindow(ev, dialog);
  1062.         return handled;        // In preparation for more "if" cases to be added below.
  1063.     }
  1064.  
  1065.     // get the mouse in local coordinates
  1066.     ODWindow* odwnd = frame->GetWindow(ev);
  1067.     ODPoint odPoint;
  1068.     GetWindowPoint(odwnd, ev, event->where, &odPoint);
  1069.  
  1070.     // test for click in grow box, if appropriate
  1071.     if (frame->IsRoot(ev))
  1072.     {
  1073.         WindowPtr wnd   = (WindowPtr)odwnd->GetPlatformWindow(ev);
  1074.  
  1075.         Rect r = wnd->portRect;
  1076.         r.left = r.right  - 15;
  1077.         r.top  = r.bottom - 15;
  1078.         if (::PtInRect(odPoint.AsQDPoint(), &r)) {
  1079.             ::SetRect(&r, 200, 200, 20000, 20000);
  1080.             long newWindowSize = GrowWindow(wnd, event->where, &r);
  1081.             ::SizeWindow(wnd, LoWord(newWindowSize), HiWord(newWindowSize), true);
  1082.             odwnd->AdjustWindowShape(ev);
  1083.             return kODTrue;
  1084.         } 
  1085.     } 
  1086.  
  1087.     // Try to grab all of our foci╔
  1088.     if ( fSession->GetArbitrator(ev)->RequestFocusSet(ev, fFocusSet,frame) )
  1089.     {
  1090.         this->FocusAcquired(ev, fSelectionFocus, frame);
  1091.         this->FocusAcquired(ev, fMenuFocus, frame);
  1092.         this->FocusAcquired(ev, fKeyFocus, frame);
  1093.         
  1094.     } else {
  1095.         return kODFalse;    // We couldn't get focus.
  1096.  
  1097.         // Of course, you shouldn't fail if you really don't need the *all*
  1098.         // of the foci.  For example, a vector drawing part that also has
  1099.         // a text tool should probably go ahead and allow drawing while 
  1100.         // disabling the text tool.
  1101.     }
  1102.  
  1103.     // Handle clicks in used shape╔
  1104.     odPoint = facet->GetWindowContentTransform(ev, kODNULL)->InvertPoint(ev, &odPoint);
  1105.     
  1106.     ODShape*  usedShape = this->MyGetUsedShape(ev, frame);
  1107.     ODBoolean hit       = usedShape->ContainsPoint(ev, &odPoint);
  1108.     usedShape->Release(ev);
  1109.     
  1110.     if (hit)
  1111.         return this->MyUsedShapeHandleMouseDown(ev, event, frame, facet);
  1112.  
  1113.     return handled;
  1114. }
  1115.  
  1116.  
  1117.  
  1118. //------------------------------------------------------------------------------
  1119. // CPRedPart::MyUsedShapeHandleMouseDown
  1120. //------------------------------------------------------------------------------
  1121.  
  1122. ODBoolean CPRedPart::MyUsedShapeHandleMouseDown(Environment* ev, ODEventData* event,
  1123.                                          ODFrame* frame, ODFacet* facet)
  1124. {
  1125.     WeBeHere("\pCPRedPart::MyUsedShapeHandleMouseDown");
  1126.  
  1127.     // Get the window and platform window (i.e. WindowPtr)╔
  1128.     ODWindow* odwnd = frame->GetWindow(ev);
  1129.     ODPlatformWindow facetPort = odwnd->GetPlatformWindow(ev);
  1130.  
  1131.     // Get the mouse in window-local and facet-local coordinates╔
  1132.     ODPoint windowPoint;
  1133.     GetWindowPoint(odwnd, ev, event->where, &windowPoint);
  1134.     ODPoint facetPoint = facet->GetWindowContentTransform(ev, kODNULL)->
  1135.             InvertPoint(ev, &windowPoint);
  1136.  
  1137.     // Handle the click in whatever way is appropriate╔
  1138.     {
  1139.         CFocus foc(ev, facet);
  1140.  
  1141.         //Rect        rct; //das folgende auskommentiert, jl
  1142.         //Point        macPoint = facetPoint.AsQDPoint();
  1143.     
  1144.         //::PenNormal();
  1145.         //::PenMode(srcXor);
  1146.         //::SetRect(&rct, macPoint.h - 3, macPoint.v - 3, macPoint.h + 3, macPoint.v + 3);
  1147.         //::PaintOval(&rct);
  1148.         //::PenNormal();
  1149.         
  1150.         this->fCount++; //neu, jl
  1151.         this->MySetDirty(ev); //neu
  1152.         frame->Invalidate(ev,kODNULL,kODNULL); //neu
  1153.     }
  1154.     
  1155.     return kODTrue;        // We handled the click.
  1156. }
  1157.  
  1158. //-------------------------------------------------------------------------
  1159. // Facet protocol
  1160. //-------------------------------------------------------------------------
  1161.  
  1162. void CPRedPart::FacetAdded(Environment* ev, ODFacet* facet)
  1163. {
  1164.     WeBeHere("\pCPRedPart::FacetAdded");
  1165.     
  1166.     // Add new facet to list of current facets.
  1167.  
  1168.     fFacets.Add(facet);
  1169.  
  1170.     ODFrame* frame = facet->GetFrame(ev);
  1171.     frame->RequestFrameShape(ev, this->MyGetFrameShape(ev, frame), kODNULL);
  1172.         // ÑÑ First, MyGetFrameShape is called to calculate the frame
  1173.         // shape we want.  However, we might not get it, due to the
  1174.         // needs/constraints of the containing part.  Therefore, after
  1175.         // calculating what we want, we see if we can get it by calling
  1176.         // RequestFrameShape.
  1177.         // RequestFrameShape either returns us what we passed it, or
  1178.         // returns something else because it thinks it knows best.
  1179.         // Either way, we then proceed with the returned result.
  1180.         // Note that this means that we have to be prepared to deal
  1181.         // with a frame shape other than we desire.
  1182.  
  1183.     this->MyAdjustFacets(ev, frame);
  1184.         // Given a new negotiated frame shape, adjust our facets based
  1185.         // on it.  That's all there is to it.
  1186.  
  1187.     if (frame->IsRoot(ev)) 
  1188.     {
  1189.         ODBoolean succeeded = kODFalse;
  1190.         succeeded = fSession->GetArbitrator(ev)->RequestFocusSet(ev, fFocusSet,frame);
  1191.         if (succeeded)
  1192.         {
  1193.             this->FocusAcquired(ev, fSelectionFocus, frame);
  1194.             this->FocusAcquired(ev, fMenuFocus, frame);
  1195.             this->FocusAcquired(ev, fKeyFocus, frame);
  1196.         }
  1197.     }
  1198. }
  1199.  
  1200. void CPRedPart::FacetRemoved(Environment* ev, ODFacet* facet)
  1201. {
  1202.     WeBeHere("\pCPRedPart::FacetRemoved");
  1203.  
  1204.     fFacets.Remove(facet);
  1205.         // This just removes the reference from our facet list.
  1206.  
  1207.     ODFrame* frame = facet->GetFrame(ev);
  1208.     frame->RequestFrameShape(ev, this->MyGetFrameShape(ev, frame), kODNULL);
  1209.     this->MyAdjustFacets(ev, frame);
  1210.         // ÑÑ╩This is here in case losing a facet means that we need to recalculate
  1211.         // the frame.  This would occur if the part added some of its own facets,
  1212.         // beyond the single facet that is automatically given to a frame.  If
  1213.         // you don't have your own additional facets, then this code renegotiates
  1214.         // the frame shape for no reason, since the frame will be going away
  1215.         // immediately afterwards (after the last/only facet is removed).
  1216. }
  1217.  
  1218.  
  1219.  
  1220. //--------------------------------------------------------------------
  1221. // CPRedPart::MyInvalAllFacets
  1222. //--------------------------------------------------------------------
  1223.  
  1224. void CPRedPart::MyInvalAllFacets(Environment* ev)
  1225. {
  1226.     // This is just a CPRedPart utility method.
  1227.  
  1228.     for (FacetLink *fl = fFacets.First(); fl->Facet(); fl=fl->Next())
  1229.         fl->Facet()->Invalidate(ev, kODNULL, kODNULL);
  1230. }
  1231.  
  1232.  
  1233.  
  1234. //-------------------------------------------------------------------------
  1235. // Part Activation protocol
  1236. //-------------------------------------------------------------------------
  1237.  
  1238. ODBoolean CPRedPart::BeginRelinquishFocus(Environment* ev, ODTypeToken focus,
  1239.                                               ODFrame* ownerFrame,
  1240.                                               ODFrame* proposedFrame)
  1241. {
  1242.     WeBeHere("\pCPRedPart::BeginRelinquishFocus");
  1243. ODUnused(ownerFrame);
  1244.     if ((focus == fModalFocus) && (proposedFrame->GetPart(ev) != fPartWrapper)) {
  1245.         return kODFalse;
  1246.             // ÑÑ 6/23/94
  1247.             // What IS ModalFocus, anyway?  The whole purpose of this
  1248.             // ModalFocus thing is to restrict frame changes.  This is
  1249.             // the part's chance to do this.  But how much to restrict╔
  1250.             //
  1251.             // This is an interesting case.  ModalFocus is kind of a weird
  1252.             // concept in OpenDoc, as it goes against the principal of
  1253.             // being able to click anywhere at any time.  This implementation
  1254.             // keeps the focus on the part.  Note that the implementation
  1255.             // of ModalFocus might be more restrictive than this.  You may
  1256.             // wish to restrict it to a single frame, instead of allowing
  1257.             // the focus to move from frame to frame within a single part.
  1258.             // If you wish to restrict it to a single frame, then the if
  1259.             // should only check if it is a modal focus.
  1260.     }
  1261.     else {
  1262.         return kODTrue;
  1263.             // This is the super-script way of handling ModalFocus.  You
  1264.             // can NOT switch off the frame to another, no matter what.
  1265.     }
  1266. }
  1267.  
  1268. void CPRedPart::CommitRelinquishFocus(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame,
  1269.                                                          ODFrame* proposedFrame)
  1270. {
  1271.     WeBeHere("\pCPRedPart::CommitRelinquishFocus");
  1272. ODUnused(proposedFrame);
  1273.     this->FocusLost(ev, focus, ownerFrame);
  1274.         // ÑÑ 6/23/94
  1275.         // No choices to be made here.  It's too late to say no.  We are
  1276.         // losing the focus if we are here.  Getting called here means
  1277.         // that BeginRelinquishFocus has already agreed that losing focus
  1278.         // is okay.  If you don't want this to be happening, then you need
  1279.         // to do something in BeginRelinquishFocus.
  1280.         //
  1281.         // The way that some other samples are currently written I believe
  1282.         // to be in error.  The recipes say that when this is called, it
  1283.         // has already been decided that, focus-wise, you lose.  Therefore
  1284.         // there should be no conditions on calling FocusLost.
  1285. }
  1286.                             
  1287. void CPRedPart::AbortRelinquishFocus(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame,
  1288.                                                         ODFrame* proposedFrame)
  1289. {
  1290.     WeBeHere("\pCPRedPart::AbortRelinquishFocus");
  1291. ODUnused(focus);
  1292. ODUnused(ownerFrame);
  1293. ODUnused(proposedFrame);
  1294.     // ÑÑ 6/23/94
  1295.     // Being here means that BeginRelinquishFocus said no to one of the foci.
  1296.     // You are being informed of this because you may have already taken action
  1297.     // based on a previous focus.  Note that if foci are managed as a set, if
  1298.     // BeginRelinquishFocus says false to any of the foci, then no action is
  1299.     // taken.  If however the foci are tested one at a time, it is possible that
  1300.     // the part has already taken action based on the first foci, and therefore
  1301.     // needs to undo something once a foci says no thanks.
  1302. }
  1303.                               
  1304. void CPRedPart::FocusAcquired(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame)
  1305. {
  1306.     WeBeHere("\pCPRedPart::FocusAcquired");
  1307.     if (focus == fMenuFocus) 
  1308.         if (ownerFrame && fMenuBar)
  1309.         {    
  1310.             fMenuBar->Display(ev);
  1311.         }
  1312. }    
  1313.  
  1314. void CPRedPart::FocusLost(Environment* ev, ODTypeToken focus, ODFrame* ownerFrame)
  1315. {
  1316.     WeBeHere("\pCPRedPart::FocusLost");
  1317. ODUnused(ownerFrame);
  1318.     if (focus == fMenuFocus) 
  1319.     {
  1320.     }
  1321. }
  1322.  
  1323.  
  1324.  
  1325. //-------------------------------------------------------------------------
  1326. // Storage protocol
  1327. //-------------------------------------------------------------------------
  1328.  
  1329. void CPRedPart::CloneInto(Environment* ev, ODDraftKey key, ODStorageUnit* toSU, ODFrame* scope)
  1330.  
  1331.  
  1332. {
  1333.     WeBeHere("\pCPRedPart::CloneInto");
  1334.  
  1335.     ODStorageUnit*    su = fPartWrapper->GetStorageUnit(ev);
  1336.     ODDraft*        draft = su->GetDraft(ev);
  1337.  
  1338.     ODVolatile(draft);
  1339.  
  1340.     this->Externalize(ev);
  1341.     
  1342.     su->CloneInto(ev, key, toSU, scope->GetStorageUnit(ev)->GetID(ev));
  1343.  
  1344.     if (ev->_major != NO_EXCEPTION)
  1345.         draft->AbortClone(ev, key);
  1346. }
  1347.  
  1348.  
  1349.  
  1350. //-------------------------------------------------------------------------
  1351. // Frame protocol
  1352. //-------------------------------------------------------------------------
  1353.  
  1354. void CPRedPart::DisplayFrameRemoved(Environment* ev, ODFrame* frame)
  1355.  
  1356. // Removes the frame from the list of display frames.
  1357. //
  1358. // Called by Frame::Remove().
  1359. //
  1360. // This method makes whatever other adjustments are necessary
  1361. // to deal with removing one of the presentations. This includes
  1362. // removing any frames embedded within this display frame.
  1363. // Before calling this method, you must ensure that the frame
  1364. // has no facets.
  1365.  
  1366. {
  1367.     WeBeHere("\pCPRedPart::DisplayFrameRemoved");
  1368.  
  1369.     fSession->GetArbitrator(ev)->RelinquishFocusSet(ev, fFocusSet, frame);
  1370. }
  1371.  
  1372.  
  1373. void CPRedPart::DisplayFrameClosed(Environment* ev, ODFrame* frame)
  1374.  
  1375. // Informs a part that one of its display frames is closing.
  1376. //
  1377. // Called by the frame object.
  1378. // The part should remove ╥frame╙ from its list of display frames,
  1379. // call Frame::Close() on any frames that are embedded within that
  1380. // frame, and then release the frame.
  1381.  
  1382. {
  1383.     WeBeHere("\pCPRedPart::DisplayFrameClosed");
  1384.  
  1385.     fSession->GetArbitrator(ev)->RelinquishFocusSet(ev, fFocusSet, frame);
  1386. }
  1387.  
  1388.  
  1389. void CPRedPart::FrameShapeChanged(Environment* ev, ODFrame* frame)
  1390.  
  1391. // ÑÑ╩Notifies the part that the frame shape of one of its
  1392. // display frames has been changed by its containing part.
  1393. //
  1394. // Called by Frame::ChangeFrameShape.
  1395. //
  1396. // The part should take whatever actions are necessary to respond
  1397. // to the new shape. It may need to re-layout its content, change
  1398. // its used shape, resize its embedded frames, or something else.
  1399. // It also has the option of turning around and asking the frame
  1400. // for a different frame shape via RequestFrameShape, though it
  1401. // must be able to handle the shape it is given. If the size of
  1402. // the frame is not sufficient, the part may ask the containing
  1403. // part for a continuation frame via CreateEmbeddedFrame.
  1404.  
  1405. {
  1406.     WeBeHere("\pCPRedPart::FrameShapeChanged");
  1407.  
  1408.     frame->RequestFrameShape(ev, this->MyGetFrameShape(ev, frame), kODNULL);
  1409.     this->MyAdjustFacets(ev, frame);
  1410.     frame->Invalidate(ev, kODNULL, kODNULL);
  1411.     frame->InvalidateActiveBorder(ev);
  1412. }
  1413.  
  1414.  
  1415. ODShape* CPRedPart::MyGetFrameShape(Environment* ev, ODFrame* frame)
  1416.  
  1417. // This is just to centralize the frame shape code.  Do it any way
  1418. // is best for your part.
  1419.  
  1420. {
  1421.     ODShape* newFrameShape;
  1422.     
  1423.     if (frame->IsRoot(ev))
  1424.         newFrameShape = frame->GetFrameShape(ev, kODNULL);
  1425.     else
  1426.         newFrameShape = this->MyGetUsedShape(ev, frame);
  1427.  
  1428.     return newFrameShape;
  1429. }
  1430.  
  1431.  
  1432. ODShape* CPRedPart::MyGetUsedShape(Environment* ev, ODFrame* frame)
  1433.  
  1434. // This is just to centralize the frame shape code.  Do it any way
  1435. // is best for your part.
  1436.  
  1437. {
  1438.     ODShape* frameShape = frame->GetFrameShape(ev, kODNULL);
  1439.     RgnHandle    shapeRgn = frameShape->GetQDRegion(ev);
  1440.     frameShape->Release(ev);
  1441.     
  1442.     Rect        rr = (*shapeRgn)->rgnBBox;
  1443.     short        hh = rr.bottom - rr.top;
  1444.     short        ww = rr.right - rr.left;
  1445.  
  1446.     if (hh > ww)  hh = ww;
  1447.     if (hh < 200) hh = 200;
  1448.  
  1449.     ::SetRect(&rr, 0, 0, hh, hh);
  1450.     ::OpenRgn();
  1451.     ::FrameRoundRect(&rr, 40, 40);
  1452.     ::CloseRgn(shapeRgn = NewRgn());
  1453.  
  1454.     ODShape* usedShape = frame->CreateShape(ev);
  1455.     usedShape->SetQDRegion(ev, shapeRgn);
  1456.  
  1457.     return usedShape;
  1458. }
  1459.  
  1460.  
  1461. void CPRedPart::MyAdjustFacets(Environment* ev, ODFrame* frame)
  1462.  
  1463. // Given a frame, iterate through all of the facets and adjust them
  1464. // according to the new frame.
  1465.  
  1466. {
  1467.     ODShape* usedShape  = this->MyGetUsedShape(ev, frame);
  1468.     frame->ChangeUsedShape(ev, usedShape, kODNULL);
  1469.     usedShape->Release(ev);
  1470.  
  1471.     ODShape* frameShape = frame->GetFrameShape(ev, kODNULL);
  1472.     ODFrameFacetIterator* facets = frame->CreateFacetIterator(ev);
  1473.     for (ODFacet* facet = facets->First(ev);
  1474.             facets->IsNotComplete(ev);
  1475.             facet = facets->Next(ev) )
  1476.     {
  1477.         facet->ChangeActiveShape(ev, frameShape, kODNULL);
  1478.     }
  1479.     frameShape->Release(ev);
  1480. }
  1481.  
  1482.  
  1483.