home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Containers / ContainerControl / CControlContainer.cpp next >
Encoding:
Text File  |  1996-12-15  |  24.2 KB  |  943 lines  |  [TEXT/CWIE]

  1. // =================================================================================
  2. //    CControlContainer.cpp            ©1996-97 Microsoft Corporation All rights reserved.
  3. // =================================================================================
  4. //
  5. //    A control that contains other controls
  6.  
  7. #include "ocheaders.h"
  8. #include <LArrayIterator.h>
  9. #include "CControlContainer.h"
  10. #include "CControlSite.h"
  11.  
  12. const ArrayIndexT    index_Self = -1;
  13.  
  14. //======================================================================
  15. //
  16. //    Public Methods
  17. //
  18.  
  19. #pragma mark === CControlContainer::Construction & Destruction ===
  20.  
  21. // ---------------------------------------------------------------------------
  22. //        • CControlContainer::CControlContainer
  23. // ---------------------------------------------------------------------------
  24. //    Default Constructor
  25.  
  26. CControlContainer::CControlContainer (void) : CBaseControl(), CContainer()
  27. {
  28.     mFocusSite = NULL;
  29.     mModalFocusSite = NULL;
  30.     mLastSiteClicked = NULL;
  31.     mScheduledControlsMap = NULL;
  32.     mMapRefCon = 0;
  33.     
  34.     // Create two TextEdit controls    
  35.     CreateTextEditControl(10, 10, 150, 150);
  36.     CreateTextEditControl(10, 170, 150, 150);
  37. }
  38.  
  39.  
  40. // ---------------------------------------------------------------------------
  41. //        • CControlContainer::~CControlContainer
  42. // ---------------------------------------------------------------------------
  43. //    Destructor
  44.  
  45. CControlContainer::~CControlContainer (void)
  46. {
  47.     if (mScheduledControlsMap)
  48.         delete mScheduledControlsMap;
  49. }
  50.  
  51.  
  52. #pragma mark === CControlContainer ===
  53.  
  54. // ---------------------------------------------------------------------------
  55. //        • CControlContainer::FindSiteHitBy
  56. // ---------------------------------------------------------------------------
  57. //    Find which contained control was hit, if any
  58.  
  59. CControlSite* CControlContainer::FindSiteHitBy (Point inWhere)
  60. {
  61.        Uint32                i;
  62.     Uint32                numSites;
  63.     CControlSite*        theSiteP;
  64.     
  65.     numSites = GetCount();
  66.     
  67.     for ( i = numSites; i > 0; i--)
  68.     {
  69.         FetchSite(i, (CXSite **) &theSiteP);
  70.         
  71.         if (theSiteP)
  72.         {
  73.             if (theSiteP->Contains(inWhere))
  74.                 return theSiteP;
  75.         }
  76.     }
  77.         
  78.     return NULL;
  79. }
  80.  
  81.  
  82. // ---------------------------------------------------------------------------
  83. //        • CControlContainer::RequestFocus
  84. // ---------------------------------------------------------------------------
  85. //    Handle request for focus from a contained control
  86.  
  87. STDMETHODIMP
  88. CControlContainer::RequestFocus (CControlSite* inSiteP, Boolean inAcquire, FocusSet inFocus)
  89. {
  90.     ErrorCode        theResult = S_OK;
  91.     FocusSet        needFocus = EmptyFocusSet;
  92.  
  93.     if (!inFocus)
  94.         return S_OK;
  95.         
  96.     if (!inSiteP)
  97.         return E_FAIL;
  98.  
  99.     if (inAcquire)
  100.     {
  101.         CControlSite*    saveModal = mModalFocusSite;
  102.         CControlSite*    saveKeyboard = mFocusSite;
  103.         Boolean8        modalReleased = false;
  104.         Boolean8        keyboardReleased = false;
  105.         
  106.         if (inFocus & ModalFocus)
  107.         {
  108.             // If noone has the focus, add it to the list to request
  109.             if (mModalFocusSite == NULL)
  110.             {
  111.                 needFocus = FocusSet(needFocus | ModalFocus);
  112.             }
  113.             // Does someone else have the focus?
  114.             else if (mModalFocusSite != inSiteP)
  115.             {
  116.                 // Ask them if they'll give it up
  117.                 if (mModalFocusSite->SetFocus(RequestReleaseCommand, ModalFocus) == S_OK)
  118.                 {
  119.                     modalReleased = true;
  120.                     mModalFocusSite = inSiteP;
  121.                 }
  122.                 else    // They won't release it - fail the request
  123.                     theResult = E_FAIL;
  124.             }
  125.         }
  126.  
  127.         if ((inFocus & KeyboardFocus) && (theResult == S_OK))
  128.         {
  129.             // If noone has the focus, add it to the list to request
  130.             if (mFocusSite == NULL)
  131.             {
  132.                 needFocus = FocusSet(needFocus | KeyboardFocus);
  133.             }
  134.             // Does someone else have the focus?
  135.             else if (mFocusSite != inSiteP)
  136.             {
  137.                 // Ask them if they'll give it up
  138.                 if (mFocusSite->SetFocus(RequestReleaseCommand, KeyboardFocus) == S_OK)
  139.                 {
  140.                     keyboardReleased = true;
  141.                     mFocusSite = inSiteP;
  142.                 }
  143.                 else    // They won't release it - fail the request
  144.                     theResult = E_FAIL;
  145.             }
  146.         }
  147.         
  148.         // If we don't hold the requested foces types locally (self or embedded controls)
  149.         if ((needFocus != EmptyFocusSet) && (theResult == S_OK))
  150.         {
  151.             // Request the focus types from our container
  152.             if (mContainerSiteP->RequestFocus(inAcquire, needFocus) == S_OK)
  153.             {
  154.                 if (needFocus & ModalFocus)
  155.                     mModalFocusSite = inSiteP;
  156.                 if (needFocus & KeyboardFocus)
  157.                     mFocusSite = inSiteP;
  158.             }
  159.             else    // Request to our container failed - fail this request.
  160.                 theResult = E_FAIL;
  161.         }
  162.         
  163.         // If there was a problem, attempt to restore the focus holders as existed before
  164.         // this operation.
  165.         if (theResult != S_OK)
  166.         {
  167.             if (modalReleased && (saveModal->SetFocus(TakeNextCommand, ModalFocus) == S_OK))
  168.                 mModalFocusSite = saveModal;
  169.             else
  170.                 mModalFocusSite = NULL;
  171.                 
  172.             if (keyboardReleased && (saveKeyboard->SetFocus(TakeNextCommand, KeyboardFocus) == S_OK))
  173.                 mFocusSite = saveKeyboard;
  174.             else
  175.                 mFocusSite = NULL;
  176.         }
  177.     }
  178.     else    // !inAcquire - release
  179.     {
  180.         if (inFocus & ModalFocus)
  181.         {
  182.             if ((mModalFocusSite != NULL) && (mModalFocusSite == inSiteP))
  183.             {
  184.                 mModalFocusSite = NULL;
  185.                 mContainerSiteP->RequestFocus(false, ModalFocus);
  186.             }
  187.         }
  188.         
  189.         if (inFocus & KeyboardFocus)
  190.         {
  191.             if ((mFocusSite != NULL) && (mFocusSite == inSiteP))
  192.             {
  193.                 mFocusSite = NULL;
  194.                 mContainerSiteP->RequestFocus(false, KeyboardFocus);
  195.             }
  196.         }
  197.     }
  198.  
  199.     return theResult;
  200. }
  201.  
  202.  
  203. // ---------------------------------------------------------------------------
  204. //        • CControlContainer::SetIdleTime
  205. // ---------------------------------------------------------------------------
  206. //    Handle request for idle time from a contained control
  207.  
  208. STDMETHODIMP
  209. CControlContainer::SetIdleTime (CControlSite* inSiteP, Int32 inWaitTicks, Uint32 inIdleRefCon)
  210. {
  211.     ErrorCode        theResult = E_FAIL;
  212.  
  213.     if (!mScheduledControlsMap)
  214.         mScheduledControlsMap = new LArray(sizeof(SchedControlMap));
  215.     
  216.     if (mScheduledControlsMap)
  217.     {
  218.         switch (inWaitTicks)
  219.         {
  220.             case RemoveAllIdlers:
  221.                 theResult = RemoveControlIdler(inSiteP);
  222.                 break;
  223.             case RemoveIdler:
  224.                 theResult = RemoveRefConIdler(inSiteP, inIdleRefCon);
  225.                 break;
  226.             default:
  227.                 theResult = SetIdleTimeSelf(inSiteP, inWaitTicks, inIdleRefCon);
  228.                 break;
  229.         }
  230.     }
  231.     
  232.     return theResult;
  233. }
  234.  
  235. //----------------------------------------------------------------------
  236. //
  237. //    IUnknown Methods
  238. //
  239.  
  240. #pragma mark === CControlContainer::IUnknown ===
  241.  
  242. // ---------------------------------------------------------------------------
  243. //        • CControlContainer::IUnknown::QueryInterface
  244. // ---------------------------------------------------------------------------
  245. //    Do we implement the requested interface?
  246.  
  247. STDMETHODIMP
  248. CControlContainer::QueryInterface (REFIID inRefID, void** outObj)
  249. {
  250.     ErrorCode    theResult;
  251.     
  252.     // Since we are both a container and a control, query each interface
  253.     // from which we derive in turn.
  254.     theResult = CContainer::QueryInterface(inRefID, outObj);
  255.     
  256.     if (theResult == E_NOINTERFACE)
  257.         theResult = CBaseControl::QueryInterface(inRefID, outObj);
  258.     
  259.     // If we don't implement the interface ourself, pass the request up
  260.     // to our containing object.
  261.     if ((theResult == E_NOINTERFACE) && mUnkOuterP)
  262.         theResult = mUnkOuterP->QueryInterface(inRefID, outObj);
  263.     
  264.     return theResult;
  265. }
  266.  
  267.  
  268. //----------------------------------------------------------------------
  269. //
  270. //    IControl Methods
  271. //
  272.  
  273. #pragma mark === CControlContainer::IControl ===
  274.  
  275. // ---------------------------------------------------------------------------
  276. //        • CControlContainer::IControl::Draw
  277. // ---------------------------------------------------------------------------
  278. //    Draw the control and all contained controls
  279.  
  280. STDMETHODIMP
  281. CControlContainer::Draw(DrawContext* inContext)
  282. {
  283.        Uint32                i;
  284.     Uint32                numSites;
  285.     CControlSite*        theSiteP;
  286.     IControl*            controlP;
  287.     
  288.     if (inContext->DrawAspect != DVASPECT_CONTENT)
  289.         return DV_E_DVASPECT;
  290.  
  291.     // Erase the area and outline the frame
  292.     ::EraseRect(&inContext->Location);
  293.     ::PenSize(1, 1);
  294.     ::FrameRect(&inContext->Location);
  295.  
  296.     // Draw each contained control
  297.     numSites = GetCount();
  298.     
  299.     for ( i = 1; i <= numSites; i++)
  300.     {
  301.         FetchSite(i, (CXSite **) &theSiteP);
  302.         
  303.         if (theSiteP)
  304.         {
  305.             if (SUCCEEDED(theSiteP->QueryInterface(IID_IControl, &controlP)))
  306.             {
  307.                 controlP->Draw(inContext);
  308.                 controlP->Release();
  309.             }
  310.         }
  311.     }
  312.         
  313.     return S_OK;
  314. }
  315.  
  316.  
  317. // ---------------------------------------------------------------------------
  318. //        • CControlContainer::IControl::OnContextChange
  319. // ---------------------------------------------------------------------------
  320. //    Pass context change on to contained controls
  321.  
  322. STDMETHODIMP
  323. CControlContainer::OnContextChange(UInt32 inContextID, ContextCommand Command)
  324. {
  325.     IControl*        controlP;
  326.        Uint32            i;
  327.     Uint32            numSites;
  328.     ErrorCode        theResult;
  329.     CControlSite*    theSiteP;
  330.     
  331.     theResult = CBaseControl::OnContextChange(inContextID, Command);
  332.     
  333.     numSites = GetCount();
  334.     
  335.     for ( i = 1; i <= numSites; i++)
  336.     {
  337.         FetchSite(i, (CXSite **) &theSiteP);
  338.         
  339.         if (theSiteP)
  340.         {
  341.             if (SUCCEEDED(theSiteP->QueryInterface(IID_IControl, &controlP)))
  342.             {
  343.                 controlP->OnContextChange(inContextID, Command);
  344.                 controlP->Release();
  345.             }
  346.         }
  347.     }
  348.  
  349.     return theResult;
  350. }
  351.  
  352.  
  353. // ---------------------------------------------------------------------------
  354. //        • CControlContainer::IControl::SetFocus
  355. // ---------------------------------------------------------------------------
  356. //    Acquire or release one or more focus types
  357.  
  358. STDMETHODIMP
  359. CControlContainer::SetFocus(FocusCommand Command, FocusSet Focus)
  360. {
  361.     ErrorCode    result = S_OK;
  362.  
  363.     if (Command == TakeNextCommand || Command == TakePrevCommand)
  364.         result = TakeFocus(Command, Focus);
  365.     else if (Command == RequestReleaseCommand)
  366.     {
  367.         result = RequestReleaseFocus(Focus);
  368.     }
  369.     else if (Command == ReleaseCommand)
  370.     {
  371.         ReleaseFocus(Focus);
  372.         result = S_OK;
  373.     }
  374.     else
  375.         result = E_FAIL;
  376.         
  377.     return result;
  378. }
  379.  
  380.  
  381. // ---------------------------------------------------------------------------
  382. //        • CControlContainer::IControl::DoMouse
  383. // ---------------------------------------------------------------------------
  384. //    Handle mouse events for this control. Dispatch to contained controls as appropriate.
  385.  
  386. STDMETHODIMP
  387. CControlContainer::DoMouse(MouseEventType inMouseET, PlatformEvent* inEvent)
  388. {
  389.     IControl*        controlP;
  390.     DrawContext        theContext = {BeginPortType};
  391.     
  392.     switch (inMouseET) 
  393.     {
  394.         case MouseUp:
  395.             // Send mouse-up to the control that received the last mouse down
  396.             if (mLastSiteClicked)
  397.             {
  398.                 if (SUCCEEDED((mLastSiteClicked)->QueryInterface(IID_IControl, &controlP)))
  399.                 {
  400.                     controlP->DoMouse(inMouseET, inEvent);
  401.                     controlP->Release();
  402.                 }
  403.             }
  404.             break;
  405.  
  406.         case MouseDown:
  407.             // Send mouse-down to the contained control that was hit, if any.
  408.             Point        localPt;
  409.  
  410.             mContainerSiteP->AcquireContext(mActiveContext->GetContextID(), &theContext);
  411.             
  412.             localPt = inEvent->where;
  413.             ::GlobalToLocal(&localPt);
  414.             mLastSiteClicked = FindSiteHitBy(localPt);
  415.             
  416.             mContainerSiteP->ReleaseContext(&theContext);
  417.  
  418.             // If a contained control was hit, pass it the mouse down event.
  419.             if (mLastSiteClicked)
  420.             {
  421.                 if (SUCCEEDED((mLastSiteClicked)->QueryInterface(IID_IControl, &controlP)))
  422.                 {
  423.                     controlP->DoMouse(inMouseET, inEvent);
  424.                     controlP->Release();
  425.                 }
  426.             }
  427.             break;
  428.     }
  429.  
  430.     return S_OK;
  431. }
  432.  
  433.  
  434. // ---------------------------------------------------------------------------
  435. //        • CControlContainer::IControl::DoKey
  436. // ---------------------------------------------------------------------------
  437. //    Handle key events for this control. Dispatch to contained controls as appropriate.
  438.  
  439. STDMETHODIMP
  440. CControlContainer::DoKey(KeyEventType inKeyET, Char8 inChar, PlatformEvent* inEvent)
  441. {
  442.     IControl*        controlP;
  443.     DrawContext        theContext = {BeginPortType};
  444.     
  445.     // Send keyboard events to the embedded control that has the keyboard focus (if any)
  446.     if (mFocusSite)
  447.     {
  448.         if (SUCCEEDED(mFocusSite->QueryInterface(IID_IControl, &controlP)))
  449.         {
  450.             controlP->DoKey(inKeyET, inChar, inEvent);
  451.             controlP->Release();
  452.         }
  453.     }
  454.     
  455.     return S_OK;
  456. }
  457.  
  458.  
  459. // ---------------------------------------------------------------------------
  460. //        • CControlContainer::IControl::DoActivate
  461. // ---------------------------------------------------------------------------
  462. //    Note activation state and pass on to contained controls
  463.  
  464. STDMETHODIMP
  465. CControlContainer::DoActivate(ActivateEventType inActiveET, UInt32 inContextID, PlatformEvent* inEvent)
  466. {
  467.     IControl*        controlP;
  468.        Uint32            i;
  469.     Uint32            numSites;
  470.     ErrorCode        theResult;
  471.     CControlSite*    theSiteP;
  472.     
  473.     theResult = CBaseControl::DoActivate(inActiveET, inContextID, inEvent);
  474.     
  475.     numSites = GetCount();
  476.     
  477.     for ( i = 1; i <= numSites; i++)
  478.     {
  479.         FetchSite(i, (CXSite **) &theSiteP);
  480.         
  481.         if (theSiteP)
  482.         {
  483.             if (SUCCEEDED(theSiteP->QueryInterface(IID_IControl, &controlP)))
  484.             {
  485.                 controlP->DoActivate(inActiveET, inContextID, inEvent);
  486.                 controlP->Release();
  487.             }
  488.         }
  489.     }
  490.  
  491.     return theResult;
  492. }
  493.  
  494.  
  495. // ---------------------------------------------------------------------------
  496. //        • CControlContainer::IControl::DoIdle
  497. // ---------------------------------------------------------------------------
  498. //    Handle null events for this control. Dispatch to contained controls as appropriate.
  499.  
  500. STDMETHODIMP
  501. CControlContainer::DoIdle(Uint32 inIdleRefCon)
  502. {
  503.     ErrorCode    theResult = E_FAIL;
  504.     
  505.     if (mScheduledControlsMap)
  506.     {
  507.         LArrayIterator        schedControlIter(*mScheduledControlsMap);
  508.         Boolean8            found = false;
  509.         SchedControlMap        map;
  510.         
  511.         while (schedControlIter.Next(&map) && !found)
  512.         {
  513.             if (map.ContainerRefCon == inIdleRefCon)
  514.             {
  515.                 theResult = map.Control->DoIdle(map.ControlRefCon);
  516.                 found = true;
  517.             }
  518.         }
  519.     }
  520.     
  521.     return theResult;
  522. }
  523.  
  524. //======================================================================
  525. //
  526. //    Private Methods
  527. //
  528.  
  529. #pragma mark === CControlContainer Private Methods ===
  530.  
  531. // ---------------------------------------------------------------------------
  532. //        • CControlContainer::CreateTextEditControl
  533. // ---------------------------------------------------------------------------
  534. //    Create a TextEdit control at the specified position
  535.  
  536. void CControlContainer::CreateTextEditControl(Uint32 inTop, Uint32 inLeft, Uint32 inHeight, Uint32 inWidth)
  537. {
  538.     CControlSite*        theSiteP;
  539.  
  540.     theSiteP = new CControlSite(this, inTop, inLeft, inHeight, inWidth);
  541.     if (theSiteP)
  542.     {
  543.         theSiteP->SetContainerData( (IContainer *) this, NULL);
  544.         theSiteP->AddParam("src", "textedit.acx");
  545.         theSiteP->AddParam("classid", "CLSID:{03d64580-21d1-11d0-b42d-8215fbcfdd9c}");
  546.         theSiteP->AddParam("codebase", "TextEdit.hqx");
  547.  
  548.         theSiteP->CreateControl(true);
  549.         
  550.         AddSite(theSiteP);
  551.     }
  552. }
  553.  
  554.  
  555. // ---------------------------------------------------------------------------
  556. //        • CControlContainer::FirstFocus
  557. // ---------------------------------------------------------------------------
  558. //    Find the first contained control that should be offered the focus
  559.  
  560. ArrayIndexT CControlContainer::FirstFocus (FocusSet Focus, Boolean8 forward)
  561. {
  562.     ArrayIndexT        result = LArray::index_Bad;
  563.     CControlSite*    currentSiteP = NULL;
  564.  
  565.     if ((Focus & KeyboardFocus) && (mFocusSite != NULL))
  566.         currentSiteP = mFocusSite;
  567.     else if ((Focus & ModalFocus) && (mModalFocusSite != NULL))
  568.         currentSiteP = mModalFocusSite;
  569.     
  570.     if (currentSiteP != NULL)
  571.     {
  572.         result = mSiteArrayP->FetchIndexOf(currentSiteP);
  573.         if (result != LArray::index_Bad)
  574.         {
  575.             if (forward)
  576.             {
  577.                 // Start with the next control on the list.
  578.                 // If this is the last item, fail.
  579.                 result++;
  580.                 if (result > GetCount())
  581.                     result = LArray::index_Bad;
  582.             }
  583.             else
  584.             {
  585.                 // Start with the previous control on the list.
  586.                 // If this is the first item, fail.
  587.                 result--;
  588.                 if (result < 1)
  589.                     result = LArray::index_Bad;
  590.             }
  591.         }
  592.     }
  593.     else
  594.     {
  595.         if (GetCount() > 0)
  596.         {
  597.             if (forward)
  598.                 result = LArray::index_First;    // Start with the first embedded control
  599.             else
  600.                 result = LArray::index_Last;    // Start with the last embedded control
  601.         }
  602.         else
  603.             result = LArray::index_Bad;            // No sites - fail
  604.     }
  605.     
  606.     return result;
  607. }
  608.  
  609.  
  610. // ---------------------------------------------------------------------------
  611. //        • CControlContainer::FocusTaken
  612. // ---------------------------------------------------------------------------
  613. //    Records the focus types now held by the embedded control
  614.  
  615. void CControlContainer::FocusTaken(FocusSet inFocus, CControlSite* inSiteP)
  616. {
  617.     if (inFocus & KeyboardFocus)
  618.         mFocusSite = inSiteP;
  619.     
  620.     if (inFocus & ModalFocus)
  621.         mModalFocusSite = inSiteP;
  622. }
  623.  
  624.  
  625. // ---------------------------------------------------------------------------
  626. //        • CControlContainer::HaveFocus
  627. // ---------------------------------------------------------------------------
  628. //    Are any of these focus types held?
  629.  
  630. Boolean8 CControlContainer::HaveFocus (FocusSet Focus)
  631. {
  632.     if (((Focus & KeyboardFocus) && (mFocusSite != NULL)) ||
  633.         ((Focus & ModalFocus) && (mModalFocusSite != NULL)))
  634.         return true;
  635.     else
  636.         return false;
  637. }
  638.  
  639.  
  640. // ---------------------------------------------------------------------------
  641. //        • CControlContainer::NextFocus
  642. // ---------------------------------------------------------------------------
  643. //    Which control should be offered focus next?
  644.  
  645. ArrayIndexT    CControlContainer::NextFocus (Boolean8 forward, ArrayIndexT index)
  646. {
  647.     ArrayIndexT        next;
  648.     
  649.     // Searching forward or backwards?
  650.     if (forward)
  651.     {
  652.         // Forward.
  653.         // The next contained control is the next target. If no more contained
  654.         // controls, fail.
  655.         next = index + 1;
  656.         if (next > GetCount())
  657.             next = LArray::index_Bad;
  658.     }
  659.     else
  660.     {
  661.         // Backward.
  662.         // The prior contained control in the list is the next target.
  663.         // If already at the beginning of the list, fail.
  664.         next = index - 1;
  665.         if (next <= 0)
  666.             next = LArray::index_Bad;
  667.     }
  668.     
  669.     return next;
  670. }
  671.  
  672.  
  673. // ---------------------------------------------------------------------------
  674. //        • CControlContainer::ReleaseFocus
  675. // ---------------------------------------------------------------------------
  676. //    Release the specified foci.
  677.  
  678. void CControlContainer::ReleaseFocus (FocusSet Focus)
  679. {
  680.     IControl*    controlP;
  681.  
  682.     if ((Focus & KeyboardFocus) && (mFocusSite != NULL))
  683.     {
  684.         if (SUCCEEDED(mFocusSite->QueryInterface(IID_IControl, &controlP)))
  685.         {
  686.             controlP->SetFocus(ReleaseCommand, KeyboardFocus);
  687.             controlP->Release();
  688.         }
  689.         
  690.         mFocusSite = NULL;
  691.     }
  692.     
  693.     if ((Focus & ModalFocus) && (mModalFocusSite != NULL))
  694.     {
  695.         if (SUCCEEDED(mModalFocusSite->QueryInterface(IID_IControl, &controlP)))
  696.         {
  697.             controlP->SetFocus(ReleaseCommand, ModalFocus);
  698.             controlP->Release();
  699.         }
  700.         
  701.         mModalFocusSite = NULL;
  702.     }
  703. }
  704.  
  705.  
  706. // ---------------------------------------------------------------------------
  707. //        • CControlContainer::RequestReleaseFocus
  708. // ---------------------------------------------------------------------------
  709. //    Attempt to release the specified foci.
  710.  
  711. ErrorCode
  712. CControlContainer::RequestReleaseFocus (FocusSet Focus)
  713. {
  714.     ErrorCode    theResult = S_OK;
  715.     IControl*    controlP;
  716.  
  717.     if ((Focus & ModalFocus) && (mModalFocusSite != NULL))
  718.     {
  719.         if (SUCCEEDED(mModalFocusSite->QueryInterface(IID_IControl, &controlP)))
  720.         {
  721.             if (controlP->SetFocus(RequestReleaseCommand, ModalFocus) == S_OK)
  722.                 mModalFocusSite = NULL;
  723.             else
  724.                 theResult = E_FAIL;
  725.             
  726.             controlP->Release();
  727.         }
  728.         else
  729.             theResult = E_FAIL;
  730.     }
  731.     
  732.     if ((theResult == S_OK) && (Focus & KeyboardFocus) && (mFocusSite != NULL))
  733.     {
  734.         if (SUCCEEDED(mFocusSite->QueryInterface(IID_IControl, &controlP)))
  735.         {
  736.             if (controlP->SetFocus(RequestReleaseCommand, KeyboardFocus) == S_OK)
  737.                 mFocusSite = NULL;
  738.             else
  739.                 theResult = E_FAIL;
  740.  
  741.             controlP->Release();
  742.         }
  743.         else
  744.             theResult = E_FAIL;
  745.         
  746.         mFocusSite = NULL;
  747.     }
  748.     
  749.     return theResult;
  750. }
  751.  
  752.  
  753. // ---------------------------------------------------------------------------
  754. //        • CControlContainer::RemoveControlIdler
  755. // ---------------------------------------------------------------------------
  756. //    Remove all idlers associated with this control.
  757.  
  758. ErrorCode
  759. CControlContainer::RemoveControlIdler (CControlSite* inSiteP)
  760. {
  761.     ErrorCode        theResult = E_FAIL;
  762.  
  763.     if (mScheduledControlsMap)
  764.     {
  765.         // Find all control/refcon pairs for this control
  766.         LArrayIterator    schedControlIter(*mScheduledControlsMap);
  767.         SchedControlMap    tempMap;
  768.         
  769.         while (schedControlIter.Next(&tempMap))
  770.         {
  771.             if (tempMap.Control == inSiteP)
  772.             {
  773.                 // Tell our container to remove the corresponding idler.
  774.                 theResult = mContainerSiteP->SetIdleTime(RemoveIdler, tempMap.ContainerRefCon);
  775.                 
  776.                 // Remove the record from our list.
  777.                 if (theResult == S_OK)
  778.                     mScheduledControlsMap->RemoveItemsAt(1, schedControlIter.GetCurrentIndex());
  779.             }
  780.         }
  781.     }
  782.     
  783.     return theResult;
  784. }
  785.  
  786.  
  787. // ---------------------------------------------------------------------------
  788. //        • CControlContainer::RemoveRefConIdler
  789. // ---------------------------------------------------------------------------
  790. //    Remove the idler for this control with the specified refcon.
  791.  
  792. ErrorCode
  793. CControlContainer::RemoveRefConIdler (CControlSite* inSiteP, Uint32 inIdleRefCon)
  794. {
  795.     ErrorCode        theResult = E_FAIL;
  796.  
  797.     if (mScheduledControlsMap)
  798.     {
  799.         // Find a record for this control/refcon pair
  800.         LArrayIterator    schedControlIter(*mScheduledControlsMap);
  801.         SchedControlMap    tempMap;
  802.         Boolean            found = false;
  803.         
  804.         while (schedControlIter.Next(&tempMap) && !found)
  805.         {
  806.             // If found, tell our container to remove the corresponding idler.
  807.             if (tempMap.Control == inSiteP && tempMap.ControlRefCon == inIdleRefCon)
  808.             {
  809.                 theResult = mContainerSiteP->SetIdleTime(RemoveIdler, tempMap.ContainerRefCon);
  810.                 found = true; 
  811.  
  812.                 // Remove the record from our list.
  813.                 if (theResult == S_OK)
  814.                     mScheduledControlsMap->RemoveItemsAt(1, schedControlIter.GetCurrentIndex());
  815.             }
  816.         }
  817.     }
  818.     
  819.     return theResult;
  820. }
  821.  
  822.  
  823. // ---------------------------------------------------------------------------
  824. //        • CControlContainer::SetIdleTimeSelf
  825. // ---------------------------------------------------------------------------
  826. //    Add or update the idler information for this control/refcon pair.
  827.  
  828. ErrorCode
  829. CControlContainer::SetIdleTimeSelf (CControlSite* inSiteP, Int32 inWaitTicks, Uint32 inIdleRefCon)
  830. {
  831.     ErrorCode        theResult = E_FAIL;
  832.  
  833.     if (mScheduledControlsMap)
  834.     {
  835.         //    see if there is already a record for this control/refcon pair
  836.         LArrayIterator    schedControlIter(*mScheduledControlsMap);
  837.         SchedControlMap    tempMap;
  838.         Boolean            found = false;
  839.         
  840.         while (schedControlIter.Next(&tempMap) && !found)
  841.         {
  842.             // If so, pass the mapped refcon and the new wait time to the container
  843.             if (tempMap.Control == inSiteP && tempMap.ControlRefCon == inIdleRefCon)
  844.             {
  845.                 theResult = mContainerSiteP->SetIdleTime(inWaitTicks, tempMap.ContainerRefCon);
  846.                 found = true; 
  847.             }
  848.         }
  849.         
  850.         if (!found)
  851.         {
  852.             //    if not, create a new refcon map entry and fill it in
  853.             tempMap.Control = inSiteP;
  854.             tempMap.ControlRefCon = inIdleRefCon;
  855.             tempMap.ContainerRefCon = ++mMapRefCon;
  856.             
  857.             theResult = mContainerSiteP->SetIdleTime(inWaitTicks, tempMap.ContainerRefCon);
  858.             
  859.             if (theResult == S_OK)
  860.             {
  861.                 mScheduledControlsMap->InsertItemsAt(1, 1, &tempMap);
  862.             }
  863.         }
  864.     }
  865.     
  866.     return theResult;
  867. }
  868.  
  869.  
  870. // ---------------------------------------------------------------------------
  871. //        • CControlContainer::TakeFocus
  872. // ---------------------------------------------------------------------------
  873. //    Take the specified foci. If we already have them, advance them to the "next" control.
  874.  
  875. ErrorCode CControlContainer::TakeFocus(FocusCommand Command, FocusSet Focus)
  876. {
  877.     ErrorCode        result = E_FAIL;
  878.     Boolean8        forward = (Command == TakeNextCommand);
  879.     Boolean8        found;
  880.     Boolean8        done;
  881.     ArrayIndexT        index = LArray::index_Bad;
  882.     CControlSite*    siteP;
  883.  
  884.     if (HaveFocus(Focus))
  885.     {
  886.         // Embedded control(s) holds one or more of the requested foci.
  887.         // Find first control to which we should try passing the focus and release 
  888.         // the current holder(s) of the focus.
  889.         index = FirstFocus(Focus, forward);
  890.         ReleaseFocus(Focus);
  891.         if (index == LArray::index_Bad)
  892.         {
  893.             // We can't take the focus.
  894.             result = E_FAIL;
  895.         }
  896.     }
  897.     else
  898.     {
  899.         // We don't have the requested focus.
  900.         // Find first control to which we should try passing the focus.
  901.         if (mLastSiteClicked)
  902.         {
  903.             index = mSiteArrayP->FetchIndexOf(mLastSiteClicked);
  904.         }
  905.         
  906.         if ((index == LArray::index_Bad) && (GetCount() > 0))
  907.         {
  908.             if (Command == TakeNextCommand)
  909.                 index = LArray::index_First;
  910.             else
  911.                 index = LArray::index_Last;
  912.         }
  913.     }
  914.     
  915.     done = false;
  916.     while (index != LArray::index_Bad && !done)
  917.     {
  918.         found = mSiteArrayP->FetchItemAt(index, &siteP);
  919.         if (found && siteP)
  920.         {
  921.             IControl*    controlP;
  922.             
  923.             if (SUCCEEDED(siteP->QueryInterface(IID_IControl, &controlP)))
  924.             {
  925.                 if (controlP->SetFocus(Command, Focus) == S_OK)
  926.                 {
  927.                     FocusTaken(Focus, siteP);
  928.                     controlP->Release();
  929.                     result = S_OK;
  930.                     done = true;
  931.                 }
  932.                 else
  933.                     controlP->Release();
  934.             }
  935.         }
  936.         
  937.         index = NextFocus(forward, index);
  938.     }
  939.     
  940.     return result;
  941. }
  942.  
  943.