|
|
//+-----------------------------------------------------------------------
//
// TDC / STD Notifications
// Copyright (C) Microsoft Corporation, 1996, 1997
//
// File: Notify.cpp
//
// Contents: Implementation of the CEventBroker class.
// This class translates internal TDC / STD events into
// appropriate notifications for the external world.
//
//------------------------------------------------------------------------
#include "stdafx.h"
#include <simpdata.h>
#include "TDC.h"
#include <MLang.h>
#include "Notify.h"
#include "TDCParse.h"
#include "TDCArr.h"
#include "SimpData.h"
#include "TDCIds.h"
#include "TDCCtl.h"
//------------------------------------------------------------------------
//
// Method: CEventBroker()
//
// Synopsis: Class constructor
//
// Arguments: None
//
//------------------------------------------------------------------------
CEventBroker::CEventBroker(CTDCCtl *pReadyStateControl) { m_cRef = 1; m_pSTDEvents = NULL; // ;begin_internal
m_pDATASRCListener = NULL; // ;end_internal
m_pDataSourceListener = NULL; m_pBSC = NULL;
// Can't AddRef this control, since it has a ref on this object;
// would lead to circular refs & zombie objects.
//
m_pReadyStateControl = pReadyStateControl;
// When we're born, we'd better be born READYSTATE_COMPLETE.
// If and when a query starts, we can go READYSTATE_LOADED.
m_lReadyState = READYSTATE_COMPLETE; }
CEventBroker::~CEventBroker() {
SetDataSourceListener(NULL); // ;begin_internal
SetDATASRCListener(NULL); // ;end_internal
SetSTDEvents(NULL); }
//+-----------------------------------------------------------------------
//
// Method: AddRef()
//
// Synopsis: Implements part of the standard IUnknown COM interface.
// (Adds a reference to this COM object)
//
// Arguments: None
//
// Returns: Number of references to this COM object.
//
//+-----------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEventBroker::AddRef () { return ++m_cRef; }
//+-----------------------------------------------------------------------
//
// Method: Release()
//
// Synopsis: Implements part of the standard IUnknown COM interface.
// (Removes a reference to this COM object)
//
// Arguments: None
//
// Returns: Number of remaining references to this COM object.
// 0 if the COM object is no longer referenced.
//
//+-----------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEventBroker::Release () { ULONG retval;
retval = --m_cRef;
if (m_cRef == 0) { m_cRef = 0xffff; delete this; }
return retval; }
//------------------------------------------------------------------------
//
// Method: GetReadyState()
//
// Synopsis: Returns the current ReadyState in the supplied pointer.
//
// Arguments: plReadyState Pointer to space to hold ReadyState result
//
// Returns: S_OK indicating success.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::GetReadyState(LONG *plReadyState) { *plReadyState = m_lReadyState; return S_OK; }
//------------------------------------------------------------------------
//
// Method: UpdateReadySTate()
//
// Synopsis: Update our ReadyState and FireOnChanged iif it changed
//
// Arguments: lReadyState new ReadyState
//
// Returns: S_OK indicating success.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::UpdateReadyState(LONG lReadyState) { // If we're actually stopping something, then fire READYSTATE_COMPLETE
if (m_lReadyState != lReadyState) { m_lReadyState = lReadyState; if (m_pReadyStateControl != NULL) { m_pReadyStateControl->FireOnChanged(DISPID_READYSTATE); m_pReadyStateControl->FireOnReadyStateChanged(); } }
return S_OK; }
//------------------------------------------------------------------------
//
// Method: SetDataSourceListener()
//
// Synopsis: Sets the COM object which should receive DATASRC
// notification events.
//
// Arguments: pDataSourceLIstener Pointer to COM object to receive notification
// events, or NULL if no notifications to be sent.
//
// Returns: S_OK indicating success.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::SetDataSourceListener(DataSourceListener *pDataSourceListener) { // If we've changed/reset the data source listener, make sure we don't
// think we've fired dataMemberChanged on it yet.
ClearInterface(&m_pDataSourceListener);
if (pDataSourceListener != NULL) { m_pDataSourceListener = pDataSourceListener; m_pDataSourceListener->AddRef(); } return S_OK; }
// ;begin_internal
//------------------------------------------------------------------------
//
// Method: SetDATASRCListener()
//
// Synopsis: Sets the COM object which should receive DATASRC
// notification events.
//
// Arguments: pDATASRCLIstener Pointer to COM object to receive notification
// events, or NULL if no notifications to be sent.
//
// Returns: S_OK indicating success.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::SetDATASRCListener(DATASRCListener *pDATASRCListener) { // If we've changed/reset the data source listener, make sure we don't
// think we've fired dataMemberChanged on it yet.
ClearInterface(&m_pDATASRCListener);
if (pDATASRCListener != NULL) { m_pDATASRCListener = pDATASRCListener; m_pDATASRCListener->AddRef(); } return S_OK; } // ;end_internal
//------------------------------------------------------------------------
//
// Method: SetSTDEvents()
//
// Synopsis: Sets the COM object which should receive DATASRC
// notification events.
//
// Arguments: pSTDEvents Pointer to COM object to receive notification
// events, or NULL if no notifications to be sent.
//
// Returns: S_OK indicating success.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::SetSTDEvents(OLEDBSimpleProviderListener *pSTDEvents) { ClearInterface(&m_pSTDEvents);
if (pSTDEvents != NULL) { m_pSTDEvents = pSTDEvents; m_pSTDEvents->AddRef(); } return S_OK; }
//------------------------------------------------------------------------
//
// Method: aboutToChangeCell()
//
// Synopsis: Notifies anyone who wants to know that a particular cell
// is about to change.
//
// Arguments: iRow Row number of the cell that has changed.
// iCol Column number of the cell that has changed.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::aboutToChangeCell(LONG iRow, LONG iCol) { HRESULT hr = S_OK;
_ASSERT(iRow >= 0); _ASSERT(iCol >= 1); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->aboutToChangeCell(iRow, iCol); return hr; }
//------------------------------------------------------------------------
//
// Method: CellChanged()
//
// Synopsis: Notifies anyone who wants to know that a particular cell
// has changed.
//
// Arguments: iRow Row number of the cell that has changed.
// iCol Column number of the cell that has changed.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::cellChanged(LONG iRow, LONG iCol) { HRESULT hr = S_OK;
_ASSERT(iRow >= 0); _ASSERT(iCol >= 1); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->cellChanged(iRow, iCol); return hr; }
//------------------------------------------------------------------------
//
// Method: RowChanged()
//
// Synopsis: Notifies anyone who wants to know that a particular row
// has changed.
//
// Arguments: iRow Number of the row that has changed.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::RowChanged(LONG iRow) { HRESULT hr = S_OK;
_ASSERT(iRow >= 0); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->cellChanged(iRow, -1); return hr; }
//------------------------------------------------------------------------
//
// Method: ColChanged()
//
// Synopsis: Notifies anyone who wants to know that a particular column
// has changed.
//
// Arguments: iCol Number of the column that has changed.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::ColChanged(LONG iCol) { HRESULT hr = S_OK;
_ASSERT(iCol > 0); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->cellChanged(-1, iCol); return hr; }
//------------------------------------------------------------------------
//
// Method: aboutToDeleteRows()
//
// Synopsis: Notifies anyone who wants to know that a some rows
// have been deleted.
//
// Arguments: iRowStart Number of row on which deletion started.
// iRowCount Number of rows deleted.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::aboutToDeleteRows(LONG iRowStart, LONG iRowCount) { HRESULT hr = S_OK;
_ASSERT(iRowStart >= 0); _ASSERT(iRowCount > 0); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->aboutToDeleteRows(iRowStart, iRowCount); return hr; }
//------------------------------------------------------------------------
//
// Method: deletedRows()
//
// Synopsis: Notifies anyone who wants to know that a some rows
// have been deleted.
//
// Arguments: iRowStart Number of row on which deletion started.
// iRowCount Number of rows deleted.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::deletedRows(LONG iRowStart, LONG iRowCount) { HRESULT hr = S_OK;
_ASSERT(iRowStart >= 0); _ASSERT(iRowCount > 0); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->deletedRows(iRowStart, iRowCount); return hr; }
//------------------------------------------------------------------------
//
// Method: aboutToInsertRows()
//
// Synopsis: Notifies anyone who wants to know that a some rows
// have been inserted.
//
// Arguments: iRowStart Number of row on which insertion started.
// iRowCount Number of rows inserted.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::aboutToInsertRows(LONG iRowStart, LONG iRowCount) { HRESULT hr = S_OK;
_ASSERT(iRowStart >= 0); _ASSERT(iRowCount > 0); if (m_pSTDEvents != NULL) m_pSTDEvents->aboutToInsertRows(iRowStart, iRowCount); return hr; }
//------------------------------------------------------------------------
//
// Method: insertedRows()
//
// Synopsis: Notifies anyone who wants to know that a some rows
// have been inserted.
//
// Arguments: iRowStart Number of row on which insertion started.
// iRowCount Number of rows inserted.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::insertedRows(LONG iRowStart, LONG iRowCount) { HRESULT hr = S_OK;
_ASSERT(iRowStart >= 0); _ASSERT(iRowCount > 0); if (m_pSTDEvents != NULL) m_pSTDEvents->insertedRows(iRowStart, iRowCount); return hr; }
//------------------------------------------------------------------------
//
// Method: rowsAvailable()
//
// Synopsis: Notifies anyone who wants to know that a some rows
// have arrived. Although this is very similar to insertedRows
// we want to preserve the distinction between rows that
// arrive on the wire and an insert operation that might be
// performed while some data is still downloading.
//
// Arguments: iRowStart Number of row on which insertion started.
// iRowCount Number of rows inserted.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::rowsAvailable(LONG iRowStart, LONG iRowCount) { HRESULT hr = S_OK;
_ASSERT(iRowStart >= 0); _ASSERT(iRowCount > 0); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->rowsAvailable(iRowStart, iRowCount); return hr; }
// ;begin_internal
#ifdef NEVER
//------------------------------------------------------------------------
//
// Method: DeletedCols()
//
// Synopsis: Notifies anyone who wants to know that a some columns
// have been deleted.
//
// Arguments: iColStart Number of column on which deletion started.
// iColCount Number of columns deleted.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::DeletedCols(LONG iColStart, LONG iColCount) { HRESULT hr = S_OK;
_ASSERT(iColStart > 0); _ASSERT(iColCount > 0); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->DeletedColumns(iColStart, iColCount); return hr; }
//------------------------------------------------------------------------
//
// Method: InsertedCols()
//
// Synopsis: Notifies anyone who wants to know that a some columns
// have been inserted.
//
// Arguments: iColStart Number of column on which insertion started.
// iColCount Number of columns inserted.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::InsertedCols(LONG iColStart, LONG iColCount) { HRESULT hr = S_OK;
_ASSERT(iColStart > 0); _ASSERT(iColCount > 0); if (m_pSTDEvents != NULL) hr = m_pSTDEvents->InsertedColumns(iColStart, iColCount); return hr; } #endif
// ;end_internal
//------------------------------------------------------------------------
//
// Method: STDLoadStarted()
//
// Synopsis: Notifies anyone who wants to know that the STD control
// has begun loading its data.
//
// Arguments: pBSC Pointer to data-retrieval object.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::STDLoadStarted(CComObject<CMyBindStatusCallback<CTDCCtl> > *pBSC, boolean fAppending) { HRESULT hr = S_OK;
m_pBSC = pBSC; return hr; }
//------------------------------------------------------------------------
//
// Method: STDLoadCompleted()
//
// Synopsis: Notifies anyone who wants to know that the STD control
// has loaded all of its data.
// Note this function should be idempotent -- i.e. it may be
// called more than once in synchronous cases, once when the
// transfer actually completes, and again as soon as the event
// sink is actually hooked up in order to fire the transferComplete
// event.
//
// Arguments: None.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::STDLoadCompleted() { HRESULT hr = S_OK;
m_pBSC = NULL; if (m_pSTDEvents != NULL) hr = m_pSTDEvents->transferComplete(OSPXFER_COMPLETE); UpdateReadyState(READYSTATE_COMPLETE); return hr; }
//------------------------------------------------------------------------
//
// Method: STDLoadStopped()
//
// Synopsis: Notifies anyone who wants to know that the STD control
// has aborted the data load operation.
//
// Arguments: OSPXFER giving reason for stop
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::STDLoadStopped() { HRESULT hr = S_OK;
if (m_pBSC && m_pBSC->m_spBinding) { hr = m_pBSC->m_spBinding->Abort(); m_pBSC = NULL; }
// Right now, any error results in not returning an STD object,
// therefore we should not fire transfer complete.
if (m_pSTDEvents) hr = m_pSTDEvents->transferComplete(OSPXFER_ABORT);
UpdateReadyState(READYSTATE_COMPLETE);
return hr; }
//------------------------------------------------------------------------
//
// Method: STDLoadedHeader()
//
// Synopsis: Notifies anyone who wants to know that the STD control
// has loaded its header row.
//
// Arguments: None.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::STDLoadedHeader() { HRESULT hr = S_OK;
hr = STDDataSetChanged();
UpdateReadyState(READYSTATE_INTERACTIVE); return hr; }
//------------------------------------------------------------------------
//
// Method: STDSortFilterCompleted()
//
// Synopsis: Notifies anyone who wants to know that the STD control
// has refiltered / resorted its data.
//
// Returns: S_OK upon success.
// Error code upon failure.
//
//------------------------------------------------------------------------
STDMETHODIMP CEventBroker::STDDataSetChanged() { HRESULT hr = S_OK;
if (m_pDataSourceListener != NULL) hr = m_pDataSourceListener->dataMemberChanged(NULL); // ;begin_internal
if (m_pDATASRCListener != NULL) hr = m_pDATASRCListener->datasrcChanged(NULL, TRUE); // ;end_internal
return hr; }
|