/****************************************************************************************

  
		MCListenedLayer.h
		
		Copyright: (c) 2001 Eovia Corp. All rights reserved.
		  
		Author:	del
		Date:	03/24/99

		Revision History

		when		who			what & why
		==========	==========	======================================================
		03/29/99	dsm			added TMCListened<> for other interfaces (ex: IShRasterLayer)
		03/24/99	del			moved TMCListenedLayer from Layer.h in SharedImplmentation
			  
*****************************************************************************************/
#ifndef MCLISTENEDLAYER_H
#define MCLISTENEDLAYER_H

#include "MCCountedPtr.h"
#include "IShRasterLayer.h"
#include "IChangeManagement.h"

struct IChangeListener;

class TMCListenedLayer : public TMCCountedPtr<IShRasterLayer>
{
public:
	TMCListenedLayer(IChangeListener* listener) : TMCCountedPtr<IShRasterLayer>(), fListener(listener) {}
	TMCListenedLayer(IChangeListener* listener, IShRasterLayer* lp) : TMCCountedPtr<IShRasterLayer>(lp), fListener(listener) {RegisterLayer();}
	TMCListenedLayer(IChangeListener* listener, const TMCCountedPtr<IShRasterLayer>& lp) : TMCCountedPtr<IShRasterLayer>(lp), fListener(listener) {RegisterLayer();}
	~TMCListenedLayer() {UnregisterLayer();}

	uint32 Release() {UnregisterLayer(); return TMCCountedPtr<IShRasterLayer>::Release();}
	IShRasterLayer* operator=(IShRasterLayer* lp) {UnregisterLayer(); IShRasterLayer* result = TMCCountedPtr<IShRasterLayer>::operator=(lp); RegisterLayer(); return result;}
	IShRasterLayer* operator=(const TMCCountedPtr<IShRasterLayer>& lp) {UnregisterLayer(); IShRasterLayer* result = TMCCountedPtr<IShRasterLayer>::operator=(lp); RegisterLayer(); return result;}

private:
	void RegisterLayer();
	void UnregisterLayer();

	IChangeListener* fListener;
};

//------------------------------------

template <class T> class TMCListened : public TMCCountedPtr<T>
{
public:
	TMCListened(IChangeListener* listener) : TMCCountedPtr<T>(), fListener(listener) {}
	TMCListened(IChangeListener* listener, T* lp) : TMCCountedPtr<T>(lp), fListener(listener) {RegisterLayer();}
	TMCListened(IChangeListener* listener, const TMCCountedPtr<T>& lp) : TMCCountedPtr<T>(lp), fListener(listener) {RegisterLayer();}
	~TMCListened() {UnregisterLayer();}

	uint32 Release() {UnregisterLayer(); return TMCCountedPtr<T>::Release();}
	T* operator=(T* lp) {UnregisterLayer(); T* result = TMCCountedPtr<T>::operator=(lp); RegisterLayer(); return result;}
	T* operator=(const TMCCountedPtr<T>& lp) {UnregisterLayer(); T* result = TMCCountedPtr<T>::operator=(lp); RegisterLayer(); return result;}

private:
	void RegisterLayer();
	void UnregisterLayer();

	IChangeListener* fListener;
};

template <class T> void TMCListened<T>::RegisterLayer()
{
	TMCCountedPtr<IChangeChannel> changeChannel;
	if (this->fObject != NULL)
	{
		TMCCountedPtr<IShRasterLayer> layer;
		MCCOMErr err = this->fObject->QueryInterface(IID_IShRasterLayer, (void**)&layer);
		if (!MCVerify(err == MC_S_OK)) return;
		layer->GetContentChangeChannel(&changeChannel);
		changeChannel->RegisterListener(&fListener);
		layer->GetPropertyChangeChannel(&changeChannel);
		changeChannel->RegisterListener(&fListener);
	}
}

template <class T> void TMCListened<T>::UnregisterLayer()
{
	TMCCountedPtr<IChangeChannel> changeChannel;
	if (this->fObject != NULL)
	{
		TMCCountedPtr<IShRasterLayer> layer;
		MCCOMErr err = this->fObject->QueryInterface(IID_IShRasterLayer, (void**)&layer);
		if (!MCVerify(err == MC_S_OK)) return;
		layer->GetContentChangeChannel(&changeChannel);
		changeChannel->UnregisterListener(&fListener);
		layer->GetPropertyChangeChannel(&changeChannel);
		changeChannel->UnregisterListener(&fListener);
	}
}

//------------------------------------

class TMCListenedChannelSet
{
public:
	TMCListenedChannelSet();
	~TMCListenedChannelSet();

	void SetChannelList(IShRasterLayer& raster, TChannelID ids[], uint16 channelCount);
	boolean UpdateChannelList();

	uint32 GetChannelSetMask() const {return fChannelSetMask;}

protected:
	TMCCountedPtr<IShRasterLayer> fRasterLayer;
	TChannelID fChannelIDs[32];
	uint16 fChannelCount;
	uint32 fChannelSetMask;
};

#endif