/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sfx2_ctrlitem.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2006/10/27 19:08:50 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SFXITEMPOOL_HXX //autogen
#include <svtools/itempool.hxx>
#endif
#pragma hdrstop

#include "ctrlitem.hxx"
#include "dispatch.hxx"
#include "msgpool.hxx"

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#include "statcach.hxx"
#include "viewfrm.hxx"
namespace binfilter {

//====================================================================

/*N*/ DBG_NAME(SfxControllerItem)

//--------------------------------------------------------------------
#ifdef DBG_UTIL

/*N*/ void SfxControllerItem::CheckConfigure_Impl( ULONG nType )
/*N*/ {
/*N*/ 	// echter Slot? (also kein Separator etc.)
/*N*/ 	if ( !nId )
/*N*/ 		return;
/*N*/ 
/*N*/ 	// ist die Id "uberhaupt in 'nType' konfigurierbar?
/*N*/ 	const SfxSlot *pSlot = SFX_SLOTPOOL().GetSlot(nId);
/*N*/ 	DBG_ASSERTWARNING( pSlot, "SfxControllerItem: binding not existing slot" );
/*N*/ 	if ( pSlot && !pSlot->IsMode(nType) )
/*N*/ 	{
/*?*/ 		DBG_WARNING( "SfxControllerItem: slot without ...Config-flag" );
/*?*/ 		DbgOutf( "SfxControllerItem: Config-flag missing at SID %5d",
/*?*/ 				 pSlot->GetSlotId() );
/*N*/ 	}
/*N*/ }

#endif

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

// returns the next registered SfxControllerItem with the same id

/*N*/ SfxControllerItem* SfxControllerItem::GetItemLink()
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ 	return pNext == this ? 0 : pNext;
/*N*/ }

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

// returns TRUE if this binding is really bound to a function

/*N*/ BOOL SfxControllerItem::IsBound() const
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ 	return pNext != this;
/*N*/ }

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

// returns the associated function-id or 0 if none

// USHORT SfxControllerItem::GetId() const;

//====================================================================

// registeres with the id at the bindings

/*N*/ void SfxControllerItem::Bind( USHORT nNewId, SfxBindings *pBindinx )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ 	DBG_ASSERT(pBindings || pBindinx, "Keine Bindings");
/*N*/ 
/*N*/ 	if ( IsBound() ) {
/*?*/ 		DBG_ASSERT(pBindings, "Keine Bindings");
/*?*/ 		pBindings->Release(*this);
/*N*/ 	}
/*N*/ 
/*N*/ 	nId = nNewId;
/*N*/ 	pNext = 0;
/*N*/ 
/*N*/ 	if (pBindinx)
/*N*/ 		pBindings = pBindinx;
/*N*/ 	pBindings->Register(*this);
/*N*/ }


//====================================================================

/*N*/ void SfxControllerItem::UnBind()

/*	[Beschreibung]

	"ost die Verbindung dieses SfxControllerItems mit der SfxBindings-Instanz,
	an der es zur Zeit gebunden ist. Ab diesem Zeitpunkt erh"alt es keine
	Statusbenachrichtigungen (<SfxControllerItem::StateChented()>) mehr.


	[Querverweise]

	<SfxControllerItem::ReBind()>
	<SfxControllerItem::ClearCache()>
*/
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ 	DBG_ASSERT(pBindings, "Keine Bindings");
/*N*/ 	DBG_ASSERT( IsBound(), "unbindings unbound SfxControllerItem" );
/*N*/ 
/*N*/ 	pBindings->Release(*this);
/*N*/ 	pNext = this;
/*N*/ }

//====================================================================

/*N*/ void SfxControllerItem::ReBind()

/*	[Beschreibung]

	Binded dieses SfxControllerItem wieder an die SfxBindings-Instanz,
	an der es zuletzt gebunden war. Ab diesem Zeitpunkt erh"alt es wieder
	Statusbenachrichtigungen (<SfxControllerItem::StateChented()>).


	[Querverweise]

	<SfxControllerItem::UnBind()>
	<SfxControllerItem::ClearCache()>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ 	DBG_ASSERT(pBindings, "Keine Bindings");
/*N*/ 	DBG_ASSERT( !IsBound(), "bindings rebound SfxControllerItem" );
/*N*/ 
/*N*/ 	pBindings->Register(*this);
/*N*/ }

//====================================================================

/*?*/ void SfxControllerItem::UpdateSlot()

/*	[Beschreibung]

	Holt den Status 'hart' neu.

	[Querverweise]

	<SfxControllerItem::ClearCache()>
*/

/*?*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
/*?*/ }

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

/*?*/ void SfxControllerItem::ClearCache()

/*	[Beschreibung]

	"oscht den Status-Cache f"ur dieses SfxControllerItem. D.h. beim
	n"achsten Status-Update wird das <SfxPoolItem> auf jeden Fall geschickt,
	auch wenn zuvor dasselbe geschickt wurde. Dies wird ben"otigt, wenn
	ein Controller umgeschaltet werden kann und sich diesen Status
	selbst merkt.


	[Beispiel]

	Der Kombi-Controller f"ur das Einstellen des Fl"achentyps und der
	konkreten Auspr"agung (Farbe blau oder Schraffur X) kann im Typ
	umgestellt werden, wird jedoch dann bei der n"achsten Selektion
	wieder benachrichtigt, auch wenn es dieselben Daten sind.


	[Querverweise]

	<SfxControllerItem::UnBind()>
	<SfxControllerItem::ReBind()>
*/


/*?*/ {
/*?*/ 	DBG_MEMTEST();
/*?*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*?*/ 	DBG_ASSERT(pBindings, "Keine Bindings");
/*?*/ 
/*?*/ 	pBindings->ClearCache_Impl( GetId() );
/*?*/ }

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

// replaces the successor in the list of bindings of the same id

/*N*/ SfxControllerItem* SfxControllerItem::ChangeItemLink( SfxControllerItem* pNewLink )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ 	SfxControllerItem* pOldLink = pNext;
/*N*/ 	pNext = pNewLink;
/*N*/ 	return pOldLink == this ? 0 : pOldLink;
/*N*/ }

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

// changes the id of unbound functions (e.g. for sub-menu-ids)

/*N*/ void SfxControllerItem::SetId( USHORT nItemId )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ 	DBG_ASSERT( !IsBound(), "changing id of bound binding" );
/*N*/ 	nId = nItemId;
/*N*/ }
/*?*/ 
//--------------------------------------------------------------------

/*?*/ SvStream& operator<<( SvStream& rStream, const SfxControllerItem& rFunc )
/*?*/ {
/*?*/ 	DBG_MEMTEST();
/*?*/ 	SFX_SLOTPOOL().StoreId( rStream, rFunc.nId );
/*?*/ 	return rStream;
/*?*/ }

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

/*?*/ SvStream& operator>>( SvStream& rStream, SfxControllerItem& rFunc )
/*?*/ {
/*?*/ 	DBG_MEMTEST();
/*?*/ 	USHORT nId;
/*?*/ 	SFX_SLOTPOOL().LoadId( rStream, nId );
/*?*/ 	rFunc.Bind(nId);
/*?*/ 	return rStream;
/*?*/ }

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

// creates a atomic item for a controller  without registration

/*N*/ SfxControllerItem::SfxControllerItem():
/*N*/ 	nId(0),
/*N*/ 	pNext(this),
/*N*/ 	pBindings(0)
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CTOR(SfxControllerItem, 0);
/*N*/ }

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

// creates a representation of the function nId and registeres it

/*N*/ SfxControllerItem::SfxControllerItem( USHORT nId, SfxBindings &rBindings ):
/*N*/ 	nId(nId),
/*N*/ 	pNext(this),
/*N*/ 	pBindings(&rBindings)
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CTOR(SfxControllerItem, 0);
/*N*/ 	Bind(nId, &rBindings);
/*N*/ }

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

// unregisteres the item in the bindings

/*N*/ SfxControllerItem::~SfxControllerItem()
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	if ( IsBound() )
/*N*/ 		pBindings->Release(*this);
/*N*/ 	DBG_DTOR(SfxControllerItem, 0);
/*N*/ }

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

/*N*/ void SfxControllerItem::StateChanged
/*N*/ (
/*N*/ 	USHORT				nSID,		// <SID> des ausl"osenden Slot
/*N*/ 	SfxItemState		eState, 	// <SfxItemState> von 'pState'
/*N*/ 	const SfxPoolItem*	pState		// Slot-Status, ggf. 0 oder IsInvalidItem()
/*N*/ )

/*	[Beschreibung]

	Diese virtuelle Methode wird vom SFx gerufen, um <SfxControllerItem>s
	dar"uber zu benachrichtigen, da\s sich der Status des Slots 'nSID'
	ge"andert hat. Der neue Wert sowie der von diesem Wert ermittelte
	Status wird als 'pState' bzw. 'eState' mitgegeben.

	Der Status eines Slots kann sich "andern, wenn z.B. das MDI-Fenster
	gewechselt wird oder der Slot explizit mit <SfxBindings::Invalidate()>
	invalidiert wurde.

	Achtung! Die Methode wird nicht gerufen, wenn der Slot ung"ultig wurde,
	danach jedoch wieder denselben Wert angenommen hat.

	Diese Basisklasse braucht nicht gerufen zu werden, weitere Zwischenstufen
	jedoch (z.B. <SfxToolboxControl>) sollten gerufen werden.
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ }

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

/*N*/ void SfxControllerItem::DeleteFloatingWindow()
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_CHKTHIS(SfxControllerItem, 0);
/*N*/ }

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

/*N*/ void SfxStatusForwarder::StateChanged
/*N*/ (
/*N*/ 	USHORT				nSID,		// <SID> des ausl"osenden Slot
/*N*/ 	SfxItemState		eState, 	// <SfxItemState> von 'pState'
/*N*/ 	const SfxPoolItem*	pState		// Slot-Status, ggf. 0 oder IsInvalidItem()
/*N*/ )
/*N*/ 
/*N*/ {
/*N*/ 	pMaster->StateChanged( nSID, eState, pState );
/*N*/ }

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

/*N*/ SfxStatusForwarder::SfxStatusForwarder(
/*N*/ 			USHORT              nSlotId,
/*N*/ 			SfxControllerItem&  rMaster ):
/*N*/ 	SfxControllerItem( nSlotId, rMaster.GetBindings() ),
/*N*/ 	pMaster( &rMaster )
/*N*/ {
/*N*/ }

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

/*N*/ SfxItemState SfxControllerItem::GetItemState
/*N*/ (
	const SfxPoolItem* pState 	/* 	Pointer auf das <SfxPoolItem>, dessen
									Status erfragt werden soll. */
/*N*/ )

/*	[Beschreibung]

	Statische Methode zum Ermitteln des Status des SfxPoolItem-Pointers,
	in der Methode <SfxControllerItem::StateChanged(const SfxPoolItem*)>
	zu verwenden.

	[R"uckgabewert]

	SfxItemState		SFX_ITEM_UNKNOWN
						Enabled, aber keine weitere Statusinformation
						verf"ugbar. Typisch f"ur <Slot>s, die allenfalls
						zeitweise disabled sind, aber ihre Darstellung sonst
						nicht "andern.

						SFX_ITEM_DISABLED
						Disabled und keine weiter Statusinformation
						verf"ugbar. Alle anderen ggf. angezeigten Werte sollten
						auf den Default zur"uckgesetzt werden.

						SFX_ITEM_DONTCARE
						Enabled aber es waren nur uneindeutige Werte
						verf"ugbar (also keine, die abgefragt werden k"onnen).

						SFX_ITEM_AVAILABLE
						Enabled und mit verf"ugbarem Wert, der von 'pState'
						erfragbar ist. Der Typ ist dabei im gesamten
						Programm eindeutig und durch den Slot festgelegt.
*/

/*N*/ {
/*N*/ 	return !pState
/*N*/ 				? SFX_ITEM_DISABLED
/*N*/ 				: IsInvalidItem(pState)
/*N*/ 					? SFX_ITEM_DONTCARE
/*N*/ 					: pState->ISA(SfxVoidItem) && !pState->Which()
/*N*/ 						? SFX_ITEM_UNKNOWN
/*N*/ 						: SFX_ITEM_AVAILABLE;
/*N*/ }

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

/*N*/ SfxMapUnit SfxControllerItem::GetCoreMetric() const

/*	[Beschreibung]

	Holt vom zust"andigen Pool die Ma\seinheit ab, in der das Status-Item
	vorliegt.
*/

/*N*/ {
/*N*/ 	SfxStateCache *pCache = pBindings->GetStateCache( nId );
/*N*/ 	SfxDispatcher *pDispat = pBindings->GetDispatcher_Impl();
/*N*/ 
/*N*/     if ( !pDispat )
/*N*/     {
/*?*/         SfxViewFrame* pViewFrame = SfxViewFrame::Current();
/*?*/         if ( !pViewFrame )
/*?*/             SfxViewFrame::GetFirst();
/*?*/         if ( pViewFrame )
/*?*/             pDispat = pViewFrame->GetDispatcher();
/*N*/     }
/*N*/ 
/*N*/     if ( pDispat && pCache )
/*N*/     {
/*N*/         const SfxSlotServer *pServer = pCache->GetSlotServer( *pDispat );
/*N*/         if ( pServer )
/*N*/         {
/*N*/             SfxShell *pSh = pDispat->GetShell( pServer->GetShellLevel() );
/*N*/             SfxItemPool &rPool = pSh->GetPool();
/*N*/             USHORT nWhich = rPool.GetWhich( nId );
/*N*/             return rPool.GetMetric( nWhich );
/*N*/         }
/*N*/     }
/*N*/ 
/*N*/     DBG_WARNING( "W1: Can not find ItemPool!" );
/*N*/     return SFX_MAPUNIT_100TH_MM;
/*N*/ }

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

#ifdef WNT
#pragma optimize("g",off)
#endif


}
