home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-12-20 | 9.5 KB | 386 lines | [TEXT/CWIE] |
- #include "ocheaders.h"
- #include "BDDISPIDs.h"
- #include "CPopupMenuControl.h"
- #include "CPopupMenuTracker.h"
- #include "BDUtils.h"
- #include "FnAssert.h"
- #include "dispatch.h"
- #include <LArray.h>
- #include <LArrayIterator.h>
- #include "CConnectionPoint.h"
- #include "CCPContainer.h"
- #include <iterator.h>
- #include <ctype.h>
- #include <math.h>
- #include <stdio.h>
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Constants
- //
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // class statics
- //
-
- short CPopupMenuControl::gMenuRSRCID = 1000;
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::CPopupMenuControl
- //
-
- CPopupMenuControl::CPopupMenuControl(void)
- {
- mMenuHandle = NULL;
-
- mID[0] = 0;
-
- mIsIdling = false;
-
- #ifdef _DEBUG
- IUnknown* unk;
- this->QueryInterface(IID_IUnknown, (void**) &unk);
- GetObjectName (unk, mThisName);
- #endif
-
- SetOriginatorName("?");
-
- // CBaseEventServer setup
- AddOutGoingInterface(IID_IDidMenuEvents);
- SetUpConnectionPoints();
-
- // CBaseEventClient setup
- AddIncomingInterface(IID_IDoMenuEvents);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::~CPopupMenuControl
- //
-
- CPopupMenuControl::~CPopupMenuControl(void)
- {
- if ( mIsIdling )
- mContainerSiteP->SetIdleTime(RemoveAllIdlers, 0);
-
- if ( mMenuHandle )
- {
- DisposeMenu(mMenuHandle);
- mMenuHandle = NULL;
- }
-
- mID[0] = 0;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CConsoleControl::IObjectWithSite::SetSite
- //
- STDMETHODIMP
- CPopupMenuControl::SetSite(IUnknown* inClientSite)
- {
- CBaseControl::SetSite(inClientSite);
-
- if ( mContainerSiteP )
- mIsIdling = ( mContainerSiteP->SetIdleTime(0, 0) == S_OK );
- }
-
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IControl::Draw
- //
-
- STDMETHODIMP
- CPopupMenuControl::Draw(DrawContext* Context)
- {
- if (Context->DrawAspect != DVASPECT_CONTENT)
- return ResultFromScode(DV_E_DVASPECT);
-
- return ResultFromScode(S_OK);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IControl::DoIdle
- //
-
- STDMETHODIMP
- CPopupMenuControl::DoIdle(THIS_ Uint32 idleRefCon)
- {
- #pragma unused(idleRefCon)
-
- CBaseEventClient::SetUpConnections(mContainerSiteP, mContainerP);
-
- return ResultFromScode(S_OK);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::FireOneEvent
- //
-
- STDMETHODIMP
- CPopupMenuControl::FireOneEvent(REFIID refID, long eventID, IUnknown* eventTarget, PlatformEvent* event)
- {
- #pragma unused(refID, eventTarget)
-
- IDidMenuEvents* target = (IDidMenuEvents*) eventTarget;
- IUnknown* unk;
-
- this->QueryInterface(IID_IUnknown, (void**) &unk);
-
- switch ( eventID )
- {
- case DISPID_CLICK:
- target->Click(unk, event, mOriginatorName, mItemSelected);
- break;
- }
-
- return ResultFromScode(S_OK);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IDoMenuEvents::Popup
- //
-
- STDMETHODIMP
- CPopupMenuControl::Popup(IUnknown* source, PlatformEvent* event)
- {
-
- if ( mMenuHandle )
- {
- char theName[256];
- ::GetObjectName(source, theName);
- SetOriginatorName(theName);
-
- CPopupMenuTracker thePopup(this, mMenuHandle, 0);
- thePopup.TrackMouse(event->where);
- thePopup.GetCurrentItem(&mItemSelected);
- if ( mItemSelected.itemNumber != 0 )
- FireEvent(IID_IDidMenuEvents, DISPID_CLICK, event);
- }
-
- return ResultFromScode(S_OK);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IDoMenuEvents::Clear
- //
-
- STDMETHODIMP
- CPopupMenuControl::Clear(IUnknown* source, PlatformEvent* event)
- {
- if ( mMenuHandle && IsSource(source))
- {
- short nItems = ::CountMItems(mMenuHandle);
- for ( short i = nItems; i >= 1; i-- )
- ::DelMenuItem(mMenuHandle, i);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IDoMenuEvents::RemoveItem
- //
-
- STDMETHODIMP
- CPopupMenuControl::RemoveItem(IUnknown* source, PlatformEvent* event, const CMenuItem & theItem)
- {
- if ( mMenuHandle && IsSource(source))
- {
- short nItems = ::CountMItems(mMenuHandle);
- if ( theItem.itemNumber <= nItems && theItem.itemNumber > 0 )
- ::DelMenuItem(mMenuHandle, theItem.itemNumber);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IDoMenuEvents::AddItem
- //
-
- STDMETHODIMP
- CPopupMenuControl::AddItem(IUnknown* source, PlatformEvent* event, const CMenuItem & theItem)
- {
- if ( mMenuHandle && IsSource(source))
- {
- Str255 itemText;
- strcpy((char *)itemText, theItem.itemText);
- c2pstr((char *)itemText);
-
- // Note: if afterItemNumber is zero, the item gets inserted as the first
- // item. If afterItemNumber is greater than the number of items in
- // the menu, then it gets inserted as the last item.
- short afterItemNumber = theItem.itemNumber - 1;
- ::InsMenuItem(mMenuHandle, itemText, afterItemNumber);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IPersistPropertyBag::Load
- //
-
- STDMETHODIMP
- CPopupMenuControl::Load(IPropertyBag* propertyBag, IErrorLog* errorLog)
- {
- CBaseControl::Load(propertyBag, errorLog);
- CBaseEventClient::Load(propertyBag, errorLog);
-
- char propertyString[Str255BufferLength];
- long i = 0;
-
- // try to load in each property. if we can't get it, then leave
- // things at the default.
-
- char propertyNameString[Str255BufferLength];
-
- mMenuHandle = ::NewMenu(GetMenuRSRCID(), "\p");
-
- // loop through all the menuitem[x] parameters. It's possible there's only one, with no [x]
- strcpy(propertyNameString, MENUITEM_STR);
- if ( ::LoadPropertyString(propertyBag, propertyNameString, propertyString, Str255StringLength, errorLog) )
- AddMenuItem(propertyString);
- else
- {
- for ( i = 0; i <= MAX_NUM_MENU_ITEMS; i++ )
- {
- sprintf(propertyNameString, "%s[%ld]", MENUITEM_STR, i);
- if ( ::LoadPropertyString(propertyBag, propertyNameString, propertyString, Str255StringLength, errorLog) )
- AddMenuItem(propertyString);
- }
- }
-
- ::InsertMenu(mMenuHandle, hierMenu);
-
- // Eventually we may be able to inherit this from CBaseControl, or
- // an as-yet undefined base class that simply loads the ID paramter.
- // When the framework supports GetID instead of GetName in IControl, then
- // mID may change to something else, as well.
- if ( ::LoadPropertyString(propertyBag, "sourceid", propertyString, Str255StringLength, errorLog) )
- {
- strcpy((char*)(&mID[1]), propertyString);
- mID[0] = strlen(propertyString);
- }
-
- return ResultFromScode(S_OK);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::IUnknown::QueryInterface
- //
- // Returns a pointer to the specified interface on a component to which a
- // client currently holds an interface pointer.
- //
-
- STDMETHODIMP
- CPopupMenuControl::QueryInterface(REFIID refID, void** obj)
- {
- HRESULT result = E_NOINTERFACE;
-
- // --- This is temporary for beta 2 ---
- //
- // Since we're checking for IID_IConnectionPointContainer in
- // CBaseEventServer, we want to delegate to it first if that's
- // the refID -- otherwise CBaseControl will catch it, which
- // will get us a different list of connection points.
- // In all other cases, we'll delegate to CBaseControl first.
- //
- // This ugliness will disappear with a future release of the
- // framework.
-
- if ( refID == IID_IConnectionPointContainer )
- {
- result = CBaseEventServer::QueryInterface(refID, obj);
- if ( result == S_OK )
- goto labelExit;
-
- result = CBaseEventClient::QueryInterface(refID, obj);
- if ( result == S_OK )
- goto labelExit;
-
- result = CBaseControl::QueryInterface(refID, obj);
- if ( result == S_OK )
- goto labelExit;
- }
- else
- {
- result = CBaseControl::QueryInterface(refID, obj);
- if ( result == S_OK )
- goto labelExit;
-
- result = CBaseEventServer::QueryInterface(refID, obj);
- if ( result == S_OK )
- goto labelExit;
-
- result = CBaseEventClient::QueryInterface(refID, obj);
- if ( result == S_OK )
- goto labelExit;
-
- // finally, check for IDoMenuEvents
-
- {
- void* pv = nil;
-
- if (refID == IID_IDoMenuEvents)
- pv = (void*)(IDoMenuEvents*) this;
-
- *obj = pv;
-
- if ( pv )
- {
- ((IUnknown*) pv)->AddRef();
- result = S_OK;
- }
-
- goto labelExit;
- }
- }
-
- labelExit:
- return result;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::GetMenuRSRCID
- //
- short CPopupMenuControl::GetMenuRSRCID(void)
- {
- // MMF?
- // the purpose of this method is to attempt to generate a unique identifier
- // for each menu resource. However, we're still seeing strange behavior
- // when it comes to resources (the wrong menu appearing the first time a
- // control is clicked, for instace). Perhaps this method will dissappear
- // when we solve those problems.
-
- return (++CPopupMenuControl::gMenuRSRCID);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::SetOriginatorName
- //
- void CPopupMenuControl::SetOriginatorName(char * theName)
- {
- strcpy(mOriginatorName, theName);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // CPopupMenuControl::AddMenuItem
- //
- void CPopupMenuControl::AddMenuItem(char * itemName)
- {
- c2pstr(itemName);
- ::AppendMenu(mMenuHandle, (StringPtr)itemName);
- p2cstr((StringPtr)itemName);
- }
-